πŸ‘¨πŸ»β€πŸ’» μ΄νŽ™ν‹°λΈŒ μžλ°” - μ œλ„€λ¦­

PeterΒ·2022λ…„ 3μ›” 20일
0
post-thumbnail

5μž₯ - μ œλ„€λ¦­


  • 5μž₯ μš©μ–΄ 정리
ν•œκΈ€ μš©μ–΄μ˜λ¬Έ μš©μ–΄μ˜ˆ
λ§€κ°œλ³€μˆ˜ν™” νƒ€μž…parameterized typeList<String>
μ‹€μ œ νƒ€μž… 맀개 λ³€μˆ˜actual type parameterString
μ œλ„€λ¦­ νƒ€μž…generic typeList<E>
μ •κ·œ νƒ€μž… 맀개 λ³€μˆ˜formal type parameterE
λΉ„ν•œμ •μ  μ™€μΌλ“œμΉ΄λ“œ νƒ€μž…unbounded wildcard typeList<?>
둜 νƒ€μž…raw typeList
ν•œμ •μ  νƒ€μž… λ§€κ°œλ³€μˆ˜bounded type bound<T extends Number>
μž¬κ·€μ  νƒ€μž… ν•œμ •recursive type bound<T extends Comparable<T>>
ν•œμ •μ  μ™€μΌλ“œμΉ΄λ“œ νƒ€μž…bounded wildcard typeList<? extends Number>
μ œλ„€λ¦­ λ©”μ„œλ“œgeneric methodstatic <E> List<E> asList(E[] a)
νƒ€μž… 토큰type tokenString.class

πŸ’‘ 둜 νƒ€μž…μ€ μ‚¬μš©ν•˜μ§€ 말라

β€œλ‘œ νƒ€μž…μ„ μ‚¬μš©ν•˜λ©΄ λŸ°νƒ€μž„μ— μ˜ˆμ™Έκ°€ 일어날 수 μžˆμœΌλ―€λ‘œ μ‚¬μš©ν•˜λ©΄ μ•ˆ 됨”

1. raw type μ‚¬μš©μ˜ 문제점

  • 둜 νƒ€μž…μ„ μ‚¬μš©ν•˜λ©΄ μ œλ„€λ¦­μ΄ μ•ˆκ²¨μ£ΌλŠ” νƒ€μž… μ•ˆμ •μ„±κ³Ό ν‘œν˜„λ ₯을 λͺ¨λ‘ μžƒκ²Œ 됨.
  • λ¬Έμ œκ°€ λ˜λŠ” 경우 μ˜ˆμ‹œ μ½”λ“œ
    • μ•„λž˜μ˜ μ˜ˆμ‹œλ₯Ό 톡해 둜 νƒ€μž… μ‚¬μš©μ‹œ λŸ°νƒ€μž„ μ˜ˆμ™Έκ°€ 일어날 수 μžˆμŒμ„ 확인
// Stamp μΈμŠ€ν„΄μŠ€λ§Œ μ·¨κΈ‰ν•œλ‹€.
private final Collection stamps = ...;

// stamps에 도μž₯(Stamp) λŒ€μ‹  동전(Coin)을 넣어도 아무 였λ₯˜ 없이 컴파일되고 μ‹€ν–‰ 됨
stamps.add(new Coin(...));

// μ»¬λ ‰μ…˜μ—μ„œ 이 동전을 κΊΌλ‚Ό λ•Œ, λŸ°νƒ€μž„ μ˜ˆμ™Έκ°€ λ°œμƒ
for (Iterator i = stamps.iterator(); i.hasNext();) {
		Stamp stamp = (Stamp) i.next(); // ClassCastException을 λ˜μ§„λ‹€.
		stamp.cancel();
}

2. λΉ„ν•œμ •μ  μ™€μΌλ“œ μΉ΄λ“œ : ?

  • μ œλ„€λ¦­μ˜ ν•˜μœ„ νƒ€μž… κ·œμΉ™
    • λͺ‡ 가지 μ˜ˆμ‹œ
    • String은 Object의 ν•˜μœ„ νƒ€μž…μΈκ°€? : ν•˜μœ„νƒ€μž…μ΄λ‹€.
    • List<String>은 List의 ν•˜μœ„ νƒ€μž…μΈκ°€? : ν•˜μœ„νƒ€μž…μ΄λ‹€.
    • List<String>은 List<Object>의 ν•˜μœ„ νƒ€μž…μΈκ°€? : μ•„λ‹ˆλ‹€. μƒν•˜κ΄€κ³„κ°€ μ—†λ‹€.

β†’ λ§€κ°œλ³€μˆ˜ν™” νƒ€μž…κ°„μ—λŠ” μƒν•˜κ΄€κ³„κ°€ μ—†λ‹€.

β†’ λ”°λΌμ„œ μ•„λž˜ μ½”λ“œλŠ” μ»΄νŒŒμΌλ˜μ§€ μ•ŠμŒ.

