μ»΄νμΌ μμ νμ
μ 체ν¬νλ κΈ°λ₯
Copy // μ λ€λ¦ ν΄λμ€(= μ λ€λ¦ νμ
)
class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
class Main {
public static void main(String[] args) {
Box<String> box = new Box<String>();
box.set("Hello");
String str = box.get();
}
}
μμ²λΌ μ μΈλ ν΄λμ€λ₯Ό μ λ€λ¦ ν΄λμ€(μΈν°νμ΄μ€)λΌκ³ νλ©°, λμ ν΅νμ΄ μ λ€λ¦ νμ
(Generic Type)μ΄λΌκ³ νλ€.
μ λ€λ¦μ μ¬μ©λλ μ©μ΄
μ λ€λ¦ νμ
μ μ¬μ©λλ μ©μ΄
Parameterized type(맀κ°λ³μν νμ
)
Actual type parameter(μ€μ νμ
맀κ°λ³μ)
Generic type(μ λ€λ¦ νμ
)
Formal type parameter(μ κ· νμ
맀κ°λ³μ)
Unbounded wildcard type(λΉνμ μ μμΌλμΉ΄λ νμ
)
Bounded type parameter(νμ μ νμ
맀κ°λ³μ)
Recursive type bound(μ¬κ·μ νμ
νμ )
<T extends Comparable<T>>
Bounded wildcard type(νμ μ μμΌλμΉ΄λ νμ
)
Generic method(μ λ€λ¦ λ©μλ)
static <E> List<E> asList(E[] a)
type token(νμ
ν ν°) or type literal(νμ
리ν°λ΄)
μ λ€λ¦μ μ¬μ©λλ νμ νμ
λ³μ(κ°μ μ¬ν X)
μ λ€λ¦μ μ ν
λͺ¨λ κ°μ²΄μ λν΄ λμΌνκ² λμν΄μΌνλ static
λ©μλλ static
νλμμλ νμ
λ³μλ₯Ό μ¬μ©ν μ μλ€.
static
λ©€λ²λ μΈμ€ν΄μ€ μμ±κ³Ό μκ΄μμ΄ μ¬μ©ν μ μκΈ° λλ¬Έμ, λμ
λ νμ
μ μ’
λ₯μ κ΄κ³μμ΄ λμΌν΄μΌνκΈ° λλ¬Έμ΄λ€.
Copy class Box<T> {
static T t; // μ»΄νμΌ μλ¬
static int compare(T t1, T t2) { // μ»΄νμΌ μλ¬
//...
}
}
κ·Έλ¦¬κ³ μ λ€λ¦ λ°°μ΄ νμ
μ μ°Έμ‘°λ³μλ₯Ό μ μΈνλ κ²μ κ°λ₯νμ§λ§ μ λ€λ¦ νμ
μ λ°°μ΄μ μμ±νλ κ²μ λΆκ°λ₯νλ€.
Copy class Box<T> {
T[] itemArr; // κ°λ₯
T[] toArray() { // λΆκ°λ₯
return new T[10]; // μ»΄νμΌ μλ¬
}
}
new μ°μ°μλ μ»΄νμΌ μμ μ νμ
Tκ° μ νν μμμΌ νλλ°, μμ± μμ μλ νμ
Tκ° λ¬΄μμΈμ§ μ μ μκΈ° λλ¬Έμ λΆκ°λ₯νλ€.
λ§μ½ λ°°μ΄μ μμ±νκ³ μΆλ€λ©΄ μλμ κ°μ΄ 볡μ¬λ₯Ό ν λ€ νλ³ν νμ¬ μ¬μ©νλ λ°©λ²μ΄ μλ€.
Copy class Box<T> {
T[] itemArr;
T[] toArray() {
return (T[]) Arrays.copyOf(itemArr, itemArr.length);
}
}
μ λ€λ¦ ν΄λμ€ μμ±κ³Ό μ¬μ©
Copy class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
public class Main {
public static void main(String[] args) {
Box<Apple> appleBox = new Box<Apple>();
Box<Apple> Box = new Box<>(); // νμ
μΆλ‘ μ μν΄ μλ΅ κ°λ₯
Box<Apple> grapeBox = new Box<Grape>(); // μ»΄νμΌ μλ¬
}
}
μ λ€λ¦ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό μμ±ν λλ νμ
λ³μμ λμ
ν μ€μ νμ
μ μ§μ ν΄μΌ νλ€.
μ°Έμ‘° λ³μμ μμ±μμ λμ
λ νμ
μ΄ μΌμΉν΄μΌνλ©°, μΌμΉνμ§ μμΌλ©΄ μ»΄νμΌ μλ¬κ° λ°μνλ€.
νμ
μ μλ΅νλ©΄ μ»΄νμΌλ¬κ° μ½λμμ νμ
μ 보λ₯Ό μΆλ‘ νκ³ μλμΌλ‘ μ€μ ν΄μ€λ€.(= νμ
μΆλ‘ )
μ νλ μ λ€λ¦ ν΄λμ€
μ λ€λ¦ ν΄λμ€μ νμ
λ³μμλ μ΄λ€ νμ
μ΄λΌλ λμ
λ μ μμ§λ§, extends
μ &
λ₯Ό μ¬μ©ν΄ νΉμ νμ
λ§ λμ
λλλ‘ μ νν μ μλ€.
Copy interface Eatable {
}
class Box<T extends Fruit & Eatable> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
class Fruit implements Eatable {
public String toString() {
return "Fruit";
}
}
class Apple extends Fruit {
public String toString() {
return "Apple";
}
}
class Toy {
public String toString() {
return "Toy";
}
}
public class Main {
public static void main(String[] args) {
Box<Fruit> fruitBox = new Box<Fruit>();
Box<Apple> appleBox = new Box<Apple>();
Box<Toy> toyBox = new Box<Toy>(); // μ»΄νμΌ μλ¬
fruitBox.set(new Fruit());
fruitBox.set(new Apple());
appleBox.set(new Apple());
toyBox.set(new Toy()); // μ»΄νμΌ μλ¬
}
}
μμΌλ μΉ΄λ
Copy class Juicer {
static Juice makeJuice(FruitBox<Fruit> box) {
String tmp = "";
for (Fruit f : box.getList()) {
tmp += f + " ";
}
return new Juice(tmp);
}
}
μμ κ°μ νΉμ μ λ€λ¦μ λ°λ λ©μλκ° μμ κ²½μ° FruitBox<Apple>
κ³Ό κ°μ΄ Fruit
μ μμ ν΄λμ€λ₯Ό λμ
ν μ μλ€.
Copy class Juicer {
static Juice makeJuice(FruitBox<Fruit> box) {
String tmp = "";
for (Fruit f : box.getList())
tmp += f + " ";
return new Juice(tmp);
}
// μ λ€λ¦ νμ
μ΄ λ€λ₯΄λλΌλ μ€λ²λ‘λ©μ΄ μ±λ¦½νμ§ μμ μ»΄νμΌ μλ¬
static Juice makeJuice(FruitBox<Apple> box) {
String tmp = "";
for (Fruit f : box.getList())
tmp += f + " ";
return new Juice(tmp);
}
}
μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ μ€λ²λ‘λ©μ μ¬μ©νλ©΄ μ λ€λ¦ νμ
μ΄ λ€λ₯Έ κ²λ§μΌλ‘λ μ€λ²λ‘λ©μ΄ μ±λ¦½νμ§ μμ λ©μλ μ€λ³΅ μ μκ° λμ΄ μ»΄νμΌ μλ¬κ° λ°μνλ€.
λμ μλμ κ°μ΄ μμΌλ μΉ΄λλ₯Ό μ¬μ©ν΄ ν΄κ²°ν μ μλ€.
Copy class Fruit {
// Fruit ν΄λμ€μ λ΄μ©μ μλ΅
}
class Apple extends Fruit {
// Apple ν΄λμ€μ λ΄μ©μ μλ΅
}
class FruitBox<T extends Fruit> {
private final List<T> list = new ArrayList<>();
public void add(T fruit) {
list.add(fruit);
}
public List<T> getList() {
return list;
}
}
class Juice {
private final String content;
public Juice(String content) {
this.content = content;
}
@Override
public String toString() {
return "Juice(" + content + ")";
}
}
class Juicer {
static Juice makeJuice(FruitBox<? extends Fruit> box) {
StringBuilder tmp = new StringBuilder();
for (Fruit f : box.getList()) {
tmp.append(f).append(" ");
}
return new Juice(tmp.toString());
}
}
class Main {
public static void main(String[] args) {
FruitBox<Fruit> fruitBox = new FruitBox<>();
FruitBox<Apple> appleBox = new FruitBox<>();
fruitBox.add(new Fruit());
fruitBox.add(new Apple());
appleBox.add(new Apple());
appleBox.add(new Apple());
System.out.println(Juicer.makeJuice(fruitBox));
System.out.println(Juicer.makeJuice(appleBox));
}
}
<? extends T>
: Tμ κ·Έ μμλ€λ§ κ°λ₯
<? super T>
: Tμ κ·Έ μ‘°μλ€λ§ κ°λ₯
<?>
: λͺ¨λ νμ
μ΄ κ°λ₯(=<? extends Object>)
μ λ€λ¦ λ©μλ
μΈμ€ν΄μ€ μμ±ν λμ νμ
κ³Ό μκ΄μμ΄ λ
립μ μΌλ‘ μ λ€λ¦ μ νμ μ μΈνμ¬ μΈ μ μλ€.
Copy class ClassName<E> {
private E element;
// μ λ€λ¦ νλΌλ―Έν° λ©μλ
void set(E element) {
this.element = element;
}
// μ λ€λ¦ νμ
λ°ν λ©μλ
E get() {
return element;
}
// μ λ€λ¦ λ©μλ
<T> T genericMethod(T o) {
return o;
}
}
public class Main {
public static void main(String[] args) {
ClassName<String> a = new ClassName<String>();
ClassName<Integer> b = new ClassName<Integer>();
a.set("10");
b.set(10);
System.out.println("a data : " + a.get()); // a data : 10
System.out.println(
"a E Type : " + a.get().getClass().getName()
); // a E Type : java.lang.String
System.out.println("b data : " + b.get()); // b data : 10
System.out.println(
"b E Type : " + b.get().getClass().getName()
); // b E Type : java.lang.Integer
// μ λ€λ¦ λ©μλ Integer
System.out.println(
"<T> returnType : " + a.<Integer>genericMethod(3).getClass()
.getName()
); // <T> returnType : java.lang.Integer
System.out.println(
"<T> returnType : " + a.genericMethod(3).getClass()
.getName()
); // <T> returnType : java.lang.Integer, νμ
μΆλ‘ μ μν΄ μλ΅ κ°λ₯
// μ λ€λ¦ λ©μλ String
System.out.println(
"<T> returnType : " + a.<String>genericMethod("ABCD").getClass()
.getName()
); // <T> returnType : java.lang.String
System.out.println(
"<T> returnType : " + a.genericMethod("ABCD").getClass()
.getName()
); // <T> returnType : java.lang.String, νμ
μΆλ‘ μ μν΄ μλ΅ κ°λ₯
// μ λ€λ¦ λ©μλ ClassName b
System.out.println(
"<T> returnType : " + a.<ClassName>genericMethod(b).getClass()
.getName()
); // <T> returnType : ClassName
System.out.println(
"<T> returnType : " + a.genericMethod(b).getClass()
.getName()
); // <T> returnType : ClassName, νμ
μΆλ‘ μ μν΄ μλ΅ κ°λ₯
}
}
μμ κ°μ΄ ꡬνμ νκ²λλ©΄ ν΄λμ€μμ μ§μ ν μ λ€λ¦ νμ
κ³Ό λ³λλ‘ λ©μλμμ μ§μ ν μ λ€λ¦ νμ
μ μ¬μ©ν μ μλ€.
μ μμμμ λ겨λ°μ μΈμλ₯Ό ν΅ν΄ νμ
μ μΆλ‘ ν μ μκΈ° λλ¬Έμ μ λ€λ¦ νμ
μ μλ΅ν μ μλ€.
static
μ λ€λ¦ λ©μλ μ μΈμ μ μ λ©μλλ‘ μ μΈν λ μ¬μ©ν μ μλλ°, ν΄λμ€μ μ μΈλ μ λ€λ¦ νμ
κ³Όλ λ³λλ‘ λ
립μ μΈ μ λ€λ¦ νμ
μ μ¬μ©ν΄μΌ νλ€.
Copy class ClassName<E> {
// ν΄λμ€μ μ λ€λ¦ νμ
Eλ₯Ό μ¬μ©
E genericMethod0(E o) {
return o;
}
// μλ¬ λ°μ, static λ©μλλ κ°μ²΄κ° μμ±λκΈ° μ΄μ μμ μ λ©λͺ¨λ¦¬μ μ¬λΌκ°κΈ° λλ¬Έμ ν΄λμ€μ μ μΈ λ E μ νμ μ¬μ©ν μ μμ
static E genericStaticMethod1(E o) {
return o;
}
// κ°μ νμ
λ³μ Eλ₯Ό μ¬μ©νμ§λ§ λ
립μ μΈ νμ
E μ¬μ©
static <E> E genericStaticMethod2(E o) {
return o;
}
// μ λ€λ¦ ν΄λμ€μ E νμ
κ³Ό λ€λ₯Έ λ
립μ μΈ νμ
T μ¬μ© κ°λ₯
static <T> T genericStaticMethod3(T o) {
return o;
}
// μλ¬ λ°μ, λ°ν νμ
μ ν΄λμ€ μ λ€λ¦ νμ
Eλ₯Ό μ¬μ©ν μ μμ
static <T> E genericStaticMethod4(T o) {
return o;
}
}
Generic Type Erasure
μ λ€λ¦ νμ
μ μ»΄νμΌ μμλ§ μ ν¨νκ³ , μ»΄νμΌ νμλ λ°νμ μ€μλ νμ
μ λ³΄κ° μ¬λΌμ§κ² λλ€.
extends
λ₯Ό ν΅ν μ νμ΄ μλ κ²½μ°μλ Object
λ‘ λ체λκ³ , extends
λ₯Ό ν΅ν΄ μ νμ΄ μλ κ²½μ°μλ μ νλ νμ
μΌλ‘ λ체λλ€.
Copy // μ»΄νμΌ μ
class Test<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
// μ»΄νμΌ ν
class Test {
private Object t;
public void set(Object t) {
this.t = t;
}
public Object get() {
return t;
}
}
Copy // μ»΄νμΌ μ
class Test<T extends Number> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
// μ»΄νμΌ ν
class Test {
private Number t;
public void set(Number t) {
this.t = t;
}
public Number get() {
return t;
}
}
μ°Έκ³ μλ£
Last updated 6 months ago