# μ§λ€λ¦μ€ (Generics)
written by sohyeon, hyemin π‘
# 1. μ§λ€λ¦μ΄λ?
μ§λ€λ¦
μ λ€μν νμ
μ κ°μ²΄λ€μ λ€λ£¨λ λ©μλλ 컬λ μ
ν΄λμ€μ μ»΄νμΌ μμ νμ
체ν¬λ₯Ό ν΄μ£Όλ κΈ°λ₯μ΄λ€.
κ°μ²΄μ νμ
μ μ»΄νμΌ μμ 체ν¬νκΈ° λλ¬Έμ μλͺ»λ νμ
μ΄ μ¬μ©λ μ μλ λ¬Έμ λ₯Ό μ»΄νμΌ κ³Όμ μμ μ κ±°ν μ μλ€.
# μ§λ€λ¦μ μ₯μ
- νμ μμ μ±μ μ 곡
- νμ 체ν¬μ νλ³νμ μλ΅ν μ μμΌλ―λ‘ μ½λκ° κ°κ²°ν΄ μ§
λΉμ§λ€λ¦ μ½λλ λΆνμνκ² νμ λ³νμ νκΈ° λλ¬Έμ νλ‘κ·Έλ¨ μ±λ₯μ μ μν₯μ λ―ΈμΉλ€.
# ex) μμ
List list = new ArrayList();
list.add("hello");
String str = (String) list.get(0); // νμ
λ³νμ΄ νμ
List<String> list2 = new ArrayList<>();
list2.add("hello");
String str2 = list.get(0); // λΆνμ
# 2. μ λ€λ¦ ν΄λμ€ μ μΈ
# ex) Box ν΄λμ€
/* Box<T>ν΄λμ€ μ μΈ */
// μ§λ€λ¦ νμ
Tλ₯Ό μ μΈ
class Box<T> { // class Box {
// Object item;
T item;
void setItem(T item) { // void setItem(Object item) {
this.item = item;
}
T getItem() { // Object getItem() {
return item;
}
}
/* Box<T>ν΄λμ€ μ¬μ© */
Box<String> b = new Box<String>(); // T λμ μ€μ νμ
μ§μ
b.setItem(new Object()); // ERROR: Stringνμ
μ΄μΈμ νμ
μ μ§μ λΆκ°
b.setItem("ABC"); // OK: Stringνμ
λ§ κ°λ₯
// String item = (String)b.getItem();
String item = b.getItem(); // νλ³ν νμμμ
/* νΈνμ± */
Box b2 = new Box(); // OK: Tλ Objectλ‘ κ°μ£Όλλ€.
b2.setItem("ABC"); // WARN: unchecked or unsafe operation.
b2.setItem(new Object()); // WARN: unchecked or unsafe operation.
- T: νμ
λ³μ(type variable)
Tκ° μλ λ€λ₯Έ κ²λ μ¬μ©κ°λ₯νλ€. (ex. ArrayList, Map<K,V>)
μν©μ λ§κ² μλ―Έ μλ λ¬Έμλ₯Ό μ νν΄μ μ¬μ©νλ κ²μ΄ μ’λ€. (T:type, E:element, K:key, V:value, ...)
κΈ°νΈλ§ λ€λ₯Ό λΏ 'μμμ μ°Έμ‘°ν νμ 'μ μλ―Ένλ€.
# ex) Boxν΄λμ€
Box
ν΄λμ€: μ΄λ€ νμ μ΄λ νκ°μ§ νμ μ μ ν΄μ λ£μ μ μλ€. Box
ν΄λμ€: Stringνμ λ§ λ΄μ μ μλ€.
class Box<String> { // μ§λ€λ¦ νμ
μ StringμΌλ‘ μ§μ
String item;
void setItem(String item) {
this.item = item;
}
String getItem() {
return item;
}
}
# μ§λ€λ¦μ€μ μ ν
λͺ¨λ κ°μ²΄μ λμΌνκ² λμν΄μΌ νλ staticλ©€λ²μλ νμ λ³μ Tλ₯Ό μ¬μ©ν μ μλ€.
- Tλ μΈμ€ν΄μ€λ³μλ‘ κ°μ£ΌλκΈ° λλ¬Έμ΄λ€. staticμλ μΈμ€ν΄μ€λ³μλ₯Ό μ°Έμ‘°ν μ μλ€.
μ§λ€λ¦ νμ μ λ°°μ΄μ (μ μΈμ κ°λ₯νμ§λ§) μμ±νλ κ²μ λΆκ°λ₯νλ€.
- newμ°μ°μ, instacneofμ°μ°μλ μ»΄νμΌ μμ μ νμ Tκ° λμ§ μ ννκ² μμμΌ νκΈ° λλ¬Έμ Tλ₯Ό νΌμ°μ°μλ‘ μ¬μ©ν μ μλ€.
μ°Έκ³ : μ§λ€λ¦ λ°°μ΄μ κΌ μμ±ν΄μΌ ν κ²½μ° λ°©λ²
newμ°μ°μ λμ 'Reflection API'μ newInstance()μ κ°μ΄ λμ μΌλ‘ κ°μ²΄λ₯Ό μμ±νλ λ©μλλ‘ λ°°μ΄ μμ±
Objectλ°°μ΄μ μμ±ν΄μ 볡μ¬ν λ€μμ T[]λ‘ νλ³ν
# 3. μ§λ€λ¦ ν΄λμ€μ κ°μ²΄ μμ±κ³Ό μ¬μ©
# ex) Box μ§λ€λ¦ ν΄λμ€ μ μ
class Box<T> {
ArrayList<T> list = new ArrayList<T>();
void add(T item) { list.add(item); }
T get(int i) { return list.get(i); }
ArrayList<T> getList() { return list; }
int size() { return list.size(); }
public String toString() { return list.toString(); }
}
# ex) Box κ°μ²΄
Box<Apple> appleBox = new Box<Apple>(); // OK
// ERROR: μ°Έμ‘°λ³μμ μμ±μμ λμ
λ νμ
μ΄ μΌμΉν΄μΌ νλ€.
Box<Apple> appleBox = new Box<Grape>();
// νμ
μμκ΄κ³: Appleμ΄ Fruitμ μμμΌ κ²½μ°
// ERROR: μμκ΄κ³μ¬λ μΌμΉλ νμ
μ΄μ¬μΌ νλ€.
Box<Fruit> appleBox = new Box<Apple>();
// μ§λ€λ¦ ν΄λμ€ μμκ΄κ³: FruitBox<T>κ° Box<T>μ μμμΈ κ²½μ°
Box<Apple> appleBox = new FruitBox<Apple>(); // OK: λ€νμ±
// μΆμ κ°λ₯ν νμ
μλ΅ κ°λ₯ (JDK1.7λΆν°)
Box<Apple> appleBox = new Box<Apple>(); // OK
Box<Apple> appleBox = new Box<>(); // JDK1.7λΆν° OK
# ex) Box.add() μ¬μ©
// μμ±μ λμ
λ νμ
κ³Ό λ€λ₯Έ νμ
μ κ°μ²΄ μΆκ° λΆκ°
Box<Apple> appleBox = new Box<Apple>();
appleBox.add(new Apple()); // OK
appleBox.add(new Grape()); // ERROR
// νμ
μμκ΄κ³: Appleμ΄ Fruitμ μμ
Box<Fruit> fruitBox = new Box<Fruit>();
fruitBox.add(new Fruit()); // OK
fruitBox.add(new Apple()); // ERROR: Fruitλ§ κ°λ₯
# 4. μ νλ μ§λ€λ¦ ν΄λμ€
νμ
λ¬Έμλ‘ μ¬μ©ν νμ
μ λͺ
μνλ©΄ ν μ’
λ₯μ νμ
λ§ μ§μ ν μ μλλ‘ μ νν μ μμ§λ§,
κ·Έλλ λͺ¨λ μ’
λ₯μ νμ
μ μ§μ ν μ μλ€λ κ²μλ λ³ν¨μ΄ μλ€.
μ§λ€λ¦ νμ
μ extends
λ₯Ό μ¬μ©νλ©΄, νΉμ νμ
μ μμλ€λ§ λμ
ν μ μκ² μ νν μ μλ€.
# ex) μμ
class FruitBox<T extends Fruit>{ // Fruitμ μμλ§ νμ
μΌλ‘ μ§μ κ°λ₯
ArrayList<T> list = new ArrayList<T>();
}
FruitBox<Apple> appleBox = new FruitBox<Apple>(); //OK. Appleμ Fruitμ μμ
FruitBox<Toy> toyBox = new FruitBox<Toy>(); //μλ¬. Toyλ Fruitμ μμμ΄ μλ
ν΄λμ€κ° μλλΌ μΈν°νμ΄μ€λ₯Ό ꡬνν΄μΌ νλ€λ μ μ½μ΄ νμνλ€λ©΄,
extends
λ₯Ό μ¬μ©νλ€.
implements
λ₯Ό μ¬μ©νμ§ μλ λ€λ μ μ μ£Όμνμ.
# 5. μμΌλ μΉ΄λ
# μμΌλ μΉ΄λ λμ μ΄μ
static
λ©μλμλ νμ
맀κ°λ³μ Tλ₯Ό 맀κ°λ³μμ μ¬μ©ν μ μλ€.
# ex) static λ©μλ μμ
class Juicer {
static Juice makeJuice(FruitBox<Fruit> box) {
String tmp = "";
for(Fruit f: box.getList()) tmp += f + " ";
return new Juice(tmp);
}
}
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
FruitBox<Apple> appleBox = new FruitBox<Apple>();
Juicer.makeJuice(fruitBox); // OK
Juicer.makeJuice(appleBox); // ERROR: FruitBox<Apple> -> FruitBox<Fruit> νλ³ν μλ¨
μ§λ€λ¦μ€λ₯Ό μ¬μ©νμ§ μκ±°λ, νΉμ νμ
μ μ§μ ν΄μ μ¨μΌ νλ€.
νμ§λ§, νΉμ νμ
μ μ§μ νλ©΄ μ¬λ¬κ°μ§ νμ
μ λ°μ μκ° μλ€.
μ΄λ‘μΈν΄ μ§λ€λ¦ νμ
μ΄ λ€λ₯Έ μ€λ²λ‘λ©μ νκ² λλλ°,
μ§λ€λ¦ νμ
μ΄ λ€λ₯Έ κ²λ§μΌλ‘λ μ€λ²λ‘λ©μ΄ μ±λ¦½λμ§ μμΌλ©° λ©μλ μ€λ³΅ μ μλ‘ μ€λ₯κ° λ°μνλ€.
# ex) μ§λ€λ¦ νμ μ΄ λ€λ₯Έ μ€λ²λ‘λ© μμ
// μ»΄νμΌ μλ¬ λ°μ
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);
}
}
μ΄λ° λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ κ³ μλ κ²μ΄ μμΌλ μΉ΄λ
μ΄λ€.
# μμΌλ μΉ΄λ μ¬μ©
# μμΌλμΉ΄λ κΈ°νΈ: ?
μμΌλμΉ΄λλ μ΄λ ν νμ λ λ μ μλ€.
?λ Objectμ λ€λ¦μμΌλ―λ‘ extends, superλ‘ μνκ³Ό ννμ μ ν ν μ μλ€.- <? extends T>: μμΌλμΉ΄λμ μν μ ν (Tμ κ·Έ μμλ€λ§ κ°λ₯)
- <? super T>: μμΌλμΉ΄λμ νν μ ν (Tμ κ·Έ μ‘°μλ€λ§ κ°λ₯)
- <?>: μ νμμ (λͺ¨λ νμ κ°λ₯), <? extends Object>μ λμΌ
μ§λ€λ¦ ν΄λμ€μ λ¬λ¦¬ μμΌλ μΉ΄λμλ &μ μ¬μ©ν μ μλ€. (μ¦, <? extends T & E>μ κ°μ΄ μΈμμμ)
# ex) μ¬μ© μμ
class Juicer {
static Juice makeJuice(FruitBox<? extends Fruit> box) {
String tmp = "";
for(Fruit f: box.getList()) tmp += f + " ";
return new Juice(tmp);
}
}
- <? extends Object>: λͺ¨λ νμ μ΄ κ°λ₯
# 6. μ§λ€λ¦ λ©μλ
μ§λ€λ¦ λ©μλ
λ λ©μλμ μ μΈλΆμ μ§λ€λ¦ νμ
μ΄ μ μΈλ λ©μλμ΄λ€.
# ex) μ§λ€λ¦ λ©μλ μμ
// Collections.sort()
static <T> void sort(List<T> list, Comparator<? super T> c)
- μ§λ€λ¦ ν΄λμ€μ νμ 맀κ°λ³μ Tμ μ§λ€λ¦ λ©μλμ νμ 맀κ°λ³μ Tλ μλ‘ κ°μλ¬Έμλ₯Ό μ°λλΌλ λ³κ°μ κ²
- μ§λ€λ¦ λ©μλλ μ§λ€λ¦ ν΄λμ€κ° μλ ν΄λμ€μλ μ μ κ°λ₯
- static λ©€λ²μλ νμ 맀κ°λ³μλ₯Ό μ¬μ©ν μ μμ§λ§, static λ©μλμλ κ°λ₯
- λ©μλμ μ μΈλ νμ
μ μ§μλ³μμ κ°μ λλ
(λ©μλ λ΄μμλ§ μ¬μ©λλ―λ‘ staticμ΄κ±΄ μλ건 μκ΄μμ)