public class Raw {
    public static void main(String[] args) {
        List<String> strings = new ArrayList<>();
				// List<String>이 List<Object>의 ν•˜μœ„νƒ€μž…μ΄ μ•„λ‹˜.
        unsafeAdd(strings, "test");
    }

    private static void unsafeAdd(List<Object> list, Object o) {
        list.add(o);
    }
}
  • 그러면 μœ„μ™€ 같은 상황을 μ–΄λ–»κ²Œ ν•΄κ²°ν•˜λŠ”κ°€? : λΉ„ν•œμ •μ  μ™€μΌλ“œ μΉ΄λ“œλ₯Ό μ‚¬μš©ν•œλ‹€.
public class Raw {
    public static void main(String[] args) {
        List<String> strings = new ArrayList<>();
				// List<String>이 List<Object>의 ν•˜μœ„νƒ€μž…μ΄ μ•„λ‹˜.
        unsafeAdd(strings, "test");
    }
		// Objectλ₯Ό ?둜 λ°”κΏ”μ£Όμ—ˆμŒ.
    private static void unsafeAdd(List<?> list, Object o) {
        list.add(o);
    }
}
  • λΉ„ν•œμ •μ  μ™€μΌλ“œμΉ΄λ“œ νƒ€μž…(?)은 μ œλ„€λ¦­ νƒ€μž…μ„ μ“°κ³  μ‹Άμ§€λ§Œ μ‹€μ œ νƒ€μž… λ§€κ°œλ³€μˆ˜κ°€ 무엇인지 μ‹ κ²½μ“°κ³  싢지 μ•Šμ„ λ•Œ μ‚¬μš©.

3. raw type을 μ‚¬μš©ν•΄μ•Όν•˜λŠ” 경우

  • raw type을 μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” μ˜ˆμ™Έ κ²½μš°κ°€ 2가지 있음
  1. class λ¦¬ν„°λŸ΄μ—λŠ” 둜 νƒ€μž…μ„ 써야 함.
    • ex) List.class, String[].class, int.class κ°€λŠ₯ / List<String>.class, List<?>.class λΆˆκ°€λŠ₯
  2. instanceof μ—°μ‚°μž
    • λŸ°νƒ€μž„μ—λŠ” μ œλ„€λ¦­ νƒ€μž… 정보가 μ§€μ›Œμ§€λ―€λ‘œ instanceof μ—°μ‚°μžλŠ” λΉ„ν•œμ •μ  μ™€μΌλ“œμΉ΄λ“œ νƒ€μž… μ΄μ™Έμ˜ λ§€κ°œλ³€μˆ˜ν™” νƒ€μž…μ—λŠ” μ μš©ν•  수 μ—†μŒ.
    • λΉ„ν•œμ •μ  μ™€μΌλ“œ μΉ΄λ“œ νƒ€μž…μ΄λ“  둜 νƒ€μž…μ΄λ“  instanceofλŠ” μ™„μ „νžˆ λ˜‘κ°™μ΄ λ™μž‘ν•¨. κ·ΈλŸ¬λ‹ˆ κΉ”λ”ν•œ 둜 νƒ€μž…μ„ μ‚¬μš©ν•˜μž
    • ex) if(o instanceof Set) { ... }


πŸ’‘ 비검사 κ²½κ³ λ₯Ό μ œκ±°ν•˜λΌ

β€œλΉ„κ²€μ‚¬ κ²½κ³ λŠ” μ€‘μš”ν•˜λ‹ˆ λ¬΄μ‹œν•˜μ§€ λ§μžβ€

1. 비검사 κ²½κ³ 

  • 비검사 ν˜•λ³€ν™˜ κ²½κ³ , 비검사 λ©”μ„œλ“œ 호좜 κ²½κ³ , 비검사 λ§€κ°œλ³€μˆ˜ν™” κ°€λ³€μΈμˆ˜ νƒ€μž… κ²½κ³ , 비검사 λ³€ν™˜ κ²½κ³  등이 있음
  • 비검사 κ²½κ³  μ˜ˆμ‹œ
// νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό λͺ…μ‹œν•˜μ§€ μ•ŠμŒ : 비검사 λ³€ν™˜ κ²½κ³ 
Set<Lark> exaltation = new HashSet();

// 닀이아λͺ¬λ“œ μ—°μ‚°μž(<>)둜 ν•΄κ²° : μžλ°”7λΆ€ν„° νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό μΆ”λ‘ ν•΄ 쀌
Set<Lark> exaltation = new HashSet<>();
  • ν•  수 μžˆλŠ” ν•œ λͺ¨λ“  비검사 κ²½κ³ λ₯Ό μ œκ±°ν•˜μž.
    • λͺ¨λ‘ μ œκ±°ν•œλ‹€λ©΄ κ·Έ μ½”λ“œλŠ” νƒ€μž… μ•ˆμ •μ„± 보μž₯ β†’ λŸ°νƒ€μž„μ— ClassCastException λ°œμƒ μ ˆλŒ€ X

