μΆμ²
ChatGPT
λ³μ±(Variance)μ μ λ€λ¦ νμ μ΄ μμ κ΄κ³μμ μ΄λ»κ² λμνλμ§, μ¦ νμ κ°μ μμ κ΄κ³κ° μ λ€λ¦ νμ μμλ κ·Έλλ‘ μ μ§λ μ μλμ§μ λν κ°λ μ μλ―Ένλ€. λ³μ±μ κ°μ²΄ μ§ν₯ νλ‘κ·Έλλ°μμ μ λ€λ¦ νμ μ μμ ν μ¬μ©μ μν μ€μνλ€. λ³μ±μ ν¬κ² 곡λ³μ±(Convariance), λ°κ³΅λ³μ±(Contravariance), κ·Έλ¦¬κ³ λ¬΄κ³΅λ³μ±(Invariance)μΌλ‘ λλ μ μλ€.
1. λ³μ±μ μ’ λ₯
1. 곡λ³μ± Convariance
μ μ
곡λ³μ±μ μ λ€λ¦ νμ μ΄ νΉμ νμ μ νμ νμ κ΄κ³λ₯Ό κ·Έλλ‘ μ μ§νλ κ²μ μλ―Ένλ€.
κ·Έλ¬λκΉ, A νμ κ³Ό A νμ λ₯Ό μμλ°μ A'νμ μ΄ μκ³ , B νμ κ³Ό B νμ μ μμλ°μ B' νμ μ΄ μλ€λ©΄, A<? extends B> λ³μμ A'<B'> κ°μ²΄λ₯Ό λ£μ μ μλ€λ κ²μ΄λ€.
μμ
λ§μ½ Appleμ΄ Fruitμ νμ νμ μ΄λΌλ©΄, List<Apple>λ List<Fruit>μ νμ νμ μΌλ‘ κ°μ£Όλ μ μλ μν©μ΄λ€.
μ¬μ© μ¬λ‘
μλ°μμλ 곡λ³μ±μ μ§μνκΈ° μν΄ μν κ²½κ³ μμΌλ μΉ΄λ(? extendsd T)λ₯Ό μ¬μ©νλ€. μ΄λ νΉμ μ λ€λ¦ νμ μ΄ νΉμ μμ ν΄λμ€μ μλΈνμ (νμ νμ )λ€λ§ νμ©νλ€λ κ²μ μλ―Ένλ€.
List<? extends Fruit> fruits = new ArrayList<Apple>();
μ μ½λμμ List<? extends Fruit>λ Fruitμ νμ νμ λ€(Apple, Orange λ±)μ 리μ€νΈλ‘ μ¬μ©ν μ μλ€.
μ μ½
곡λ³μ±μμλ 리μ€νΈμ μλ‘μ΄ μμλ₯Ό μΆκ°ν μ μλ€. μλνλ©΄ μ€μ νμ μ΄ μ νν 무μμΈμ§ μ»΄νμΌλ¬κ° μ μ μκΈ° λλ¬Έμ΄λ€.
리μ€νΈμ μλ‘μ΄ μμλ₯Ό μΆκ°ν λ νμ μμ μ±μ μ μ§νκΈ° μν΄, μλ°λ 곡λ³μ±μ μν΄ μ μλ 리μ€νΈμ μλ‘μ΄ μμλ₯Ό μΆκ°νλ κ²μ μ ννλ€.
- μμ
List<? extends Fruit> fruits = new ArrayList<Apple>();
// fruits.add(new Apple()); // μ»΄νμΌ μ€λ₯
// fruits.add(new Fruit()); // μ»΄νμΌ μ€λ₯
μ μ½λμμ fruits 리μ€νΈλ Fruitμ νμ νμ λ€λ‘ μ νλκΈ° λλ¬Έμ Apple νμ μ 리μ€νΈλ‘ μ΄κΈ°νλμλ€. κ·Έλ¬λ fruits 리μ€νΈμ μλ‘μ΄ μμλ₯Ό μΆκ°νλ €κ³ ν λ, μ»΄νμΌ μ€λ₯κ° λ°μνλ€. μ κ·Έλ°μ§ μμλ³΄κ² λ€.
- νμ μμ μ± λ¬Έμ
fruitsμ μ μΈ νμ μ List<? extends Fruit>λ‘, μ΄λ Fruitμ νμ νμ μ μλ―Ένλ€. μ΄ μμ μμ μλ° μ»΄νμΌλ¬λ fruits 리μ€νΈκ° μ€μ λ‘ μ΄λ€ νμ νμ (Apple, Orange λ±)μ 리μ€νΈμΈμ§ μ νν μ μ μλ€.
λ§μ½ fruits 리μ€νΈμ new Apple()μ μΆκ°νλ€κ³ κ°μ ν΄ λ³΄μ. fruitsκ° List<Orange>λ‘ μ΄κΈ°νλμλ€λ©΄, Apple κ°μ²΄λ₯Ό Orange κ°μ²΄λ‘ μ·¨κΈνκ² λμ΄ νμ λΆμΌμΉ λ¬Έμ κ° λ°μνλ€. λ°λΌμ, μ»΄νμΌλ¬λ fruits 리μ€νΈμ Apple κ°μ²΄λ₯Ό μΆκ°νλ κ²μ νμ©νμ§ μλλ€.
- μ»΄νμΌλ¬μ νμ μΆλ‘ μ ν: List<? extends Fruit>λ μ»΄νμΌλ¬μκ² "μ΄ λ¦¬μ€νΈλ Fruitμ νμ νμ μΌλ‘ ꡬμ±λμ΄ μλ€"κ³ μλ €μ€λ€. κ·Έλ¬λ μ΄ λ¦¬μ€νΈκ° μ΄λ€ νΉμ ν νμ νμ μ 리μ€νΈμΈμ§ μ μ μκΈ° λλ¬Έμ, μ»΄νμΌλ¬λ νμ μμ μ±μ 보μ₯νκΈ° μν΄ μμ μΆκ°λ₯Ό λ§λ€.
λ°λΌμ, 곡λ³μ±μμλ μλ‘μ΄ μμλ₯Ό μΆκ°νλ κ²μ΄ μ νλλ€. 리μ€νΈμ νΉμ νμ μ μ νν μ μ μλ κ²½μ°κ° λ§κΈ° λλ¬Έμ, μ΄λ‘ μΈν΄ λ°μν μ μλ μ μ¬μ μΈ νμ λΆμΌμΉμ κ°μ λ¬Έμ λ₯Ό λ°©μ§νκΈ° μν΄μμ΄λ€.
곡λ³μ±μ Practical μ¬μ© μ¬λ‘
곡λ³μ±μ μΌλ°μ μΌλ‘ μ½κΈ° μ μ© μν©μμ μ μ©νλ€. μλ₯Ό λ€μ΄, λ©μλκ° μ λ€λ¦ 리μ€νΈλ₯Ό μΈμλ‘ λ°μ 리μ€νΈμ μμλ₯Ό μννκ±°λ μ½κΈ°λ§ ν λ, 곡λ³μ±μ μ¬μ©νλ κ²μ΄ μ μ νλ€. μ΄λ κ² νλ©΄ νμ νμ μ μμλ₯Ό ν¬ν¨νλ 리μ€νΈλ μμ νμ μ 리μ€νΈλ‘ μ·¨κΈν μ μμ΄ μ μ°μ±μ΄ λμμ§λ€.
public void printFruits(List<? extends Fruit> fruits) {
for (Fruit fruit : fruits) {
System.out.println(fruit);
}
}
μ λ©μλλ Fruitμ νμ νμ λ€μ ν¬ν¨νλ 리μ€νΈλ₯Ό μΈμλ‘ λ°μ μ μκ³ , μμλ€μ μμ νκ² μΆλ ₯ν μ μλ€.
2. λ°κ³΅λ³μ± Contravariance
μ μ
λ°κ³΅λ³μ±μ μ λ€λ¦ νμ μ΄ νΉμ νμ μ μμ νμ κ΄κ³λ₯Ό μ μ§νλ κ²μ μλ―Ένλ€.
κ·Έλ¬λκΉ, A νμ κ³Ό A νμ λ₯Ό μμλ°μ A'νμ μ΄ μκ³ , B νμ κ³Ό B νμ μ μμλ°μ B' νμ μ΄ μλ€λ©΄, A<? super B'> λ³μμ A'<B> κ°μ²΄λ₯Ό λ£μ μ μλ€λ κ²μ΄λ€.
μμ
λ§μ½ Fruitμ΄ Appleμ μμ νμ μ΄λΌλ©΄, List<Fruit>λ List<Apple>μ μμ νμ μΌλ‘ κ°μ£Όλ μ μλ μν©μ΄λ€.
μ¬μ© μ¬λ‘
μλ°μμλ λ°κ³΅λ³μ±μ μ§μνκΈ° μν΄ νν κ²½κ³ μμΌλμΉ΄λ(? super T)λ₯Ό μ¬μ©νλ€. μ΄λ νΉμ μ λ€λ¦ νμ μ΄ νΉμ νμ ν΄λμ€μ μνΌνμ (μμ νμ )λ€λ§ νμ©νλ€λ κ²μ μλ―Ένλ€.
List<? super Apple> apples = new ArrayList<Fruit>();
μ μ½λμμ List<? super Apple>λ Appleμ μμ νμ λ€(Fruit, Object λ±)μ 리μ€νΈλ‘ μ¬μ©ν μ μλ€.
μ μ½
λ°κ³΅λ³μ±μμλ 리μ€νΈμμ κ°μ κΊΌλΌ λ νμ μ΄ μ νν 무μμΈμ§ μ μ μμΌλ―λ‘, μμ νμ μΌλ‘λ§ λ€λ£° μ μλ€.
List<? super T>λ₯Ό μ¬μ©ν λ, 리μ€νΈμ κ°μ μΆκ°νλ κ²μ κ°λ₯νμ§λ§, κ°μ κΊΌλΌ λλ λ€μκ³Ό κ°μ μ μ½μ΄ μλ€.
- νμ μ 보μ μμ€
List<? super T> λ Tμ νμ νμ μ μμ©ν μ μλ 리μ€νΈμ΄λ€. μ΄ κ²½μ°, 리μ€νΈμ λ΄κ²¨ μλ κ°μ²΄λ T λλ Tμ μμ νμ μΌ μ μλ€. μ¦, 리μ€νΈμ T κ°μ²΄λ₯Ό μΆκ°ν μ μμ§λ§, 리μ€νΈμμ κΊΌλΌ λμλ κ·Έ κ°μ²΄μ μ νν νμ μ μ μ μλ€.
- νμ μ λΆνμ€μ±
List<? super T>μμ κ°μ κΊΌλΌ λ, κΊΌλΈ κ°μ²΄μ νμ μ Objectλ‘ μ νλλ€. μ΄λ 리μ€νΈκ° Tμ νμ νμ λΏλ§ μλλΌ Tμ μμ νμ λ μμ©ν μ μκΈ° λλ¬Έμ΄λ€. λ°λΌμ, κΊΌλΈ κ°μ²΄κ° Tμ μλΈνμ μΈμ§ μλμ§ μ μ μκΈ° λλ¬Έμ, ν΄λΉ κ°μ²΄λ₯Ό Tλ‘ μμ νκ² μΊμ€ν ν μ μλ€.
-μμ
import java.util.ArrayList;
import java.util.List;
public class ContravarianceExample {
public static void main(String[] args) {
List<? super Integer> list = new ArrayList<>();
list.add(1); // Integerλ₯Ό μΆκ°ν μ μμ
list.add(2); // Integerλ₯Ό μΆκ°ν μ μμ
Object obj = list.get(0); // κΊΌλΈ κ°μ νμ
μ Objectλ‘ μ νλ¨
// Integer number = list.get(0); // μ»΄νμΌ μ€λ₯: μ νν νμ
μ μ μ μκΈ° λλ¬Έ
System.out.println(obj); // μΆλ ₯: 1
}
}
κ° μΆκ°:
- list.add(1)κ³Ό list.add(2)λ κ°λ₯νλ©°, Integerλ₯Ό List<? super Integer>μ μΆκ°ν μ μλ€.
κ° κΊΌλ΄κΈ°:
- Object obj = list.get(0)μ κ°λ₯νλ©°, get λ©μλλ 리μ€νΈμ μλ κ°μ Objectλ‘ λ°ννλ€. μ΄λ 리μ€νΈμ μ μ₯λ κ°μ²΄μ νμ μ΄ μ νν 무μμΈμ§ μ μ μκΈ° λλ¬Έμ΄λ€.
- Integer number = list.get(0)μ μ»΄νμΌ μ€λ₯λ₯Ό λ°μμν¨λ€. list.get(0)μ΄ λ°ννλ κ°μ΄ IntegerμΌ μλ μμ§λ§, Objectλ‘ λ°νλκΈ° λλ¬Έμ Integerλ‘ μ§μ μΊμ€ν ν μ μλ€. μ νν νμ μ μ μ μκΈ° λλ¬Έμ μμ νμ§ μλ€.
λΉκ³΅λ³μ±μ Practical μ¬μ© μ¬λ‘
νμ μ μμ νμ μΌλ‘ λ€λ£¨λ©΄μ μ μ°ν μ½λλ₯Ό μμ±ν λ ν¨κ³Όμ μ΄λ€.
μμ 1 : μ΄λ²€νΈ 리μ€νΈμ μ½λ°±
μ΄λ²€νΈ 리μ€λλ μ½λ°± ν¨ν΄μμ λ°κ³΅λ³μ±μ νμ©ν μ μλ€. μ΄λ¬ν ν¨ν΄μ νΉμ νμ μ μ΄λ²€νΈλ₯Ό μ²λ¦¬νλ νΈλ€λ¬λ₯Ό λ±λ‘νλ κ²½μ°κ° λ§λ€.
μ΄λ²€νΈ 리μ€ν° μ μ
interface EventListener<T> {
void handleEvent(T event);
}
λ€μν μ΄λ²€νΈ νΈλ€λ¬ λ±λ‘
import java.util.ArrayList;
import java.util.List;
public class EventDispatcher {
private List<EventListener<? super Integer>> listeners = new ArrayList<>();
// νΈλ€λ¬ μΆκ° λ©μλ
public void addListener(EventListener<? super Integer> listener) {
listeners.add(listener);
}
// μ΄λ²€νΈ λ°μ λ©μλ
public void dispatchEvent(Integer event) {
for (EventListener<? super Integer> listener : listeners) {
listener.handleEvent(event);
}
}
public static void main(String[] args) {
EventDispatcher dispatcher = new EventDispatcher();
// Integer μ΄λ²€νΈλ₯Ό μ²λ¦¬νλ 리μ€λ λ±λ‘
dispatcher.addListener(new EventListener<Integer>() {
@Override
public void handleEvent(Integer event) {
System.out.println("Integer Event: " + event);
}
});
// Number μ΄λ²€νΈλ₯Ό μ²λ¦¬νλ 리μ€λ λ±λ‘
dispatcher.addListener(new EventListener<Number>() {
@Override
public void handleEvent(Number event) {
System.out.println("Number Event: " + event);
}
});
dispatcher.dispatchEvent(42); // Integer μ΄λ²€νΈ λ°μ
}
}
μ μ½λμμ EventDispatcherλ EventListener<? super Integer> νμ μ 리μ€λλ₯Ό λ±λ‘ν μ μλ€. μ΄λ IntegerλΏλ§ μλλΌ Numberμ κ°μ Integerμ μμ νμ μ μ²λ¦¬νλ 리μ€λλ μμ©ν μ μκ² νλ€. μ΄λ‘ μΈν΄ μ½λμ μ μ°μ±μ΄ λμμ§κ³ λ€μν νμ μ 리μ€λλ₯Ό λ±λ‘ν μ μλ€.
3. 무곡λ³μ± Invariance
μ μ
무곡λ³μ±μ μ λ€λ¦ νμ μ΄ νΉμ νμ μ μμ λλ νμ κ΄κ³λ₯Ό νμ©νμ§ μλ κ²μ μλ―Ένλ€. μ¦, μ λ€λ¦ νμ μ λν΄ μ νν μΌμΉνλ νμ λ§ μ¬μ©ν΄μΌ νλ€.
μμ
List<Fruit>λ List<Apple>μ νμ νμ λ μλκ³ μμ νμ λ μλλ€. λ μ λ€λ¦ νμ μ μλ‘ μ ν κ΄λ ¨μ΄ μλ€.
List<Fruit> fruits = new ArrayList<Fruit>(); // μ νν μΌμΉν΄μΌλ§ ν©λλ€.
μ μ½λμμ List<Fruit>λ List<Apple>λ‘ λ체λ μ μλ€. 무곡λ³μ±μμλ μ λ€λ¦ νμ μ μμ κ΄κ³κ° μ μ§λμ§ μλλ€.
2. λ³μ±μ΄ μ‘΄μ¬νλ μ΄μ
λ³μ±μ μ λ€λ¦ νμ μ΄ μμ ꡬ쑰μ ν¨κ» μ¬μ©λ λμ μμ μ±μ 보μ₯νκΈ° μν΄ νμνλ€. λ³μ±μ μ μ ν μ¬μ©νμ§ μμΌλ©΄ νμ μμ μ±μ΄ κΉ¨μ§ μ μμΌλ©°, μ΄λ λ°νμ μμΈλ νμ λΆμΌμΉ μ€λ₯λ₯Ό μ λ°ν μ μλ€. λ°λΌμ μλ°μμλ μ λ€λ¦ νμ μ λν λ³μ±μ λͺ μμ μΌλ‘ νννμ¬ κ°λ°μκ° νμ μμ μ±μ μ μ§νλ©΄μ μ λ€λ¦μ μ¬μ©ν μ μλλ‘ νλ€.
1. 곡λ³μ±κ³Ό νμ μμ μ±
곡λ³μ±μ μλ€λ¦ νμ μ΄ μμ κ³μΈ΅μμ νμ νμ μΌλ‘ νμ₯λ λ μ μ©νλ€. μλ₯Ό λ€μ΄, List<? extends Number>λ Numberμ νμ νμ λ€μ λν 리μ€νΈλ₯Ό μμ νκ² μ²λ¦¬ν μ μλ€. νμ§λ§ 리μ€νΈμ μλ‘μ΄ μμλ₯Ό μΆκ°ν λλ μμ νμ§ μμ μ μμΌλ―λ‘ μ½κΈ° μ μ© λ¦¬μ€νΈμ μ€ μ¬μ©λλ€.
2. λ°κ³΅λ³μ±κ³Ό μ μ°μ±
λ°κ³΅λ³μ±μ μ λ€λ¦ νμ μ΄ μμ κ³μΈ΅μμ μμ νμ μΌλ‘ νμ₯λ λ μ μ©νλ€. μλ₯Ό λ€μ΄, Comparator<? super Integer>λ Integerμ μμ νμ λ€μ λν λΉκ΅κΈ°λ₯Ό μ¬μ©νμ¬ κ°μ²΄λ€μ λΉκ΅ν μ μλ€. μ΄λ λΉκ΅κΈ°μ μ μ°μ±μ μ¦κ°μν¨λ€.
3. μ€μ μμ
곡λ³μ±κ³Ό λ°κ³΅λ³μ±μ μλ°μ 컬λ μ νλ μμν¬μμ μμ£Ό μ¬μ©λλ€. μλ₯Ό λ€μ΄, Collections.copy λ©μλλ 곡λ³μ±κ³Ό λ°κ³΅λ³μ± λͺ¨λλ₯Ό μ¬μ©ν΄ λ§€μ° μ μ°νκ² λμνλ€.
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dest.set(i, src.get(i));
}
}
μ λ©μλλ src 리μ€νΈμμ λ°μ΄ν°λ₯Ό μ½κ³ , dest 리μ€νΈλ‘ 볡μ¬νλ€. srcλ Tμ νμ νμ μ 리μ€νΈλ‘ μ νλλ©°, destλ Tμ μμ νμ μ 리μ€νΈλ‘ μ νλλ€. μ΄ λ©μλλ λ§€μ° μ μ°νλ©°, λ€μν νμ μ 리μ€νΈλ₯Ό 볡μ¬ν λ μ¬μ©λ μ μλ€.
'λΉ κ΅¬λ© μ±μ°κΈ°' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[Java] μμΈ, μλ¬ (0) | 2024.08.27 |
---|---|
[Java] μ λ€λ¦ (1) | 2024.08.27 |
[Java] μ μ λ€λ¦μ μμ νμ μ μ¬μ©ν μ μλκ° (0) | 2024.08.27 |
[Java] λ°μ±(Boxing), μΈλ°μ±(Unboxing)μΌλ‘ μΈν΄ λ°μν μ μλ μ±λ₯ μ΄μ (0) | 2024.08.27 |
[Java] μ λ€λ¦μ νμ μκ±° Type Erasure (0) | 2024.08.27 |