2023. 3. 15. 13:41γJAVA/Effective JAVA
[μ΄νν°λΈ μλ°] Item26. λ‘ νμ μ μ¬μ©νμ§ λ§λΌ.
https://hyejin.tistory.com/1124
μ λ² κΈμμ μ λ€λ¦ νμ μ λν μ©μ΄ μ 리λ₯Ό νκ³ , κ·Έλ¬λ©΄μ λ‘ ν°μ μ μ¬μ©νλ©΄ μμ’μ? μ΄μ μ λν΄μ μ΄μ§ μ μλλ° μ΄λ² κΈμμ μ’ λ μμΈν μμ±νλ€.
λ‘ νμ μ μ¬μ©νμ§ λ§κ³ 맀κ°λ³μν νμ μ μ¬μ©νλΌ.
List numbers = new ArrayList();
numbers.add(10);
numbers.add("whiteShip");
for (Object number : numbers) {
System.out.println("number = " + (Integer)number); // error!
}
List<Integer> numbers2 = new ArrayList<>();
numbers2.add(10);
numbers2.add("whiteShip"); // compile error λ°μ
// νλ³νλ νμ μμ
for (Integer integer : numbers2) {
System.out.println("integer = " + integer);
}
λ‘ νμ μ μ¬μ©ν μμ μμ μ 맀κ°λ³μν νμ μ μ¬μ©ν μλ μμ λ‘ μ΄μ λ₯Ό μ μ μλ€.
λ¨Όμ 맀κ°λ³μν νμ μ μ¬μ©νλ©΄ λ°νμμ΄ μλ μ»΄νμΌ μμ μ λ¬Έμ λ₯Ό μ°Ύμ μ μλ€.
λ°μμλ List<Integer> λ‘ numbersλ₯Ό μ μΈνκΈ° λλ¬Έμ μ¬κΈ°μ whiteShipμ΄λΌλ λ¬Έμμ΄μ λ£μΌλ €κ³ νλ μ»΄νμΌ μμ μμ λ°λ‘ μλ¬λ₯Ό λνλ΄ λ°νμκΉμ§ κ°μ§ μκ³ λ μλ¬λ₯Ό μμ ν μ μλ€.
κ·Έλ¦¬κ³ μ λ€λ¦μ νμ©νλ©΄ μ΄ μ λ³΄κ° μ£Όμμ΄ μλ νμ μ μΈ μ체μ λ ΉμμκΈ° λλ¬Έμ ννλ ₯μμ μ’λ€.
List numbers λ₯Ό 보면 νλλͺ μ numbers μ ν΅ν΄ λμΆ© μ§μμ ν μ μκΈ΄ νμ§λ§ μ νν μ΄λ€ κ°μ΄ λ€μ΄κ°λμ§μ λν΄μλ λ£μ΄λ΄μΌ μλ€.
νμ§λ§ List<Integer> numbers2λ₯Ό 보면 κ·Έλ₯ νλμ μ μ΄ Listλ Integerλ₯Ό λ£λꡬλ! νκ³ μ μ μλ€.
λ°λΌμ μ λ€λ¦μ νμ©νμ§ μμ λ‘νμ μ μ¬μ©νλ©΄ μμ μ±κ³Ό ννλ ₯μ μλλ€.
κ·Όλ°.. κ·Έλ λ€λ©΄ λ‘νμ μ΄ κ΅³μ΄ μ μλκ°? μ λν΄μ μλ¬Έμ κ°μ§ μ μλ€.
κ·Έλ₯ 맀κ°λ³μν νμ λ§ μ¬μ©νλ©΄ λλκ±° μλκ°?
public class Box<E /*extends Number*/> { // μ λ€λ¦ ν΄λμ€ <E> : νμ
맀κ°λ³μ extends Number : Numberλ₯Ό μμλ°μ νμ
λ§ κ°λ₯ (νμ μ μΈ νμ
맀κ°λ³μ)
private E item;
private void add(E e) {
this.item = e;
}
private E get() {
return this.item;
}
public static void main(String[] args) {
Box<Integer> box = new Box<>(); // <Integer> : μ€μ νμ
맀κ°λ³μ
box.add(10);
System.out.println(box.get() * 100);
printBox(box);
}
private static void printBox(Box<?> box) { // λΉνμ μ μμΌλ μΉ΄λ νμ
(μλ¬΄λ° νμ
μ΄λ λμμ΄ λλ€.)
System.out.println("box = " + box.get());
}
}
μ¬κΈ°μ 보면 Box<Integer>λ‘ λ§€κ°λ³μν νμ μ μ¬μ©ν΄μ boxλ₯Ό μ μΈνλ€.
build ν byte codeλ₯Ό 보면
μ»΄νμΌλ°λ 컬λ μ μμ μμλ₯Ό κΊΌλ΄λ λͺ¨λ κ³³μ 보μ΄μ§ μλ νλ³νμ μΆκ°νμ¬ μ λ μ€ν¨νμ§ μμμ 보μ₯νλ€.
Boxμ Integerκ° μλ ObjectμΈκ±Έ νμΈν μ μκ³ , κ·Έ λ€μ CHECKCASTλ₯Ό ν΅ν΄ Integerλ‘ νλ³νμ λ°λ‘ ν΄μ£Όλ κ²μ μ μ μλ€.
μ¦, μ½λ μμμλ§ μ°λ¦¬κ° μ¬μ©νκΈ° νΈνκ² λ§€κ°λ³μν νμ μ μ¬μ©νλ κ²μ΄λΌλ κ²μ΄λ€.
λν νμ μλ° λ²μ κ³Όμ νΈνμ±μ μν΄μλ λ‘νμ μ μ§μνλ€.
μλ° μ λ€λ¦μ λ°μλ€μ΄κΈ° μ κΉμ§ 10λ μ΄λΌλ μκ°μ΄ κ±Έλ ΈκΈ° λλ¬Έμ μ λ€λ¦μ΄ μμ΄ μ§ μ½λκ° μ΄λ―Έ λ§μ΄ μλ€.
λ°λΌμ κΈ°μ‘΄ μ½λλ₯Ό λͺ¨λ μμ©νκΈ° νλ©΄μ μ λ€λ¦μ μ¬μ©νλ μλ‘μ΄ μ½λμλ λ§λ¬Όλ € λμκ°μΌλ§ νλ€.
μ΄ λ§μ΄κ·Έλ μ΄μ νΈνμ±μ μν΄ λ‘ νμ μ μ§μνκ³ μ λλ¦ κ΅¬νμλ μκ±° λ°©μμ μ¬μ©νκΈ°λ‘ νλ€.
Listμ List<Object>μ μ°¨μ΄λ?
public class Raw {
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
unsafeAdd(strings, Integer.valueOf(42)); // μλͺ»λ κ°μ΄ λ€μ΄κ° μ μλ€!
String s = strings.get(0); // μ»΄νμΌλ¬κ° μλμΌλ‘ νλ³ν μ½λλ₯Ό λ£μ΄μ€λ€.
// unsafeAdd2(strings, Integer.valueOf(42)); // List<Object>μ List<String>μ λ€λ₯Έκ²μ΄κΈ° λλ¬Έμ μ μ΄μ μλ¬κ° λλ€.
}
// λ‘ νμ
μ νμ
μμ μ±μ μμλ€.
// μλνλ©΄ μ΄λ€ Listλ μΌλ¨ λ°κ³ μλͺ»λ κ°μ΄ λ€μ΄κ° νλ₯ μ΄ λ§κΈ° λλ¬Έμ΄λ€.
private static void unsafeAdd(List list, Object o) {
list.add(o);
}
// List<Object>λ
private static void unsafeAdd2(List<Object> list, Object o) {
list.add(o);
}
}
Listμ List<Object>λ κ·ΈλΌ κ°μ κ² μλκ°? ν μ μλλ° κ±°μ λΉμ·νμ§λ§ μμ μ±μ λΆλΆμμ μ°¨μ΄κ° μλ€.
Listλ μ λ€λ¦ νμ μμ μμ ν λ°μ λΊ κ²μ΄κ³ , List<Object>λ λͺ¨λ νμ μ νμ©νλ€λ μμ¬λ₯Ό μ»΄νμΌλ¬μ λͺ νν μ λ¬ν κ²μ΄λ€.
unsafeAdd λ©μλλ₯Ό 보면 Listμ strings κ° λ€μ΄κ°κ³ , 42κ° λ€μ΄κ°κ³ , stringsμμ get νλ λΆλΆμμ μλ¬κ° λλλ° μ μ΄μ κ°μ΄ λ€μ΄κ°λ λΆλΆμμ κ°μ΄ μλͺ» λ€μ΄κ°λ λ¬Έμ κ° μλ€.
κ·Έλ°λ° unsafeAdd2λ₯Ό 보면 List<Object>μ stringsλ₯Ό λ£μΌλ €κ³ νλ©΄ μλ¬κ° λλ€. μλνλ©΄ List<Object>μ List<String>μ λ€λ₯΄κΈ° λλ¬Έμ΄λ€.
Stringμ΄ Objectμ νμ ν΄λμ€λκΉ λμ§ μλ? ν μ μμ§λ§ λ€λ₯΄λ€.
맀κ°λ³μλ‘ Listλ₯Ό λ°λ λ©μλμ List<String>μ λκΈΈ μ μμ§λ§, List<Object> λ₯Ό λ°λ λ©μλμλ λκΈΈ μ μλ€. μ΄λ μ λ€λ¦ νμ νμ κ·μΉ λλ¬ΈμΌλ‘ List<String> μ Listμ νμ νμ μ΄μ§λ§ List<Object>λ μλκΈ° λλ¬Έμ΄λ€.
λ°λΌμ List<Object> κ°μ 맀κ°λ³μν νμ μ μ¬μ©ν λμ λ¬λ¦¬ Listκ°μ λ‘νμ μ μ¬μ©νλ©΄ νμ μμ μ±μ μκ² λλ€.
λν Setκ³Ό Set<?> μ°¨μ΄ μμ μμ μ±μ μλ€.
public class Numbers {
static int numElementsInCommon(Set s1, Set s2) { // μμ Setμ μμ μ±μ΄ κΉ¨μ§λ€ (μ무κ°μ΄λ λ£μ μ μμ΄μ)
int result = 0;
for (Object o : s1) {
if (s2.contains(o)) {
result ++;
}
}
return result;
}
// Set<?>μΌλ‘ μ μΈνλ©΄ 무μμ΄λ λ°μ μ μλ Set νμ
μ΄ λλ€.
static int numElementsInCommon2(Set<?> s1, Set<?> s2) { // Set<?>λ νμ’
λ₯μ νμ
λ§ λ°μ μ μλ€.
int result = 0;
for (Object o : s1) {
if (s2.contains(o)) {
result ++;
}
}
return result;
}
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
Set<?> mySet = set;
System.out.println(Numbers.numElementsInCommon(Set.of(1, 2 ,3), Set.of(1,2)));
System.out.println(Numbers.numElementsInCommon2(Set.of(1, 2 ,3), Set.of(1,2)));
}
}
Setκ³Ό Set<?> μμ λΉμ·νκΈ΄ νμ§λ§ Setμ μμ μ±μ μλ λ€λ μ μμ μ°¨μ΄κ° μλ€.
μ λ€λ¦ νμ μ μ°κ³ λ μΆμ§λ§ μ€μ νμ 맀κ°λ³μκ° λ¬΄μμΈμ§ μ κ²½ μ°κ³ μΆμ§ μλ€λ©΄ μμΌλ μΉ΄λλ₯Ό λμ μ¬μ©νλκ² μ’λ€.
Set<?> μ μ΄λ€ νμ μ΄λΌλ λ΄μ μ μλ κ°μ₯ λ²μ©μ μΈ λ§€κ°λ³μν Set νμ μ΄λ€.
λ‘ νμ 컬λ μ μμλ μ무 μμλ λ£μ μ μμ΄ νμ λΆλ³μμ νΌμνκΈ° μ¬μ΄ λ°λ©΄, Collection<?>μλ null μΈμλ μ΄λ€ μμλ λ£μ μ μλ€.
λλΆλΆμ κ²½μ°μμ λ‘νμ μ΄ μλ 맀κ°λ³μν νμ μ μ¬μ©νλ©΄ λλλ° μμΈκ° μλ€.
λ°λ‘ class 리ν°λ΄κ³Ό instanceofμ΄λ€.
public class UseRawType<E> {
private E e;
public static void main(String[] args) {
System.out.println("UseRawType.class = " + UseRawType.class);
UseRawType<String> stringUseRawType = new UseRawType<>();
System.out.println("stringUseRawType = " + (stringUseRawType instanceof UseRawType));
}
}
UserRawType<Integer>.classλΌλκ²μ μκ³ , ν΄λμ€λͺ .classλ§ κ°λ₯νλ€.
κ·Έλ¦¬κ³ instanceofλ 맀κ°λ³μν νμ μ μ§μνμ§ μκ³ λ‘νμ μΌλ‘ μ¬μ©ν΄μΌ νλ€.
π μ 리
class 리ν°λ΄κ³Ό instanceof μμΈλ₯Ό μ μΈνκ³ λ λ‘ νμ μ μ¬μ©νλ©΄ μμ μ±κ³Ό ννλ ₯μ μκΈ° λλ¬Έμ 맀κ°λ³μν νμ μ μ¬μ©νμ!!
λ‘ νμ μ μ¬μ©νλ©΄ λ°νμ μλ¬κ° μΌμ΄λ μ μκΈ° λλ¬Έμ μ¬μ©νλ©΄ μλλ€. λ‘ νμ μ κ·Έμ μ λ€λ¦μ΄ λμ λκΈ° μ μ μ΄μ μ½λμμ νΈνμ±μ μν΄ μ 곡λμμ λΏμ΄λ€!
Set<Object>λ μ΄λ€ νμ μ κ°μ²΄λ μ μ₯ν μ μλ 맀κ°λ³μν νμ
Set<?> λ λͺ¨μ’ μ νμ κ°μ²΄λ§ μ μ₯ν μ μλ μμΌλ μΉ΄λ νμ
Sest μ λ‘ νμ μΌλ‘ μ λ€λ¦ νμ μμ€ν μ μνμ§ μλλ€.
Set<Object>μ Set<?> λ μμ νμ§λ§, λ‘ νμ μ μμ νμ§ μλ€.
νκΈ μ©μ΄ | μλ¬Έ μ©μ΄ | μ |
맀κ°λ³μν νμ | paramterized type | List<String> |
μ€μ νμ 맀κ°λ³μ | actual type paramteter | String |
μ λ€λ¦ νμ | generic type | List<E> |
μ κ· νμ 맀κ°λ³μ | formal type paramteter | E |
λΉνμ μ μμΌλ μΉ΄λ νμ | unbounded wildcard type | List<?> |
λ‘ νμ | raw type | List |
νμ μ νμ 맀κ°λ³μ | bounded type paramter | <E extends Number> |
μ¬κ·μ νμ νμ | recursive type bound | <T extends Comparable<T>> |
νμ μ μμΌλ μΉ΄λ νμ | bounded wildcard type | List<? extends Number> |
μ λ€λ¦ λ©μλ | generic method | static <E> List<E> |
νμ ν ν° | type token | String.class |