2. @SuppressWarnings μ–΄λ…Έν…Œμ΄μ…˜

  • κ²½κ³ λ₯Ό μ œκ±°ν•  μˆ˜λŠ” μ—†μ§€λ§Œ νƒ€μž… μ•ˆμ „ν•˜λ‹€κ³  ν™•μ‹ ν•  수 μžˆλ‹€λ©΄, @SuppressWarnings(”unchecked”) μ–΄λ…Έν…Œμ΄μ…˜μ„ 달아 κ²½κ³ λ₯Ό 숨기자.
  • @SuppressWarnings μ–΄λ…Έν…Œμ΄μ…˜μ€ 항상 κ°€λŠ₯ν•œ ν•œ 쒁은 λ²”μœ„μ— μ μš©ν•˜μž
    • λ³€μˆ˜ μ„ μ–Έ, μ•„μ£Ό 짧은 λ©”μ„œλ“œ, μƒμ„±μž λ“±
    • μ ˆλŒ€λ‘œ 클래슀 전체에 μ μš©ν•΄μ„œλŠ” μ•ˆ 됨
  • @SuppressWarnings(”unchecked”) μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•  λ•Œλ©΄ κ·Έ κ²½κ³ λ₯Ό λ¬΄μ‹œν•΄λ„ μ•ˆμ „ν•œ 이유λ₯Ό 항상 μ£Όμ„μœΌλ‘œ 남겨야 함.


πŸ’‘ λ°°μ—΄λ³΄λ‹€λŠ” 리슀트λ₯Ό μ‚¬μš©ν•˜λΌ

1. λ°°μ—΄ vs 리슀트

λ°°μ—΄λ¦¬μŠ€νŠΈ(μ œλ„€λ¦­)
문법String[]List<String>
---------
μƒν•˜κ΄€κ³„Subκ°€ Super의 ν•˜μœ„ νƒ€μž…μΌ λ•Œ,
Sub[]도 Super[]의 ν•˜μœ„ νƒ€μž…

→곡변(covariant)
Type1이 Type2의 ν•˜μœ„ νƒ€μž…μΌ λ•Œ,
List<Type1>λŠ” List<Type2>의 ν•˜μœ„ νƒ€μž…λ„ μƒμœ„ νƒ€μž…λ„ μ•„λ‹˜ (μƒν•˜κ΄€κ³„ μ—†μŒ).

β†’ λΆˆκ³΅λ³€(invariant)
---------
νƒ€μž… μ•ˆμ „μ»΄νŒŒμΌ : νƒ€μž… μ•ˆμ „ X
λŸ°νƒ€μž„ : νƒ€μž… μ•ˆμ „ O

β†’ 컴파일 μ‹œμ μ— νƒ€μž… μ•ˆμ „μ„±μ„ 보μž₯ 받지 λͺ»ν•˜μ—¬ λŸ°νƒ€μž„μ— μ˜ˆμ™Έ λ°œμƒ κ°€λŠ₯
컴파일 : νƒ€μž… μ•ˆμ „ O
λŸ°νƒ€μž„ : νƒ€μž… μ•ˆμ „ X

β†’ 컴파일 μ‹œμ μ— νƒ€μž… μ•ˆμ „μ„±μ„ 보μž₯ λ°›μŒ
---------
싀체화싀체화

β†’ λŸ°νƒ€μž„μ—λ„ μžμ‹ μ΄ λ‹΄κΈ°λ‘œ ν•œ μ›μ†Œμ˜ νƒ€μž…μ„ 인지 & 확인
싀체화 λΆˆκ°€(μ†Œκ±° λ§€μ»€λ‹ˆμ¦˜)

β†’ λŸ°νƒ€μž„μ—λŠ” μ›μ†Œμ˜ νƒ€μž… 정보λ₯Ό μ•Œ 수 μ—†μŒ(컴파일 μ‹œμ μ— νƒ€μž… 정보 μ†Œκ±°), λΉ„ν•œμ •μ  μ™€μΌλ“œ μΉ΄λ“œ νƒ€μž…μ€ μ˜ˆμ™Έ.

2. λ°°μ—΄λ³΄λ‹€λŠ” 리슀트

  • 곡변일 λ•Œ λ°œμƒν•  수 μžˆλŠ” 문제
// 배열은 κ³΅λ³€μ΄λ―€λ‘œ μ •μƒμ μœΌλ‘œ 컴파일 됨
Object[] objectArray = new Long[1];
objectArray[0] = "νƒ€μž…μ΄ 달라 넣을 수 μ—†λ‹€." // λŸ°νƒ€μž„μ— ArrayStoreException을 λ˜μ§„λ‹€
// μ œλ„€λ¦­μ€ λΆˆκ³΅λ³€μ΄λ―€λ‘œ 컴파일이 μ‹€νŒ¨ 함
List<Object> ol = new ArrayList<Long>(); // ν˜Έν™˜λ˜μ§€ μ•ŠλŠ” νƒ€μž…
ol.add("νƒ€μž…μ΄ 달라 넣을 수 μ—†λ‹€.");

