5️⃣

μ™€μΌλ“œ μΉ΄λ“œ <❓>

μ™€μΌλ“œ μΉ΄λ“œ (WildCards)

 
μ œλ„€λ¦­ μ½”λ“œμ—μ„œ λ¬ΌμŒν‘œ (?) λŠ” μ™€μΌλ“œ μΉ΄λ“œλΌκ³  λΆˆλ¦°λ‹€. μ™€μΌλ“œ μΉ΄λ“œλŠ” unkonwn type 을 μ˜λ―Έν•œλ‹€.
μ™€μΌλ“œ μΉ΄λ“œλŠ” λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž…, ν•„λ“œ ν˜Ήμ€ μ§€μ—­ λ³€μˆ˜μ™€ 리턴 νƒ€μž…λ“±μ— ν™œμš©λœλ‹€.
μ™€μΌλ“œ μΉ΄λ“œλŠ” μ œλ„€λ¦­ λ©”μ„œλ“œ 호좜 ν˜Ήμ€ μ œλ„€λ¦­ 클래슀의 μΈμŠ€ν„΄μŠ€ν™”μ—λŠ” μ‚¬μš©λ  수 μ—†λ‹€.
 

Upper Bounded Wildcards

  • λ³€μˆ˜μ— λŒ€ν•œ μ œν•œμ„ μ™„ν™” ν•˜κ³  싢은 경우 Upper Bounded Wildcardsλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 예λ₯Όλ“€μ–΄ List<Integer>, List<Doublce> and List<Number> νƒ€μž…μ„ λͺ¨λ‘ 받을 수 μžˆλŠ” λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•˜κ³  싢은 경우 Upper Bounded Wildcardsλ₯Ό μ‚¬μš©ν•˜λ©΄ λ©λ‹ˆλ‹€.
 
Upper Bounded Wildcardsλ₯Ό μ„ μ–Έν•˜κΈ° μœ„ν•΄μ„œλŠ” wildcard character(’?’)에 extends ν‚€μ›Œλ“œλ₯Ό 달면 λ©λ‹ˆλ‹€. λ°”μš΄λ””λ“œ νƒ€μž… νŒŒλΌλ―Έν„°μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ 이 λ¬Έλ§₯μ—μ„œ extends λŠ” ν™•μž₯(extends)κ³Ό κ΅¬ν˜„(implements)을 ν¬κ΄„ν•©λ‹ˆλ‹€.
 
