JAVA μ λ€λ¦(Generics) ν΄λμ€μ λ©μλ
π λ€λ£¨λ λ΄μ©
- μ λ€λ¦μ μ μ
- μ λ€λ¦ ν΄λμ€
- μ λ€λ¦ λ©μλ
- μ λ€λ¦ μ ν(extends, super)
- μμΌλ μΉ΄λ
- μ λ€λ¦ μ - Collections.sort()
μ λ€λ¦(Generics) μ΄λ?
μ λ€λ¦μ ν΄λμ€, λ©μλμμ μ¬μ©ν λ°μ΄ν° νμ μ λμ€μ νμ νλ κΈ°λ²μ΄λ€. λμ€μλΌλ λ§μ ν΄λμ€λ λ©μλλ₯Ό μ μΈν λκ° μλ μ¬μ©ν λ, μ¦ μΈμ€ν΄μ€λ₯Ό μμ±ν λλ λ©μλλ₯Ό νΈμΆν λ μ νλ€λ μλ―Έμ΄λ€.
μ λ€λ¦μ μ¬μ© λ°©λ²κ³Ό νΉμ§μ λ©μλμ 맀κ°λ³μμ κ΅μ₯ν μ μ¬νλ°, λ©μλμ 맀κ°λ³μκ° 'κ°'κ³Ό κ΄λ ¨λμ΄ μλ€λ©΄ μ λ€λ¦μ λ°μ΄ν°μ 'νμ 'κ³Ό κ΄λ ¨μ΄ μλ€.
λ°λΌμ ν΄λμ€μ λ©μλκ° λ€μν νμ μ λ€λ£° μ μλλ° μ΄λ₯Ό μ λ€λ¦μ μ¬μ©νμ§ μκ³ κ΅¬ννκ³ μ νλ©΄ λ°©λ²μ λ κ°μ§μ΄λ€.
Object νμ μ μ¬μ©νλμ§, λμΌν λ©μ»€λμ¦μ κ°μ§ ν΄λμ€μ λ©μλλ₯Ό μ¬λ¬ κ° μ μνλμ§.
μΌλ¨ Objectλ₯Ό μ¬μ©νλ©΄ μ½λ μ€λ³΅μ λ§μ μ μκ² μ§λ§ κ°μ²΄μ νμ μ μ»΄νμΌ νμμ 체ν¬ν μ μλ€λ μ μ½μ¬νμ΄ μκΈ°κ³ μ΄λ‘ μΈν΄ λ°νμμ νμ μΌλ‘ μΈν μ€λ₯κ° λ°μν μ μλ€.
μ λ€λ¦μ μ¬μ©νλ©΄ Objectλ₯Ό μ¬μ©ν λμ λ¬λ¦¬ κ°μ²΄μ νμ μ μ»΄νμΌ νμμ 체ν¬ν μ μμ΄μ νμ μμ μ±(type safety)λ₯Ό λμ΄κ³ νλ³νμ λ²κ±°λ‘μμ΄ μ€μ΄λ λ€λ μ₯μ μ΄ μλ€.
νμ μμ μ±(type safety)
- μλνμ§ μμ νμ μ κ°μ²΄κ° μ μ₯λλ κ²μ λ§λλ€.
- μ μ₯λ κ°μ²΄λ₯Ό κΊΌλ΄μ¬ λ λ€λ₯Έ νμ μΌλ‘ μλͺ» νλ³ννμ¬ λ°μν μ μλ μ€λ₯λ₯Ό μ€μΈλ€.
μ λ€λ¦μ μ₯μ
- νμ μμ μ±
- μ½λκ° κ°κ²°ν΄μ§λ€.
JAVAμ μ λ€λ¦μ C++μ ν νλ¦Ώ ν΄λμ€μ μ μ¬ν κ°λ μ΄λΌκ³ νλ€.
μ λ€λ¦ ν΄λμ€
μ λ€λ¦μ ν΄λμ€μ λ©μλμμ μ¬μ©ν μ μλλ° μ λ€λ¦ νμ μ μ μΈν ν΄λμ€λ₯Ό μ λ€λ¦ ν΄λμ€λΌ νλ€.
public class Box<T> {
private T item;
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
ν΄λμ€μμ μ¬μ©νλ €λ©΄ ν΄λμ€ λͺ μ°μΈ‘μ <>λ₯Ό μ¬μ©ν΄μ μ μΈνλ€.
public class Box<M, I> {
private M material;
private I item;
public M getMaterial() {
return material;
}
public void setMaterial(M material) {
this.material = material;
}
public I getItem() {
return item;
}
public void setItem(I item) {
this.item = item;
}
}
λν ,(μ½€λ§)λ‘ κ΅¬λΆν΄μ μ¬λ¬ κ°λ₯Ό μ μΈν μ μλ€.
Box<Paper, String> box = new Box<Paper, String>();
Box<Paper, String> box = new Box<>(); // JDK1.7λΆν° μλ΅ κ°λ₯
Box box = new Box(); // Objectλ‘ κ°μ£Ό
μ λ€λ¦ ν΄λμ€λ μ΄λ κ² μ¬μ©ν μ μλ€.
JDK1.7λΆν° μμ±μμ <>μ νμ μ μλ΅ν μ μλ€.
μ λ€λ¦μ JDK1.5λΆν° λμ λμλλ° νμ νΈνμ μν΄ νμ μ μ§μ νμ§ μκ³ λ κ°μ²΄λ₯Ό μμ±ν μ μμΌλ©° μ΄λ° κ²½μ° νμ μ Objectλ‘ κ°μ£Όλλ€.
μ£Όμν΄μΌ ν μ μ μ°Έμ‘°λ³μμμ μ§μ ν νμ κ³Ό μμ±μμμ μ§μ ν νμ μ λ°λμ μΌμΉν΄μΌ νλ€.
λ νμ μ΄ μλ‘ μμκ΄κ³μ μλ€ ν΄λ νμ μ΄ λ€λ₯΄λ©΄ μ»΄νμΌ μλ¬κ° λ°μνλ€.
μλ₯Ό λ€μ΄ Cardboard ν΄λμ€κ° Paperμ μμ ν΄λμ€λΌκ³ ν΄μ Box<Paper> box = new Box<Cardboard>();λ λΆκ°λ₯νλ€.
μ λ€λ¦ λ©μλ
μ λ€λ¦μ ν΄λμ€ λ 벨μμλ§ μ¬μ©ν μ μλκ² μλλΌ λ©μλ λ 벨μμλ μ¬μ©ν μ μλ€.
μ λ€λ¦ νμ μ μ μΈν λ©μλλ₯Ό μ λ€λ¦ λ©μλλΌ νλ€.
ν΄λμ€μ μ λ€λ¦ νμ μ΄ μ μ λ³μμ²λΌ μ¬μ©λλ€λ©΄ λ©μλμ μ λ€λ¦ νμ μ ν΄λΉ λ©μλ μμμλ§ μ¬μ©ν μ μλ μ§μμ±μ κ°λλ€.
public class CoffeeMachine {
public <T> Coffee makeCoffee(T capsule) {
return new Coffee(capsule);
}
}
μ λ€λ¦ νμ μ λ©μλμμ μ μΈν λλ μ κ·Όμ νμμ λ°ννμ μ¬μ΄μ μ μΈνλ€.
CoffeeMachine coffeeMachine = new CoffeeMachine();
Colombian capsule = new Colombian();
coffeeMachine.<Colombian>makeCoffee(capsule);
coffeeMachine.makeCoffee(capsule); // νμ
μΆμ κ°λ₯νλ―λ‘ μλ΅ κ°λ₯
μ λ€λ¦ λ©μλλ₯Ό νΈμΆν λλ λ©μλ λͺ μμ <>λ‘ νμ μ μ§μ ν΄μ€μΌ νμ§λ§ μ»΄νμΌλ¬κ° νμ μ μΆμ ν μ μλ κ²½μ°μ μλ΅ν μ μλ€.
λλΆλΆμ κ²½μ° μ»΄νμΌλ¬κ° νμ μ μΆμ ν μ μλ€.
μ λ€λ¦ μ ν
μ λ€λ¦μ μ¬μ©νλ©΄ μ¬μ©ν λ νμ μ μ§μ νκ² λλλ°, 'μ΄λ€ νμ μ΄ μ¬ μ μλμ§'λ₯Ό μ ννμ§ μμΌλ©΄ λ§ κ·Έλλ‘ μ€λ§κ°μ§ νμ μ΄ μ¬ μ μλ€. λ°λΌμ μλ°λ extends, super ν€μλλ₯Ό ν΅ν΄ μ΄λ₯Ό λ¬Έλ²μ μΌλ‘ μ νν μ μλ κΈ°λ₯μ μ 곡νλ€.
class BoxMaterial { }
class Paper { }
class Plastic { }
public class Box<M> {
private M material;
public static void main(String[] args) {
Box<Water> box = new Box<>(); // νμ
Mμ μ νμ΄ μμΌλ―λ‘ μ΄λ€ νμ
μ΄λ μ§μ κ°λ₯
}
}
class BoxMaterial { }
class Paper extends BoxMaterial { }
class Plastic extends BoxMaterial { }
public class Box<M extends BoxMaterial> {
private M material;
public static void main(String[] args) {
Box<Water> waterBox = new Box<>(); // λΆκ°. BoxMaterialκ³Ό μμ νμ
λ§ κ°λ₯
Box<Paper> paperBox = new Box<>();
Box<Plastic> plasticBox = new Box<>();
}
}
M extends BoxMaterialκ³Ό κ°μ΄ μ μΈν¨μΌλ‘μ¨ Mμλ λͺ¨λ νμ μ΄ μλ BoxMaterialκ³Ό κ·Έ μμ ν΄λμ€λ§ μ¬ μ μλ€.
extends λ€μ μ€λ νμ μ΄ μΈν°νμ΄μ€μ¬λ λμΌνκ² extends ν€μλλ₯Ό μ¬μ©νλ€.
class BoxMaterial implements Hard { }
class Paper extends BoxMaterial { }
class Plastic extends BoxMaterial { }
public interface Hard { }
public class Box<M extends BoxMaterial & Hard> {
private M material;
public static void main(String[] args) {
Box<Paper> paperBox = new Box<>();
Box<Plastic> plasticBox = new Box<>();
}
}
extends λ€μ μ¬λ¬ νμ μ μ§μ νλ €λ©΄ '&'λ₯Ό μ¬μ©νλ€.
M extends BoxMaterial & Hardλ Boxμ material νλκ° BoxMaterialμ΄λ©΄μ Hardλ₯Ό ꡬνν νμ λ§ μ§μ ν μ μλλ‘ μ νν κ²μ΄λ€.
νμ μ μ νν¨μΌλ‘μ¨ μλͺ»λ νμ μ μ§μ νλ©΄ νμ μλ¬λ₯Ό μ»΄νμΌ νμμ κ²μΆν΄μ λ°νμ μλ¬λ₯Ό λ°©μ§νλ€.
class BoxMaterial {
public String printInfo() {
return "";
}
}
public class Paper extends BoxMaterial {
@Override
public String printInfo() {
return "μ’
μ΄";
}
}
public class Plastic extends BoxMaterial {
@Override
public String printInfo() {
return "νλΌμ€ν±";
}
}
public class Box<M extends BoxMaterial> {
private M material;
public Box(M material) {
this.material = material;
}
public void printInfo() {
System.out.println(material.printInfo() + " μμμ
λλ€.");
}
public static void main(String[] args) {
Box<Paper> paperBox = new Box<>(new Paper());
paperBox.printInfo();
Box<Plastic> plasticBox = new Box<>(new Plastic());
plasticBox.printInfo();
}
}
λν νμ μ μ ννμ§ μμΌλ©΄ Box ν΄λμ€ λ΄μμ material νλλ₯Ό μ΄μ©ν΄ νΈμΆν μ μλ λ©μλλ Objectμ λ©μλλ°μ μμ§λ§ νμ μ μ ννλ©΄ ν΄λΉ νμ μ λ©μλλ₯Ό μ¬μ©ν μ μλ€.
extendsλ₯Ό μ¬μ©ν¨μΌλ‘μ¨ ν΄λΉ νμ μ μμ νμ λ§ μ¬ μ μλλ‘ νλ―λ‘ μν(upper bound)λ₯Ό μ ννλ€λ©΄ superλ λ°λλ‘ νν(lower bound)λ₯Ό μ ννλ€. μ¦ T super BoxMaterialμ BoxMaterialμ μ‘°μ νμ λ§ μ¬ μ μλλ‘ μ ννλ€. κ·Έ μΈμ μ°¨μ΄μ μ μλ€.
μμΌλ μΉ΄λ
class Fruit {
String name;
@Override
public String toString() {
return name;
}
}
class Apple extends Fruit {
public Apple() {
this.name = "μ¬κ³Ό";
}
}
class Banana extends Fruit {
public Banana() {
this.name = "λ°λλ";
}
}
class FruitCup<T extends Fruit> {
List<T> fruits;
public FruitCup() {
fruits = new ArrayList<>();
}
public void addFruit(T fruit) {
fruits.add(fruit);
}
public List<T> getFruits() {
return fruits;
}
}
public class Juicer {
public static Juice makeJuice(FruitCup<Fruit> fruitCup) {
return new Juice(fruitCup.getFruits());
}
public static void main(String[] args) {
FruitCup<Fruit> fruitCup = new FruitCup<>();
fruitCup.addFruit(new Apple());
fruitCup.addFruit(new Banana());
System.out.println(Juicer.makeJuice(fruitCup).toString());
}
}
π₯ μ€ν κ²°κ³Ό
Juice{fruits=[μ¬κ³Ό, λ°λλ]}
Process finished with exit code 0
μ μ½λμμ Juicer ν΄λμ€μ makeJuice λ©μλλ FruitCup<Fruit> νμ μ 맀κ°λ³μλ₯Ό λ°λλ€.
FruitCup<Apple> appleCup = new FruitCup<>();
appleCup.addFruit(new Apple());
System.out.println(Juicer.makeJuice(appleCup).toString()); // λΆκ°
Apple, Bananaλ Fruitμ μμμ΄μ§λ§ FruitCup<Apple>, FruitCup<Banana>λ makeJuiceμ μΈμλ‘ μ λ¬ν μ μλ€.
λ©μλμμ μ§μ ν FruitCup<Fruit> νμ λ§μ΄ μΈμκ° λ μ μλ€.
makeJuice λ©μλκ° Fruit λΏλ§ μλλΌ Fruitμ μμμΈ Apple, Bananaμ κ°μ μ λ€λ¦ νμ μ FruitCupμ 맀κ°λ³μλ‘ λ°μΌλ €λ©΄ λ©μλ λ 벨μμ μ λ€λ¦ νμ μ μ μΈνλμ§(μ λ€λ¦ λ©μλ), 'μμΌλ μΉ΄λ'λ₯Ό μ¬μ©ν μ μλ€.
μ λ€λ¦μμ μμΌλ μΉ΄λλ '?' κΈ°νΈλ₯Ό μ¬μ©νλ©° μλ―Έ κ·Έλλ‘ μ΄λ€ νμ λ λ μ μλ€.
'?'λ§ μ¬μ©νλ©΄ Object νμ κ³Ό λ€λ₯Όκ² μμΌλ―λ‘ μ λ€λ¦ μ νμμ μ¬μ©νλ extends, super ν€μλλ₯Ό ν¨κ» μ¬μ©νλ€.
<? extends T>
Tμ κ·Έ μμ νμ λ§ κ°λ₯(upper bound)
<? super T>
Tμ κ·Έ μ‘°μ νμ λ§ κ°λ₯(lower bound)
<?>
μ ν μμ΄ λͺ¨λ νμ μ΄ κ°λ₯. <? extneds Object>μ λμΌν νν
μμΌλ μΉ΄λλ₯Ό μ¬μ©ν΄ λ³κ²½ν μ½λλ λ€μκ³Ό κ°λ€.
class Fruit {
String name;
@Override
public String toString() {
return name;
}
}
class Apple extends Fruit {
public Apple() {
this.name = "μ¬κ³Ό";
}
}
class Banana extends Fruit {
public Banana() {
this.name = "λ°λλ";
}
}
class FruitCup<T extends Fruit> {
List<T> fruits;
public FruitCup() {
fruits = new ArrayList<>();
}
public void addFruit(T fruit) {
fruits.add(fruit);
}
public List<T> getFruits() {
return fruits;
}
}
public class Juicer {
public static Juice makeJuice(FruitCup<? extends Fruit> fruitCup) {
return new Juice(fruitCup.getFruits());
}
public static void main(String[] args) {
FruitCup<Fruit> fruitCup = new FruitCup<>();
fruitCup.addFruit(new Apple());
fruitCup.addFruit(new Banana());
System.out.println(Juicer.makeJuice(fruitCup).toString());
FruitCup<Apple> appleCup = new FruitCup<>();
appleCup.addFruit(new Apple());
appleCup.addFruit(new Apple());
appleCup.addFruit(new Apple());
System.out.println(Juicer.makeJuice(appleCup).toString());
}
}
π₯ μ€ν κ²°κ³Ό
Juice{fruits=[μ¬κ³Ό, λ°λλ]}
Juice{fruits=[μ¬κ³Ό, μ¬κ³Ό, μ¬κ³Ό]}
Process finished with exit code 0
μΆκ°λ‘ μμΌλ μΉ΄λλ₯Ό μ¬μ©νμ§ μκ³ μ§λ€λ¦ λ©μλλ‘ λ³κ²½νλ©΄ λ€μκ³Ό κ°λ€.
public static Juice makeJuice(FruitCup<? extends Fruit> fruitCup) {
return new Juice(fruitCup.getFruits());
}
β¬οΈ
public static <T extends Fruit> Juice makeJuice(FruitCup<T> fruitCup) {
return new Juice(fruitCup.getFruits());
}
μ΄λ€ λ°©λ²μ μ¬μ©νλ λμΌν λμμ νλ€.
μ λ€λ¦μ μ - Collections.sort()
μλ°μ Collectionsλ μμλ₯Ό μ λ ¬νλ static λ©μλ sort()λ₯Ό μ 곡νλλ°, μ΄ λ©μλκ° μ λ€λ¦ νμ μ μ¬μ©νλ μ λ€λ¦ λ©μλμ μ μ€ νλμ΄λ€.
Collection.sort(List, Comparator)μ μ μΈλΆ
static <T> void sort(List<T> list, Comparator<? super T> c)
List<T>μ Comparator<? super T> νμ μ λ κ°μ 맀κ°λ³μλ₯Ό λ°λ sort() λ©μλμ΄λ€.
첫 λ²μ§Έ 맀κ°λ³μλ μ λ ¬ λμμ΄κ³ λ λ²μ§Έ 맀κ°λ³μλ μ λ ¬ν λ°©λ²μ΄ μ μλ Comparatorμ΄λ€.
Comparatorλ <? super T>λΌλ μ λ€λ¦ νμ μ΄ μ μΈλΌ μλλ°, μ΄λ μ λ ¬ λμ μμλ€μ νμ νΉμ κ·Έ μ‘°μ νμ μ Comparatorλ₯Ό 맀κ°λ³μλ‘ νλ€λ λ»μ΄λ€.
Collection.sort(List)μ μ μΈλΆ
public static <T extends Comparable<? super T>> void sort(List<T> list)
List<T> ν κ°λ₯Ό 맀κ°λ³μλ‘ λ°λ sort() λ©μλμ΄λ€.
νμ Tλ₯Ό μμλ‘ νλ Listλ₯Ό λκΈ°λ©΄ λλλ°, T λλ κ·Έ μ‘°μ ν΄λμ€κ° Comparableμ ꡬνν΄μΌ νλ€λ μλ―Έμ΄λ€.
'JavaΒ·ο»ΏServletΒ·ο»ΏJSP' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[JAVA] Arrays.asList()μ List.of()μ μ°¨μ΄ (0) | 2023.02.10 |
---|---|
JAVAμμ Stringμ Null Safeνκ² λΉκ΅νκΈ° (0) | 2021.08.14 |
JAVAμ κ°μ²΄ μ§λ ¬ν(Serialization)μ JSON μ§λ ¬ν (0) | 2020.07.10 |
μλ° Object ν΄λμ€ μ 리 - toString(), equals(), hashCode(), clone() (0) | 2020.06.30 |
[JAVA λμμΈ ν¨ν΄] ν νλ¦Ώ λ©μλ ν¨ν΄ (59) | 2020.06.26 |
λκΈ