β†’ 이렇듯 배열은 μ‹€μˆ˜λ₯Ό λŸ°νƒ€μž„μ—μ•Ό μ•Œκ²Œ λ˜μ§€λ§Œ, 리슀트λ₯Ό μ‚¬μš©ν•˜λ©΄ 컴파일 μ‹œμ μ— μ‹€μˆ˜λ₯Ό λ°”λ‘œ μž‘μ„ 수 있음.

  • μ£Όμš” μ°¨μ΄λ“€λ‘œ 인해 λ‘˜μ„ μ„žμ–΄ μ“°κΈ°λŠ” 어렀움. 리슀트λ₯Ό μ‚¬μš©ν•˜μž.
  • λ‘˜μ„ μ„žμ–΄ μ“°λ‹€κ°€ 였λ₯˜λ‚˜ κ²½κ³ λ₯Ό λ§Œλ‚˜λ©΄, 배열을 리슀트둜 λŒ€μ²΄ν•΄λ³΄μž.


πŸ’‘ 이왕이면 μ œλ„€λ¦­ νƒ€μž…μœΌλ‘œ λ§Œλ“€λΌ

β€œν΄λΌμ΄μ–ΈνŠΈμ—μ„œ 직접 ν˜•λ³€ν™˜ν•΄μ•Όν•˜λŠ” νƒ€μž…λ³΄λ‹€ μ œλ„€λ¦­ νƒ€μž…μ΄ 더 μ•ˆμ „ν•˜κ³  μ“°κΈ° νŽΈν•˜λ‹€β€

1. μ œλ„€λ¦­ νƒ€μž…

  • νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό μ΄μš©ν•΄ μ œλ„€λ¦­μœΌλ‘œ λ§Œλ“  μŠ€νƒ