public static void process(List<? extends Foo> list) { /* ... */ }
static void process(List<? extends Foo> list) { Foo foo = list.get(0); for (Foo elem : list) { // ... } }
foreach 문의 elem λ³€μˆ˜λŠ” Foo둜 μ„ μ–Έλ˜λ©° Foo의 λ©”μ„œλ“œλ₯Ό ν™œμš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Unbounded Wildcards

  • unbounded wildcard νƒ€μž…μ€ whildcard character(’?’)의 νŠΉλ³„ν•œ μ‚¬μš©λ²•μž…λ‹ˆλ‹€.
  • 예λ₯Όλ“€μ–΄ List<?> λŠ” list of unkown type 이라고 λΆ€λ₯΄λ©° 이런 선언이 μœ μš©ν•œ 두가지 μ‹œλ‚˜λ¦¬μ˜€κ°€ μžˆμŠ΅λ‹ˆλ‹€.
    • μž‘μ„±ν•˜λ €λŠ” λ©”μ„œλ“œμ˜ κ΅¬ν˜„μ΄ Object 클래슀의 κΈ°λŠ₯만으둜 μΆ©λΆ„ν•  λ•Œ
    • μ œλ„€λ¦­ 클래슀의 λ©”μ„œλ“œλ₯Ό μž‘μ„±ν• λ•Œ λ©”μ„œλ“œμ˜ κ΅¬ν˜„μ΄ μ œλ„€λ¦­ 클래슀의 νƒ€μž… μΈμžμ— μ˜μ‘΄μ μ΄μ§€ μ•Šμ€ 경우
      • e.g. List.size or List.claer
 
μ‹œλ‚˜λ¦¬μ˜€ 1. μž‘μ„±ν•˜λ €λŠ” printList(List )의 κ΅¬ν˜„μ€ Object 클래슀의 toString λ©”μ„œλ“œ 만으둜 좩뢄함
public static void printList(List<Object> list) { for (Object elem : list) System.out.println(elem + " "); System.out.println(); }
printList λŠ” μ–΄λŠ νƒ€μž…μ΄λΌλ„ 루프λ₯Ό 돌며 좜λ ₯ν•˜κ³  μ‹Άλ‹€.
ν•˜μ§€λ§Œ μœ„μ˜ κ΅¬ν˜„μ€ κ·Έ λͺ©μ μ„ 달성할 수 μ—†λ‹€. μ•žμ„œ ν•™μŠ΅ν•˜μ˜€λ˜ μ œλ„€λ¦­κ³Ό μ„œλΈŒνƒ€μž…μ— 따라 List<Object>λŠ” List<Integer> νƒ€μž…μ„ 받을 수 μ—†κ³  ν•΄λ‹Ή λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° μœ„ν•΄μ„œλŠ” μ •ν™•νžˆ List<Object> νƒ€μž…μ˜ νŒŒλΌλ―Έν„°λ§Œ 전달 받을 수 μžˆλ‹€.
notion image
 
unbounded wildcard λ₯Ό 톡해 λͺ©μ μ„ 달성할 수 μžˆλ‹€.
public static void printList(List<?> list) { for (Object elem: list) System.out.print(elem + " "); System.out.println(); }
μž„μ˜μ˜ ꡬ체 νƒ€μž… A에 λŒ€ν•΄μ„œ List<A>λŠ” List<?> 의 μ„œλΈŒ νƒ€μž…μ΄λ‹€
notion image
 
List<Object>와 List<?>의 차이λ₯Ό μ•„λŠ”κ²ƒμ΄ μ€‘μš”ν•˜λ‹€. 이 λ‘˜μ€ μ„œλΈŒ νƒ€μž…μ— λŒ€ν•΄μ„œ 차이λ₯Ό κ°€μ§ˆ 뿐만 μ•„λ‹ˆλΌ μ‚½μž…μ— λŒ€ν•΄μ„œλ„ 차이λ₯Ό κ°€μ§„λ‹€. List<Object> μ—λŠ” Object ν˜Ήμ€ 아무 Object 의 μ„œλΈŒνƒ€μž… 객체λ₯Ό 넣을 수 μžˆμ§€λ§Œ List<?>μ—λŠ” null만 넣을 수 μžˆλ‹€.
 

Lower Bounded Wildcards
Upper Bounded Wildcards μ„Ήμ…˜μ—μ„œλŠ” Upper Bounded Wildcards κ°€ unknown type 을 νŠΉμ • νƒ€μž…μ˜ μ„œλΈŒ νƒ€μž…μœΌλ‘œ μ œν•œν•œλ‹€λŠ” 것과 그것이 extends ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ”κ²ƒμ„ μ‚΄νŽ΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€.
λΉ„μŠ·ν•˜κ²Œ Lower Bounded Wildcards λŠ” unkown type을 νŠΉμ • νƒ€μž…μ˜ 슈퍼 νƒ€μž… (λΆ€λͺ¨)둜 μ œν•œ ν•˜κ³  super ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. <? super A>
Integer 객체λ₯Ό λ¦¬μŠ€νŠΈμ— λ„£λŠ” λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•  λ•Œ Lower Bounded Wildcards λ₯Ό ν™œμš©ν•œλ‹€λ©΄ Integer 객체λ₯Ό 담을 수 μžˆλŠ” Number, Object νƒ€μž…μ˜ νŒŒλΌλ―Έν„°λ„ μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
 
public static void addNumbers(List<? super Integer> list) { for (int i = 1; i <= 10; i++) { list.add(i); } }

μ™€μΌλ“œ μΉ΄λ“œμ™€ μ„œλΈŒ νƒ€μž… Wildcards and Subtyping

notion image
보기 νž˜λ“€μ–΄μ„œ κ·Έλ¦° μ™€μΌλ“œ μΉ΄λ“œκ°€ ν¬ν•¨λœ μ œλ„€λ¦­μ˜ μ„œλΈŒ, μŠˆνΌνƒ€μž… 관계도
보기 νž˜λ“€μ–΄μ„œ κ·Έλ¦° μ™€μΌλ“œ μΉ΄λ“œκ°€ ν¬ν•¨λœ μ œλ„€λ¦­μ˜ μ„œλΈŒ, μŠˆνΌνƒ€μž… 관계도
  • 기본은 super, extends λ₯Ό λͺ¨λ‘ 슈퍼 νƒ€μž…μœΌλ‘œ 가짐
  • λκΉŒμ§€ κ°€λ©΄ κΌ­ unbounded wildcards λ₯Ό 슈퍼 νƒ€μž…μœΌλ‘œ 가짐

μ™€μΌλ“œ μΉ΄λ“œ 캑쳐와 헬퍼 λ©”μ„œλ“œ (Wildcard Capture and Helper Methods)

 
μ»΄νŒŒμΌλŸ¬κ°€ μ™€μΌλ“œ μΉ΄λ“œμ˜ νƒ€μž…μ„ μΆ”λ‘ ν•˜λŠ” κ²½μš°κ°€ μžˆλ‹€.
이λ₯Ό Wildcard Capture라고 λΆ€λ₯Έλ‹€. λŒ€λΆ€λΆ„μ˜ 경우 Wildcard CaptureλŠ” κ±±μ •ν•˜μ§€ μ•Šμ•„λ„ λ˜μ§€λ§Œ μ—λŸ¬ λ©”μ‹œμ§€μ— β€œcapture of β€œ ꡬ문이 있으면 ν•΄κ²°ν•΄ μ£Όμ–΄μ•Ό ν•œλ‹€.
 
public class WildcardError { void foo(List<?> i) { i.set(0, i.get(0));//컴파일 μ—λŸ¬ } }
java: incompatible types: java.lang.Object cannot be converted to capture#1 of ?
i.get(0)λ₯Ό ν•˜λ©΄ Object 객체λ₯Ό λ°˜ν™˜ν•˜κ³  이λ₯Ό List<?> i에 set ν•  수 μ—†λ‹€λŠ” μ—λŸ¬μ΄λ‹€. i에 넣어쀄 수 μžˆλŠ” 것은 null밖에 μ—†λ‹€.
μ œλ„€λ¦­μ„ λ„μž…ν•œ μ΄μœ μ€‘ ν•˜λ‚˜μΈ 컴파일 νƒ€μž„μ˜ μ—λŸ¬ 작기λ₯Ό μ»΄νŒŒμΌλŸ¬κ°€ μ—΄μ‹¬νžˆ μˆ˜ν–‰ν•˜κ³  있기 λ•Œλ¬Έμ— μ—λŸ¬κ°€ λ°œμƒν•˜λŠ” 것이닀.
ν•˜μ§€λ§Œ μœ„ μ½”λ“œλŠ” 리슀트의 0번째 인덱슀 값을 κΊΌλ‚΄μ„œ 0번째 μΈλ±μŠ€μ— λ„£λŠ” νƒ€μž…μ— μ „ν˜€ λ¬Έμ œκ°€ μ—†λŠ” μ½”λ“œμ΄λ‹€. 이경우 private 헬퍼 λ©”μ„œλ“œλ₯Ό 톡해 μ»΄νŒŒμΌλŸ¬μ—κ²Œ μžμ‹ μ˜ μ˜λ„λ₯Ό μ•Œλ¦΄ 수 μžˆλ‹€.
 
public class WildcardFixed { void foo(List<?> i) { fooHelper(i); } // Helper method created so that the wildcard can be captured // through type inference. private <T> void fooHelper(List<T> l) { l.set(0, l.get(0)); } }
 
 
 

Guidelines for Wildcard Use
PECS - Producer Extends Consuper Super
PECS - Producer Extends Consuper Super