// E[]λ₯Ό μ΄μš©ν•œ μ œλ„€λ¦­ μŠ€νƒ
public class Stack<E> {
    private E[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    // λ°°μ—΄ elementsλŠ” push(E)둜 λ„˜μ–΄μ˜¨ E μΈμŠ€ν„΄μŠ€λ§Œ λ‹΄λŠ”λ‹€.
    // λ”°λΌμ„œ νƒ€μž… μ•ˆμ „μ„±μ„ 보μž₯ν•˜μ§€λ§Œ,
    // 이 λ°°μ—΄μ˜ λŸ°νƒ€μž„ νƒ€μž…μ€ E[]κ°€ μ•„λ‹Œ Object[]λ‹€!
    @SuppressWarnings("unchecked")
    public Stack() {
        elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(E e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public E pop() {
        if (size == 0)
            throw new EmptyStackException();
        E result = elements[--size];
        elements[size] = null; // λ‹€ μ“΄ μ°Έμ‘° ν•΄μ œ
        return result;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    private void ensureCapacity() {
        if (elements.length == size)
            elements = Arrays.copyOf(elements, 2 * size + 1);
    }
}
  • μ œλ„€λ¦­ νƒ€μž…μ˜ μž₯점 : ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ 직접 ν˜•λ³€ν™˜ν•˜μ§€ μ•Šμ•„λ„ 됨.

2. ν•œμ •μ  νƒ€μž… λ§€κ°œλ³€μˆ˜

  • λŒ€λ‹€μˆ˜μ˜ μ œλ„€λ¦­ νƒ€μž…μ€ νƒ€μž… λ§€κ°œλ³€μˆ˜μ— μ•„λ¬΄λŸ° μ œμ•½μ„ 두지 μ•ŠλŠ”λ‹€.
    • Stack<Object>, Stack<String> λ“± μ–΄λ–€ μ°Έμ‘° νƒ€μž…μœΌλ‘œλ„ Stack을 λ§Œλ“€ 수 있음.
    • 단, Stack<int>처럼 κΈ°λ³Έ νƒ€μž…μ€ μ‚¬μš©ν•  수 μ—†μŒ.
  • ν•œμ •μ  νƒ€μž… λ§€κ°œλ³€μˆ˜ : ν•˜μœ„ νƒ€μž…λ§Œ 받을 수 있음
    • ex) <E extends Delayed> : java.util.concurrent.Delayed의 ν•˜μœ„ νƒ€μž…λ§Œ 받을 수 있음.


πŸ’‘ 이왕이면 μ œλ„€λ¦­ λ©”μ„œλ“œλ‘œ λ§Œλ“€λΌ

β€œν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μž…λ ₯ λ§€κ°œλ³€μˆ˜μ™€ λ°˜ν™˜κ°’μ„ λͺ…μ‹œμ μœΌλ‘œ ν˜•λ³€ν™˜ν•΄μ•Ό ν•˜λŠ” λ©”μ„œλ“œλ³΄λ‹€
μ œλ„€λ¦­ λ©”μ„œλ“œκ°€ 더 μ•ˆμ „ν•˜λ©° μ‚¬μš©ν•˜κΈ° 쉽닀”

1. μ œλ„€λ¦­ λ©”μ„œλ“œ

  • νƒ€μž… λ§€κ°œλ³€μˆ˜ λͺ©λ‘μ€ 이고, λ°˜ν™˜ νƒ€μž…μ€ Set인 μ œλ„€λ¦­ λ©”μ„œλ“œ
// μ œλ„€λ¦­ λ©”μ„œλ“œ
public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
    Set<E> result = new HashSet<>(s1);
    result.addAll(s2);
    return result;
}
  • λ‹¨μˆœν•œ μ œλ„€λ¦­ λ©”μ„œλ“œλΌλ©΄ 이 이 μ •λ„λ‘œ 좩뢄함
  • ν˜„μž¬ 이 λ©”μ„œλ“œλŠ” 집합 3개(μž…λ ₯ 2개, λ°˜ν™˜ 1개)의 νƒ€μž…μ΄ λͺ¨λ‘ κ°™μ•„μ•Ό ν•˜λŠ”λ°, ν•œμ •μ  μ™€μΌλ“œμΉ΄λ“œ νƒ€μž…μ„ μ‚¬μš©ν•˜μ—¬ 더 μœ μ—°ν•˜κ²Œ κ°œμ„ ν•  수 있음.
  • μ œλ„€λ¦­ λ©”μ„œλ“œμ˜ μž₯점 : ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μž…λ ₯ λ§€κ°œλ³€μˆ˜μ™€ λ°˜ν™˜ 값을 λͺ…μ‹œμ μœΌλ‘œ ν˜•λ³€ν™˜ν•˜μ§€ μ•Šμ•„λ„ 됨.

2. μž¬κ·€μ  νƒ€μž… ν•œμ •

  • 자기 μžμ‹ μ΄ λ“€μ–΄κ°„ ν‘œν˜„μ‹μ„ μ‚¬μš©ν•˜μ—¬ νƒ€μž… λ§€κ°œλ³€μˆ˜μ˜ ν—ˆμš© λ²”μœ„λ₯Ό ν•œμ •ν•  수 있음
  • 주둜 νƒ€μž…μ˜ μžμ—°μ  μˆœμ„œλ₯Ό μ •ν•˜λŠ” Comparable μΈν„°νŽ˜μ΄μŠ€μ™€ ν•¨κ»˜ μ“°μž„
// μ»¬λ ‰μ…˜μ—μ„œ μ΅œλŒ“κ°’μ„ λ°˜ν™˜ν•œλ‹€. - μž¬κ·€μ  νƒ€μž… ν•œμ • μ‚¬μš©
public static <E extends Comparable<E>> E max(Collection<E> c) {
    if (c.isEmpty())
        throw new IllegalArgumentException("μ»¬λ ‰μ…˜μ΄ λΉ„μ–΄ μžˆμŠ΅λ‹ˆλ‹€.");

    E result = null;
    for (E e : c)
        if (result == null || e.compareTo(result) > 0)
            result = Objects.requireNonNull(e);

    return result;
}
  • <E extends Comparable<E>> : β€œλͺ¨λ“  νƒ€μž… EλŠ” μžμ‹ κ³Ό 비ꡐ할 수 μžˆλ‹€.”


πŸ’‘ ν•œμ •μ  μ™€μΌλ“œμΉ΄λ“œλ₯Ό μ‚¬μš©ν•΄ API μœ μ—°μ„±μ„ 높이라

β€œPECSκ³΅μ‹μœΌλ‘œ APIλ₯Ό μœ μ—°ν•˜κ²Œ λ§Œλ“€μžβ€

1. PECS 곡식

  • PECS : producer-extends, consumer-super
  • λ§€κ°œλ³€μˆ˜ν™” νƒ€μž… Tκ°€ μƒμ‚°μžλΌλ©΄ <? extends T>λ₯Ό μ‚¬μš©(ν•˜μœ„νƒ€μž…μœΌλ‘œ μ œν•œ)ν•˜κ³ , μ†ŒλΉ„μžλΌλ©΄ <? super T>λ₯Ό μ‚¬μš©(μƒμœ„νƒ€μž…μœΌλ‘œ μ œν•œ)ν•˜λΌ.
  • produce-extends μ˜ˆμ‹œ
    • μƒμ„±μžλ‘œ λ„˜κ²¨μ§€λŠ” choices μ»¬λ ‰μ…˜μ€ T νƒ€μž…μ˜ 값을 μƒμ‚°ν•˜κΈ°λ§Œ ν•˜λ‹ˆ(그리고 λ‚˜μ€‘μ„ μœ„ν•΄ μ €μž₯ν•΄λ‘”λ‹€), Tλ₯Ό ν™•μž₯ν•˜λŠ” μ™€μΌλ“œμΉ΄λ“œ νƒ€μž…μ„ μ‚¬μš©ν•΄ μ„ μ–Έν•΄μ•Ό 함.
    • μ΄λ ‡κ²Œ ν•˜λ©΄ Chooser<Number>의 μƒμ„±μžμ— List<Integer>λ₯Ό λ„˜κΈΈ 수 있음.
    public class Chooser<T> {
        private final List<T> choiceList;
        private final Random rnd = new Random();

        // T μƒμ‚°μž λ§€κ°œλ³€μˆ˜μ— μ™€μΌλ“œμΉ΄λ“œ νƒ€μž… 적용
        public Chooser(Collection<? extends T> choices) {
            choiceList = new ArrayList<>(choices);
        }

        public T choose() {
            return choiceList.get(rnd.nextInt(choiceList.size()));
        }

        public static void main(String[] args) {
            List<Integer> intList = List.of(1, 2, 3, 4, 5, 6);
            Chooser<Number> chooser = new Chooser<>(intList);
            for (int i = 0; i < 10; i++) {
                Number choice = chooser.choose();
                System.out.println(choice);
            }
        }
    }
  • consumer-super μ˜ˆμ‹œ
    • μŠ€νƒμ˜ popAll의 dst λ§€κ°œλ³€μˆ˜λŠ” Stack으둜 λΆ€ν„° E μΈμŠ€ν„΄μŠ€λ₯Ό μ†ŒλΉ„ν•˜λ―€λ‘œ dst의 μ μ ˆν•œ νƒ€μž…μ€ Collection<? super E> dstμž„.
    // E μ†ŒλΉ„μž(consumer) λ§€κ°œλ³€μˆ˜μ— μ™€μΌλ“œμΉ΄λ“œ νƒ€μž… 적용
    public void popAll(Collection<? super E> dst) {
        while (!isEmpty())
            dst.add(pop());
    }

2. λΉ„ν•œμ •μ  νƒ€μž… λ§€κ°œλ³€μˆ˜ vs λΉ„ν•œμ •μ  μ™€μΌλ“œμΉ΄λ“œ

  • κΈ°λ³Έ κ·œμΉ™ : λ©”μ„œλ“œ 선언에 νƒ€μž… λ§€κ°œλ³€μˆ˜κ°€ ν•œ 번만 λ‚˜μ˜€λ©΄ μ™€μΌλ“œ μΉ΄λ“œλ‘œ λŒ€μ²΄ν•˜λΌ.
  • μ•„λž˜ μ˜ˆμ‹œμ—μ„œλŠ” κ°„λ‹¨ν•œ 두 번째 선언이 더 λ‚˜μŒ (public API에 적합)
    // swap λ©”μ„œλ“œμ˜ 두 가지 μ„ μ–Έ
    public static <E> void swap(List<E> list, int i, int j);
    public static void swap(List<?> list, int i, int j);


πŸ’‘ μ œλ„€λ¦­κ³Ό κ°€λ³€μΈμˆ˜λ₯Ό ν•¨κ»˜ μ“Έ λ•ŒλŠ” μ‹ μ€‘ν•˜λΌ

β€œμ œλ„€λ¦­κ³Ό κ°€λ³€μΈμˆ˜λ₯Ό ν˜Όμš©ν•˜λ©΄ νƒ€μž… μ•ˆμ •μ„±μ΄ 깨진닀”

1. κ°€λ³€ 인수(...)

  • λ©”μ„œλ“œμ— λ„˜κΈ°λŠ” 인수의 개수λ₯Ό ν΄λΌμ΄μ–ΈνŠΈκ°€ μ‘°μ ˆν•  수 있게 ν•΄μ€Œ.
  • κ°€λ³€μΈμˆ˜ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ κ°€λ³€μΈμˆ˜λ₯Ό λ‹΄κΈ° μœ„ν•œ 배열이 μžλ™μœΌλ‘œ ν•˜λ‚˜ 생성됨.

2. μ œλ„€λ¦­κ³Ό κ°€λ³€μΈμˆ˜μ˜ 혼용

  • μ œλ„€λ¦­κ³Ό κ°€λ³€μΈμˆ˜λ₯Ό ν˜Όμš©ν–ˆμ„ λ•Œμ˜ 문제
    • νž™ μ˜€μ—Ό(heap pollution) : λ§€κ°œλ³€μˆ˜ν™” νƒ€μž…μ˜ λ³€μˆ˜κ°€ νƒ€μž…μ΄ λ‹€λ₯Έ 객체 μ°Έμ‘°ν–ˆμ„ λ•Œ λ°œμƒ
    • μ•„λž˜ μ˜ˆμ‹œμ²˜λŸΌ νƒ€μž… μ•ˆμ •μ„±μ΄ κΉ¨μ§€λ‹ˆ μ œλ„€λ¦­ varargs λ°°μ—΄ λ§€κ°œλ³€μˆ˜μ— 값을 μ €μž₯ν•˜λŠ” 것은 μ•ˆμ „ν•˜μ§€ μ•ŠμŒ.
    // μ œλ„€λ¦­κ³Ό varargsλ₯Ό ν˜Όμš©ν•˜λ©΄ νƒ€μž… μ•ˆμ „μ„±μ΄ 깨진닀!
    static void dangerous(List<String>... stringLists) {
        List<Integer> intList = List.of(42);
        Object[] objects = stringLists;
        objects[0] = intList; // νž™ μ˜€μ—Ό λ°œμƒ
        String s = stringLists[0].get(0); // ClassCastException
    }

3. @SafeVarargs μ–΄λ…Έν…Œμ΄μ…˜

  • λ©”μ„œλ“œ μž‘μ„±μžκ°€ κ·Έ λ©”μ„œλ“œκ°€ νƒ€μž… μ•ˆμ „ν•¨μ„ 보μž₯ν•˜λŠ” μž₯치
  • μ œλ„€λ¦­μ΄λ‚˜ λ§€κ°œλ³€μˆ˜ν™” νƒ€μž…μ˜ varargs λ§€κ°œλ³€μˆ˜λ₯Ό λ°›λŠ” λͺ¨λ“  λ©”μ„œλ“œμ— @SafeVarargsλ₯Ό 달아라.
    • 이 말은 μ•ˆμ „ν•˜μ§€ μ•Šμ€ varargs λ©”μ„œλ“œλŠ” μ ˆλŒ€ μž‘μ„±ν•΄μ„œλŠ” μ•ˆλœλ‹€λŠ” λœ»μž„.
  • λ‹€μŒ 두 쑰건을 λ§Œμ‘±ν•˜λŠ” μ œλ„€λ¦­ varargs λ©”μ„œλ“œλŠ” μ•ˆμ „ν•¨
    1. varargs λ§€κ°œλ³€μˆ˜ 배열에 아무것도 μ €μž₯ν•˜μ§€ μ•ŠλŠ”λ‹€.
    2. κ·Έ λ°°μ—΄(ν˜Ήμ€ 볡제본)을 μ‹ λ’°ν•  수 μ—†λŠ” μ½”λ“œμ— λ…ΈμΆœν•˜μ§€ μ•ŠλŠ”λ‹€.
  • μ œλ„€λ¦­ varargs λ§€κ°œλ³€μˆ˜λ₯Ό μ•ˆμ „ν•˜κ²Œ μ‚¬μš©ν•˜λŠ” λ©”μ„œλ“œ μ˜ˆμ‹œ
    @SafeVarargs
    static <T> List<T> flatten(List<? extends T>... lists) {
        List<T> result = new ArrayList<>();
        for (List<? extends T> list : lists)
            result.addAll(list);
        return result;
    }

4. κ°€λ³€μΈμˆ˜ λŒ€μ‹  Listλ₯Ό μ‚¬μš©ν•˜λŠ” 방식

  • β€œλ°°μ—΄λ³΄λ‹€λŠ” 리슀트λ₯Ό μ‚¬μš©ν•˜λΌβ€λΌλŠ” 쑰언에 따라 (μ‹€μ²΄λŠ” 배열인) varargs λ§€κ°œλ³€μˆ˜λ₯Ό Listλ§€κ°œλ³€μˆ˜λ‘œ λ°”κΏ€ 수 있음
  • μ œλ„€λ¦­ varargs λ§€κ°œλ³€μˆ˜λ₯Ό List둜 λŒ€μ²΄ν•œ λ©”μ„œλ“œ μ˜ˆμ‹œ
    static <T> List<T> flatten(List<List<? extends T>> lists) {
        List<T> result = new ArrayList<>();
        for (List<? extends T> list : lists)
            result.addAll(list);
        return result;
    }


πŸ’‘ νƒ€μž… μ•ˆμ „ 이쒅 μ»¨ν…Œμ΄λ„ˆλ₯Ό κ³ λ €ν•˜λΌ

β€œμ»¨ν…Œμ΄λ„ˆμ—μ„œ λ§€κ°œλ³€μˆ˜ν™” νƒ€μž…μ˜ μˆ˜κ°€ μž„μ˜μ˜ 수라면
νƒ€μž… μ•ˆμ „ 이쒅 μ»¨ν…Œμ΄λ„ˆ νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μžβ€

1. νƒ€μž… μ•ˆμ „ 이쒅 μ»¨ν…Œμ΄λ„ˆ νŒ¨ν„΄

  • ν‚€λ₯Ό λ§€κ°œλ³€μˆ˜ν™”ν•œ λ‹€μŒ, μ»¨ν…Œμ΄λ„ˆμ— 값을 λ„£κ±°λ‚˜ λΊ„ λ•Œ λ§€κ°œλ³€μˆ˜ν™”ν•œ ν‚€λ₯Ό ν•¨κ»˜ μ œκ³΅ν•˜λŠ” 방식
  • 각 νƒ€μž…μ˜ 클래슀 객체λ₯Ό ν‚€ μ—­ν• λ‘œ μ‚¬μš©ν•˜λŠ” 예제λ₯Ό μ‚΄νŽ΄λ³΄μž
μš©μ–΄μ„€λͺ…
class λ¦¬ν„°λŸ΄String.class
class λ¦¬ν„°λŸ΄μ˜ νƒ€μž…Class
νƒ€μž… ν† ν°λ©”μ„œλ“œλ“€μ΄ μ£Όκ³  λ°›λŠ” class λ¦¬ν„°λŸ΄
  • νƒ€μž… μ•ˆμ „ 이쒅 μ»¨ν…Œμ΄λ„ˆ νŒ¨ν„΄ - API μ½”λ“œ
public class Favorites {
		public <T> void putFavorite(Class<T> type, T instance);
		public <T> T getFavorite(Class<T> type);
}
  • νƒ€μž… μ•ˆμ „ 이쒅 μ»¨ν…Œμ΄λ„ˆ νŒ¨ν„΄ - API κ΅¬ν˜„
    • cast λ©”μ„œλ“œλŠ” ν˜•λ³€ν™˜ μ—°μ‚°μžμ˜ 동적 버전이닀.
      • 주어진 μΈμˆ˜κ°€ Class 객체가 μ•Œλ €μ£ΌλŠ” νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€μΈμ§€λ₯Ό κ²€μ‚¬ν•œ λ‹€μŒ, λ§žλ‹€λ©΄ κ·Έ 인수λ₯Ό κ·ΈλŒ€λ‘œ λ°˜ν™˜, μ•„λ‹ˆλ©΄ ClassCastException을 던짐.
public class Favorites {   
    private Map<Class<?>, Object> favorites = new HashMap<>();

    // 동적 ν˜•λ³€ν™˜μœΌλ‘œ λŸ°νƒ€μž„ νƒ€μž… μ•ˆμ „μ„± 확보
    public <T> void putFavorite(Class<T> type, T instance) {
        favorites.put(Objects.requireNonNull(type), type.cast(instance));
    }
    public <T> T getFavorite(Class<T> type) {
        return type.cast(favorites.get(type));
    }
}
  • νƒ€μž… μ•ˆμ „ 이쒅 μ»¨ν…Œμ΄λ„ˆ νŒ¨ν„΄ - ν΄λΌμ΄μ–ΈνŠΈ
	
public static void main(String[] args) {
    Favorites f = new Favorites();
    
    f.putFavorite(String.class, "Java");
    f.putFavorite(Integer.class, 0xcafebabe);
    f.putFavorite(Class.class, Favorites.class);
   
    String favoriteString = f.getFavorite(String.class);
    int favoriteInteger = f.getFavorite(Integer.class);
    Class<?> favoriteClass = f.getFavorite(Class.class);
    
    System.out.printf("%s %x %s%n", favoriteString,
            favoriteInteger, favoriteClass.getName());
}
  • 이 ν”„λ‘œκ·Έλž¨μ€ Java cafebabe Favoritesλ₯Ό 좜λ ₯함.

2. ν•œμ •μ  νƒ€μž… 토큰

  • ν•œμ •μ  νƒ€μž… 토큰 : ν•œμ •μ  νƒ€μž… λ§€κ°œλ³€μˆ˜λ‚˜ ν•œμ •μ  μ™€μΌλ“œμΉ΄λ“œλ₯Ό μ‚¬μš©ν•΄ ν‘œν˜„ κ°€λŠ₯ν•œ νƒ€μž…μ„ μ œν•œν•˜λŠ” νƒ€μž… 토큰
  • μ‚¬μš© μ˜ˆμ‹œ : getAnnotation λ©”μ„œλ“œ
    • annotationType μΈμˆ˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜ νƒ€μž…μ„ λœ»ν•˜λŠ” ν•œμ •μ  νƒ€μž… 토큰이닀.
    • 이 λ©”μ„œλ“œλŠ” ν† ν°μœΌλ‘œ λͺ…μ‹œν•œ νƒ€μž…μ˜ μ–΄λ…Έν…Œμ΄μ…˜μ΄ λŒ€μƒ μš”μ†Œμ— λ‹¬λ €μžˆλ‹€λ©΄ μ–΄λ…Έν…Œμ΄μ…˜μ„ λ°˜ν™˜ν•˜κ³ , μ—†λ‹€λ©΄ null을 λ°˜ν™˜ν•¨
public <T extends Annotation> T getAnnotation(Class<T> annotationType);
profile
https://dev-peter.online/

0개의 λŒ“κΈ€