Programming/Java

F013 - Generic

osean 2021. 5. 26. 03:10
✍️ κ΅­λΉ„ ν•™μ›μ—μ„œ ν”„λ‘œμ νŠΈλ₯Ό 진행할 λ•Œ Map μžλ£Œκ΅¬μ‘°κ°€ 뭔지도 λͺ°λžλ˜ μ‹œμ ˆ, μ„œλ‘œ λ‹€λ₯Έ 객체λ₯Ό Object 배열에 λ‹΄μ•„ 직접 ν˜•λ³€ν™˜μ„ ν•΄μ„œ 데이터λ₯Ό μ‘°μž‘ν–ˆλ˜ 기얡이 μžˆλŠ”λ°, 이 λ•Œ ν˜•λ³€ν™˜μ„ 자꾸 잘λͺ»ν•΄μ„œ λŸ°νƒ€μž„ μ—λŸ¬κ°€ 계속 λ‚¬λ˜ κ²½ν—˜μ΄ 생각났닀.
과거에 λ§ˆμ£Όν–ˆλ˜ λ¬Έμ œλ“€μ„ μƒκΈ°ν•˜κ³ , μ™œ ν•΄λ‹Ή κ°œλ…μ΄ ν•„μš”ν•œμ§€ 이번 ν•™μŠ΅μ„ 톡해 μ•Œμ•„κ°€λŠ” μ‹œκ°„μ„ κ°€μ Έλ³΄μž.

Generic

Genericμ΄λž€ λ‹¨μ–΄μ˜ 사전적 μ˜λ―ΈλŠ” '포괄적인' μ΄λΌλŠ” λœ»μ΄λ‹€. 단어 뜻 κ·ΈλŒ€λ‘œ ν΄λž˜μŠ€μ— λ‹΄κΈΈ κ°μ²΄λ‚˜ λ©”μ†Œλ“œ, μƒμ„±μžμ˜ 맀개 λ³€μˆ˜μ˜ μ’…λ₯˜λ₯Ό νŠΉμ • 클래슀λ₯Ό μ§€μ •ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, 포괄적인 의미의 단어λ₯Ό μ‚¬μš©ν•΄ λ‹΄κΈΈ 객체의 μ’…λ₯˜μ— λŒ€ν•΄μ„œ μ—΄μ–΄λ‘”λ‹€λŠ” 의미둜 μ‚¬μš©ν•œλ‹€.

즉, Generic은 컴파일 νƒ€μž„μ—μ„œ ν΄λž˜μŠ€μ— λ‹΄κΈΈ 객체의 ν˜•νƒœμ— ν•΄λ‹Ή ν΄λž˜μŠ€μ— λ‹΄κΈΈ ν˜•νƒœμ™€ λ§žλŠ”μ§€ ν™•μΈν•˜λŠ” 역할을 ν•œλ‹€. μ΄λŠ” κ°œλ°œμžκ°€ 직접 ν˜•λ³€ν™˜μ„ ν•΄μ•Όν•˜λŠ” μˆ˜κ³ λ‘œμ›€μ„ 덜고, ν”„λ‘œκ·Έλž¨ 컴파일 μ‹œμ— ν˜•νƒœλ₯Ό ν™•μΈν•˜κ³  λ§žμ§€ μ•Šμ„ 경우 μ˜ˆμ™Έλ₯Ό λ˜μ§€κΈ° λ•Œλ¬Έμ— 이λ₯Ό ν•΄κ²°ν•˜λŠ” 것도 λŸ°νƒ€μž„ μ‹œ μ˜ˆμ™Έλ₯Ό λ˜μ§€λŠ” 것보닀 훨씬 μˆ˜μ›”ν•˜λ‹€.

...
public class GenericTest {
    public static void main(String[] args) {

        List list = new ArrayList();
        list.add(100);
        list.add(200);
        list.add("300");
				String value1 = (String) list.get(1);
        Integer value2 = (Integer) list.get(2);
        System.out.println("λ¬Έμžμ—΄ list[1] : " + value1);
        System.out.println("μ •μˆ˜ list[2] : " + value2);
    }
}

μœ„μ˜ μ½”λ“œλŠ” Generic이 λ“±μž₯ν•˜κΈ° 이전에 μ‚¬μš©ν•˜λ˜ λ°©μ‹μ˜ μ½”λ“œλ₯Ό κ°„λ‹¨ν•˜κ²Œ μž‘μ„±ν•œ 것이닀. List κ°μ²΄λŠ” ArrayList 클래슀둜 κ΅¬ν˜„λ˜μ—ˆμ§€λ§Œ ν•΄λ‹Ή 리슀트 내뢀에 μ–΄λ–€ νƒ€μž…μ˜ 데이터가 λ“€μ–΄κ°ˆμ§€ μ•Œ 수 μ—†λŠ” 상황이기 λ•Œλ¬Έμ— List 객체 λ‚΄μ—λŠ” μ•„λ¬΄λŸ° μ°Έμ‘° μžλ£Œν˜•μœΌλ‘œ μ„ΈνŒ…λ  수 μžˆλ‹€.
(좔후에 Collection.List λ‚΄λΆ€ ꡬ쑰에 λŒ€ν•΄ μžμ„Ένžˆ μ•Œμ•„λ³΄μž.)

ByteCode

...
  // access flags 0x9
  public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 9 L0
    NEW java/util/ArrayList
    DUP
    INVOKESPECIAL java/util/ArrayList.<init> ()V
    ASTORE 1
   L1
    LINENUMBER 10 L1
    ALOAD 1
    BIPUSH 100
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    INVOKEINTERFACE java/util/List.add (Ljava/lang/Object;)Z (itf)
    POP
		...
   L4
    LINENUMBER 14 L4
    ALOAD 1
    ICONST_1
    INVOKEINTERFACE java/util/List.get (I)Ljava/lang/Object; (itf)
    CHECKCAST java/lang/String
    ASTORE 2
	  ...
}

ByteCodeλ₯Ό μ‚΄νŽ΄λ³΄μž. ν•΄λ‹Ή μ½”λ“œμ˜ 상단에 보면 List의 add() λ©”μ†Œλ“œμ™€ get() λ©”μ†Œλ“œκ°€ 호좜될 λ•Œ 맀개 λ³€μˆ˜μ˜ 인자둜 μ„€μ •ν•œ λ¦¬ν„°λŸ΄ 데이터가 μ»΄νŒŒμΌλŸ¬μ— μ˜ν•΄ Object둜 λ³€κ²½λ˜μ–΄ λ„˜μ–΄κ°€λŠ” 것을 확인 ν•  수 μžˆλ‹€. μ΄λŠ” λͺ¨λ“  μ°Έμ‘° μžλ£Œν˜•μ€ μ΅œμƒμœ„ μ‘°μƒμœΌλ‘œ Objectλ₯Ό 상속 λ°›κ³  μžˆμ–΄ List에 담을 λ•Œ, λ‹΄κΈ°λŠ” 객체듀이 Object둜 List에 λ‹΄κΈ°λŠ” 것이닀.

각기 λ‹€λ₯Έ μ°Έμ‘° μžλ£Œν˜•μ„ νƒ€μž…μ΄ μ„ μ–Έλ˜μ§€ μ•Šμ€ List에 λ‹΄λŠ” 것은 생각보닀 큰 λ¬Έμ œλŠ” μ•„λ‹ˆμ§€λ§Œ, ν•΄λ‹Ή List에 λ‹΄κΈ΄ 값을 κΊΌλ‚΄μ–΄ μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” κ²½μš°μ—λŠ” 큰 λ¬Έμ œμ΄λ‹€.

첫 번째 μ†ŒμŠ€μ½”λ“œκ°€ λ°”λ‘œ 문제의 μ˜ˆμ‹œμΈλ°, μ–΄μ¨Œλ“  집어 넣은 λ°μ΄ν„°λŠ” Object둜 λ™μΌν•˜κΈ° λ•Œλ¬Έμ— μ»΄νŒŒμΌλŸ¬λŠ” 문제라고 νŒλ‹¨ν•˜μ§€ μ•Šμ•„ μ»΄νŒŒμΌν•œ 클래슀 νŒŒμΌμ„ Runtime Data Area둜 λ„˜κΈΈ 것이닀. 이 λ•Œ λ¬Έμ œκ°€ λ°œμƒν•˜λŠ”λ° main() λ©”μ†Œλ“œ 호좜 μ‹œ, list λ³€μˆ˜μ˜ 데이터λ₯Ό 지역 λ³€μˆ˜λ‘œ μ„ μ–Έν•  value1, value2의 νƒ€μž…μ— λ§žμ§€ μ•Šκ²Œ μΊμŠ€νŒ… ν–ˆκΈ° λ•Œλ¬Έμ— JVM은 ClassCastException μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚¨λ‹€.

μ΄λ ‡κ²Œ λ‹¨μˆœν•œ ν˜•λ³€ν™˜μœΌλ‘œ 인해 λŸ°νƒ€μž„ μ‹œ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λŠ” 것은 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μš΄μ˜μ— μžˆμ–΄ 큰 λ¬Έμ œμ΄λ‹€. λ•Œλ¬Έμ— Generic은 μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κ³ , μ˜³μ§€ μ•Šμ€ νƒ€μž…μ„ λŒ€μž… ν–ˆμ„ λ•Œ 컴파일 μ—λŸ¬λ₯Ό λ°œμƒμ‹œμΌœ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 운영 이전에 κ°œλ°œμžκ°€ 문제의 μ˜μ—­μ„ 사전에 μˆ˜μ • ν•  수 μžˆλ‹€.

Java 5 이후에 λ“±μž₯ν•œ Generic은 λ‹€μ–‘ν•œ ν΄λž˜μŠ€μ— μ •μ˜λ˜μ–΄ μžˆλŠ”λ° λŒ€ν‘œμ μΈ μ˜ˆκ°€ 자주 μ‚¬μš©ν•˜λŠ” ArrayList<E> ν΄λž˜μŠ€μ΄λ‹€. κ·Έλ ‡λ‹€λ©΄ <> μ•ˆμ— λ“€μ–΄μžˆλŠ” 각기 λ‹€λ₯Έ μΊλ¦­ν„°λŠ” 무엇을 μ˜λ―Έν• κΉŒ?

Generic Type

사싀 Generic의 <> μ•ˆμ—λŠ” μ–΄λ–€ 문자λ₯Ό 넣어도 상관없이 μ‚¬μš© κ°€λŠ₯ν•˜λ‹€.

public class Generic<Type> {
        public Type type;

        public Generic(Type type) {
            this.type = type;
        }
    }

ν•˜μ§€λ§Œ μ΄λ ‡κ²Œ 톡일성 μ—†λŠ” 문자둜 Generic νƒ€μž…μ„ λͺ…μ„Έν•˜λ©΄ μ˜λ―Έκ°€ μ™œκ³‘λ˜κ±°λ‚˜ μ˜λ„μ™€λŠ” λ‹€λ₯΄κ²Œ ν•΄λ‹Ή ν΄λž˜μŠ€κ°€ μ‚¬μš©λ  수 μžˆλ‹€. μ΄λŸ¬ν•œ λΆ€λΆ„μ—μ„œ λ°œμƒν•˜λŠ” 문제λ₯Ό 사전에 μ˜ˆλ°©ν•˜κΈ° μœ„ν•΄ λͺ‡ 가지 κ·œμΉ™μ΄ μ‘΄μž¬ν•œλ‹€.

βœ”οΈ E : Element의 μ•½μž. μš”μ†Œμ˜ 의미λ₯Ό 가지며 주둜 Java Collectionμ—μ„œ 주둜 μ‚¬μš©λœλ‹€.

βœ”οΈ T : Type

βœ”οΈ N : Number

βœ”οΈ V : Value

βœ”οΈ K : Key

βœ”οΈ S, U, V : 두 번째, μ„Έ 번째둜 μ •μ˜ν•˜λŠ” Generic

ν•΄λ‹Ή κ·œμΉ™μ„ κΌ­ μ§€μΌœμ•Ό ν•  μ˜λ¬΄λŠ” μ—†μ§€λ§Œ λˆ„κ΅¬λ‚˜ μ΄ν•΄ν•˜κΈ° μ‰¬μš°λ €λ©΄ λ”°λ₯΄λŠ” 것이 μ’‹κ² λ‹€. 그런데 μ’…μ’… Generic에 ? 둜 μ„€μ •λ˜μ–΄ μžˆλŠ” 것을 λ³Ό 수 μžˆλŠ”λ° ? κ°€ μ˜λ―Έν•˜λŠ” 것은 무엇이고 μ–΄λ–€ μš©λ„λ‘œ μ‚¬μš©λ κΉŒ?

Wild Card '?'

public class WildCardTest {
    public static void main(String[] args) {
        WildCardTest test = new WildCardTest();

        ArrayList<Integer> arr = new ArrayList<Integer>();
        arr.add(1);
        arr.add(2);
        arr.add(3);
        test.wildCardTest(arr);

        List<String> linked = new LinkedList<String>();
        linked.add("a");
        linked.add("b");
        linked.add("c");
        test.wildCardTest(linked);
    }

    public void wildCardTest(List<?> list) {
        System.out.println("ν˜„μž¬ 클래슀 : " + list.getClass());
        for (Object obj : list) {
            System.out.println(obj.getClass());
        }
    }
}
/*
	ν˜„μž¬ 클래슀 : class java.util.ArrayList
	class java.lang.Integer
	class java.lang.Integer
	class java.lang.Integer

	ν˜„μž¬ 클래슀 : class java.util.LinkedList
	class java.lang.String
	class java.lang.String
	class java.lang.String
*/

Generic은 λ©”μ†Œλ“œμ˜ 맀개 λ³€μˆ˜ 인자둜 λ°›λŠ” 객체 쀑, Generic이 μ •μ˜λ˜μ–΄ μžˆλŠ” 객체의 νƒ€μž…μ—λ„ 적용 ν•  수 μžˆλ‹€.

WildCardTest ν΄λž˜μŠ€μ— μ •μ˜λœ wildCardTest λ©”μ†Œλ“œλ₯Ό ν™•μΈν•΄λ³΄μž. 맀개 λ³€μˆ˜ 인자둜 λ°›λŠ” List 객체의 νƒ€μž…μ΄ ? 둜 μ„ μ–Έλ˜μ–΄ μžˆλŠ”λ°, ? λŠ” Wild Card의 의미둜 μ‚¬μš©λœλ‹€. 이λ₯Ό ν†΅ν•΄μ„œ 객체가 Generic이 μ •μ˜κ°€ λ˜μ–΄ μžˆλ‹€λ©΄ 맀개 λ³€μˆ˜μ—μ„œλ„ Generic을 μ •μ˜ ν•  수 μžˆλ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€.

κ·Έλž˜μ„œ main() λ©”μ†Œλ“œμ— μ •μ˜λœ ArrayList와 LinkedList의 νƒ€μž…μ΄ λ‹€λ₯΄μ§€λ§Œ wildCardTest() λ©”μ†Œλ“œμ— 맀개 λ³€μˆ˜λ‘œ 넣어도 별닀λ₯Έ 컴파일 μ—λŸ¬λ‚˜ λŸ°νƒ€μž„ μ—λŸ¬ 없이 μ‹€ν–‰λœλ‹€.

λ‹€λ§Œ 맀개 λ³€μˆ˜λ₯Ό ? 둜 μ •μ˜ ν•  경우, λ©”μ†Œλ“œ μŠ€μ½”ν”„ λ‚΄μ—μ„œ 맀개 λ³€μˆ˜ κ°μ²΄λŠ” Object둜 μ •μ˜λ˜κΈ°μ— 객체의 νƒ€μž…μ΄ μ–΄λ–€ νƒ€μž…μΈμ§€ μ•Œκ³  μžˆλ‹€λ©΄ instanceof μ˜ˆμ•½μ–΄λ₯Ό μ΄μš©ν•΄ ν•΄λ‹Ή νƒ€μž…μ΄ λ§žλŠ”μ§€ 검증을 ν•œ 후에 μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

λ˜ν•œ, ? 은 맀개 λ³€μˆ˜λΏλ§Œ μ•„λ‹ˆλΌ 지역 λ³€μˆ˜λ‚˜ ν•„λ“œμ—μ„œλ„ 선언은 κ°€λŠ₯ν•˜λ‹€. ν•˜μ§€λ§Œ ν•΄λ‹Ή μ˜μ—­μ—μ„œ μ‚¬μš©ν•  경우 νƒ€μž… μ•ˆμ •μ„±μ΄ 떨어지기 λ•Œλ¬Έμ— 컴파일 μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚€λŠ”λ°, κ·Έ μ΄μœ λŠ” 객체의 νƒ€μž…μ΄ 무엇인지 μ•Œμ§€ λͺ»ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€. 즉, ? 은 인자둜 λ„˜μ–΄μ˜¨ 데이터λ₯Ό μ½λŠ” 것은 κ°€λŠ₯ν•˜μ§€λ§Œ μ“°λŠ” 것은 λΆˆκ°€λŠ₯ν•˜λ‹€.

public class WildCardTest {
	
		public List<?> list;

    public static void main(String[] args) {
        WildCardTest test = new WildCardTest();
				...
				test.list.add("1"); // 컴파일 μ—λŸ¬ λ°œμƒ
    }
...
}
/*
	java: no suitable method found for add(int)
	    method java.util.Collection.add(capture#1 of ?) is not applicable
	      (argument mismatch; int cannot be converted to capture#1 of ?)
	    method java.util.List.add(capture#1 of ?) is not applicable
	      (argument mismatch; int cannot be converted to capture#1 of ?)
*/

Bounded Wild Card

public class BoundedWildCardTest {

    public static void main(String[] args) {
        List<Parent> parents = new ArrayList<>();
        parents.add(new Parent(1));
        parents.add(new Parent(2));
        parents.add(new Child(3));

        List<Child> children = new ArrayList<>();
        children.add(new Child(1));
        children.add(new Child(2));
        children.add(new Child(3));

        List<String> stringList = new ArrayList<>();
        stringList.add("a");
        stringList.add("b");
        stringList.add("c");

        BoundedWildCardTest test = new BoundedWildCardTest();
        test.boundedTest(parents);
        test.boundedTest(children);
        test.boundedTest(stringList); // 컴파일 μ—λŸ¬ λ°œμƒ
    }

    public void boundedTest(List<? extends Parent> list) {
        System.out.println(list.getClass());

        for (Parent obj : list) {
            System.out.println(obj.toString());
        }
    }
}

μ•žμ—μ„œ ?(μ΄ν•˜ Wild Card)에 λŒ€ν•΄μ„œ κ³΅λΆ€ν–ˆλ‹€. Wild CardλŠ” μ–΄λ–€ νƒ€μž…μ˜ μΈμžκ°€ 와도 관계가 μ—†μ–΄ μ–΄λ–€ κ΄€μ μ—μ„œλŠ” νŽΈν• μ§€ λͺ°λΌλ„, λ‹€λ₯Έ κ΄€μ μ—μ„œ 바라본닀면 μ μ ˆν•œ ν†΅μ œκ°€ 이뀄지지 μ•ŠκΈ° λ•Œλ¬Έμ— μ˜ˆμƒν•˜μ§€ λͺ»ν•œ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€.

μ΄λŸ¬ν•œ Wild Cardλ₯Ό μ–΄λŠμ •λ„ ν†΅μ œν•˜κΈ° μœ„ν•΄ extends λΌλŠ” μ˜ˆμ•½μ–΄κ°€ μ‘΄μž¬ν•˜λŠ”λ°, μ΄λŠ” Bounded Wild Card라고 ν•˜λ©°, 클래슀 μƒμ†μ˜ κ°œλ…μ²˜λŸΌ μ§€μ •λœ 클래슀λ₯Ό ν¬ν•¨ν•˜μ—¬ ν•˜μœ„ 클래슀만 ν—ˆμš© ν•  수 μžˆλ„λ‘ ν•œλ‹€.

μœ„ μ½”λ“œλ₯Ό 확인해보면, boundedTest() λ©”μ†Œλ“œμ˜ 맀개 λ³€μˆ˜λ‘œ List 객체λ₯Ό λ°›λŠ”λ°, 이 λ•Œ <? extends Parent>둜 νƒ€μž…μ˜ μ œν•œμ΄ μ •μ˜λ˜μ–΄ μžˆλ‹€. μ΄λŠ” List 객체의 νƒ€μž…μ΄ Parent 객체λ₯Ό ν¬ν•¨ν•œ ν•˜μœ„ μžμ‹ κ°μ²΄λ“€λ§Œ 맀개 λ³€μˆ˜λ‘œ ν—ˆμš©ν•˜κ² λ‹€λŠ” 의미이기 λ•Œλ¬Έμ—, String νƒ€μž…μ˜ List κ°μ²΄λŠ” boundedTest() λ©”μ†Œλ“œμ˜ 맀개 λ³€μˆ˜ 인자둜 μ„€μ • ν•  수 μ—†λ‹€.

λ˜ν•œ Bounded Wild Cardμ—λŠ” extends 와 λ°˜λŒ€λ˜λŠ” super μ˜ˆμ•½μ–΄κ°€ μ‘΄μž¬ν•œλ‹€. ν•΄λ‹Ή Bounded Wild CardλŠ” Lower Bounded Card, extends의 κ²½μš°λŠ” Higher Wild Card라고 μΉ­ν•œλ‹€.

πŸ“ Higher Bounded Card : νƒ€μž…μ˜ λŒ€μƒμ΄ 될 객체의 μžμ‹ κ°μ²΄λ“€κΉŒμ§€ νƒ€μž…μœΌλ‘œ ν—ˆμš© ν•  수 μžˆλ‹€.

πŸ“ Lower Bounded Card : νƒ€μž…μ˜ λŒ€μƒμ΄ 될 객체의 λΆ€λͺ¨ κ°μ²΄λ“€κΉŒμ§€ νƒ€μž…μœΌλ‘œ ν—ˆμš© ν•  수 μžˆλ‹€.

Generic Method

public class BoundedWildCardTest {

    public static void main(String[] args) {
        List<Parent> parents = new ArrayList<>();
        ...

        List<Child> children = new ArrayList<>();
        ...

        List<String> stringList = new ArrayList<>();
        ...

        BoundedWildCardTest test = new BoundedWildCardTest();

        test.genericMethod(parents, new Parent(4));
        test.genericMethod(children, new Child(4));
        test.genericMethod(stringList, "abc");
    }

    public <T> void genericMethod(List<T> list, T type) {
        System.out.println("리슀트 νƒ€μž… : " + list.getClass());
        System.out.println("T : " + type.getClass());

        list.add(type);

        for (Object obj : list) {
            System.out.println(obj.toString());
        }
    }
}

Wild Card νŒŒνŠΈμ—μ„œ Wild CardλŠ” 인자둜 λ„˜μ–΄μ˜¨ 데이터λ₯Ό μ½λŠ” 것은 κ°€λŠ₯ν•˜μ§€λ§Œ μ“°λŠ” 것은 λΆˆκ°€λŠ₯ν•˜λ‹€κ³  ν–ˆλ‹€. ν•˜μ§€λ§Œ μ™„μ „νžˆ λΆˆκ°€λŠ₯ν•œ 것은 μ•„λ‹ˆλ‹€. λ©”μ†Œλ“œμ— Generic Type을 μ§€μ •ν•œλ‹€λ©΄ 맀개 λ³€μˆ˜ 인자둜 μ „λ‹¬λœ 객체의 μ“°κΈ°κ°€ κ°€λŠ₯ν•˜λ‹€.

Generic Type Erasure

μ•žμ„œ κ³΅λΆ€ν•œ λ‚΄μš©μ„ λ‹€μ‹œ λ˜μ§šμ–΄λ³΄μž. Generic이 λ“±μž₯ν•˜κΈ° μ „μ—λŠ” ν˜•λ³€ν™˜μ— λŒ€ν•œ νƒ€μž… 체크가 λŸ°νƒ€μž„μ—μ„œ μΌμ–΄λ‚˜κΈ° λ•Œλ¬Έμ— λ§Žμ€ λ¬Έμ œμ μ„ λ°œμƒμ‹œμΌœ 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œ Generic의 κ°œλ…μ΄ λ„μž…λ˜μ—ˆκ³ , λ“±μž₯ μ΄ν›„λΆ€ν„°λŠ” 컴파일 νƒ€μž„μ—μ„œ κ°•ν•œ νƒ€μž… 체크가 μΌμ–΄λ‚˜ λŸ°νƒ€μž„ 전에 문제λ₯Ό ν•΄κ²° ν•  수 있게 λ˜μ—ˆλ‹€.

μ–΄λ–»κ²Œ Generic의 κ°•ν•œ νƒ€μž… μ²΄ν¬λŠ” 컴파일 μ‹œμ μ—μ„œ 확인 ν•  수 μžˆλŠ” κ²ƒμΌκΉŒ? Generic은 μ†Œκ±° ν”„λ‘œμ„ΈμŠ€λ₯Ό μ μš©ν•˜μ—¬ μž‘λ™λ˜λŠ”λ°, μ΄λŠ” 컴파일 μ‹œμ μ—μ„œ νƒ€μž… 체크λ₯Ό μˆ˜ν–‰ν•œ ν›„ ν•΄λ‹Ή 객체의 νƒ€μž… 정보λ₯Ό λŸ°νƒ€μž„ μ‹œμ κΉŒμ§€ 가져가지 μ•ŠλŠ” 것을 μ˜λ―Έν•œλ‹€.

이λ₯Ό Type Erasure라고 λΆ€λ₯΄λŠ”데, λ°”μ΄νŠΈ μ½”λ“œλ₯Ό 확인해보면 νƒ€μž…μ΄ μ„€μ •λœ λͺ¨λ“  κ°μ²΄λ“€μ˜ νƒ€μž… 정보가 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 것을 확인 ν•  수 μžˆλ‹€.

...
	 L14
    LINENUMBER 26 L14
    ALOAD 4
    ALOAD 2
    INVOKEVIRTUAL generic/BoundedWildCardTest.boundedTest (Ljava/util/List;)V
   L15
    LINENUMBER 28 L15
    ALOAD 4
    ALOAD 1
    NEW generic/Parent
    DUP
    ICONST_4
    INVOKESPECIAL generic/Parent.<init> (I)V
    INVOKEVIRTUAL generic/BoundedWildCardTest.genericMethod (Ljava/util/List;Ljava/lang/Object;)V
...

Type ErasureλŠ” μ•„λž˜μ™€ 같은 λ°©μ‹μœΌλ‘œ 컴파일 νƒ€μž„μ—μ„œ νƒ€μž… 체크 μˆ˜ν–‰ ν›„, 객체의 νƒ€μž…μ„ μ†Œκ±°ν•œλ‹€.

πŸ’₯ 컴파일 μ‹œ, Generic이 적용된 κ°μ²΄μ—μ„œλŠ” ν•΄λ‹Ήν•˜λŠ” νƒ€μž… νŒŒλΌλ―Έν„°(void example(T t))λ‚˜ Object둜 λ³€κ²½ν•΄μ€€λ‹€.

πŸ’₯ λ§Œμ•½ Generic Type이 Object둜 λ³€κ²½λ˜μ—ˆλ‹€λ©΄ ν—ˆμš© κ°€λŠ₯ν•œ νƒ€μž…μ— μ œν•œμ΄ μ—†λ‹€λŠ” 의미(unbounded)둜, Type Erasure κ·œμΉ™μ— λŒ€ν•œ Generic이 적용 κ°€λŠ₯ν•œ λ²”μœ„λŠ” 일반적인 ν΄λž˜μŠ€λ‚˜ λ©”μ†Œλ“œ ν˜Ήμ€ μΈν„°νŽ˜μ΄μŠ€λ§Œ ν•΄λ‹Ήλœλ‹€.

πŸ’₯ Generic은 ν¬μš©μ„±μ„ 띄기 λ•Œλ¬Έμ—, λ‹€ν˜•μ‹±μ΄ 깨질 수 μžˆλ‹€. λ•Œλ¬Έμ— μ•žμ„œ 배운 Generic Methodλ₯Ό ν™œμš©ν•˜μ—¬ Bridge Methodλ₯Ό 생성해 νƒ€μž… 지정을 λŒ€μ²΄ν•œλ‹€.

πŸ’₯λ§Œμ•½ Generic이 Bounded ν•˜κ²Œ 섀정될 경우, μ»΄νŒŒμΌλŸ¬λŠ” ν•΄λ‹Ή 객체의 νƒ€μž…μ„ Objectκ°€ μ•„λ‹Œ Comparble<E>둜 λ³€κ²½ν•œλ‹€.

βœ”οΈ μ œλ„€λ¦­μ„ μ‚¬μš©ν•˜λŠ” κ°μ²΄λŠ” λŒ€λΆ€λΆ„ 싀체화 λΆˆκ°€ νƒ€μž…, Object[] 같은 κ°μ²΄λŠ” 싀체화 νƒ€μž…μ΄λΌκ³  ν•˜λŠ”λ°, 싀체화 νƒ€μž…μ˜ 경우 λŸ°νƒ€μž„ 쀑 μ˜¬λ°”λ₯΄μ§€ μ•Šμ€ νƒ€μž…μœΌλ‘œ μΊμŠ€νŒ… 될 경우 λŸ°νƒ€μž„ μ—λŸ¬κ°€ λ°œμƒ ν•  수 있기 λ•Œλ¬Έμ— 컴파일 νƒ€μž„μ—μ„œ μ‹€μ²΄ν™”ν•˜μ§€ λͺ»ν•˜κ²Œ νƒ€μž…μ„ μ†Œκ±°ν•˜λŠ” λ¦¬μŠ€νŠΈκ°™μ€ 싀체화 λΆˆκ°€ νƒ€μž…μ„ μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

πŸ”₯ 주말에 μ§„ν–‰ν•˜λ € ν–ˆλ˜ λ‚΄μš©μΈλ°, 주말에도 νšŒμ‚¬μΌμ„ ν•˜λŠλΌκ³  μ§€κΈˆκΉŒμ§€ λΆ™μž‘κ³  있게 λ˜μ—ˆλ‹€.
ν•˜μ§€λ§Œ 그만큼 κ³΅λΆ€ν•œ λ‚΄μš©λ“€μ„ λ¨Έλ¦Ώμ†μœΌλ‘œ 정리할 μ‹œκ°„μ΄ λ§Žμ•˜λŠ”λ°, 덕뢄에 μ΅œλŒ€ν•œ λ‚΄κ°€ μ΄ν•΄ν•œ λ‚΄μš©λ§ŒμœΌλ‘œ μž‘μ„±ν•˜λ €κ³  λ…Έλ ₯ ν•  수 μžˆμ—ˆλ‹€. 아직 Generic에 λŒ€ν•΄μ„œ μ „λΆ€ μ•„λŠ” 것은 μ•„λ‹ˆμ§€λ§Œ μ–΄λŠμ •λ„ 머릿속에 κ΅¬μ²΄ν™”λœ 것 κ°™μ•„ κΈ°μ˜λ‹€!

λ‹€μŒμ— μ‹œκ°„ μ—¬μœ κ°€ 생긴닀면, Compable<E> 에 λŒ€ν•΄μ„œλ„ 곡뢀λ₯Ό 해봐야겠닀.

 


μ°Έκ³  λ¬Έμ„œ

 

14μ£Όμ°¨ 과제: μ œλ„€λ¦­

14μ£Όμ°¨ 과제: μ œλ„€λ¦­ μ‹œμž‘ν•˜κΈ° 전에 μ œλ„€λ¦­μ΄ 무엇이고 μ œλ„€λ¦­μ„ μ™œ μ‚¬μš©ν•΄μ•Όν•˜λŠ”μ§€ μ•Œμ•„λ³΄μž μ œλ„€λ¦­μ΄λž€? 데이터 νƒ€μž…(data type)을 μΌλ°˜ν™”(generalize)ν•˜λŠ”κ²ƒμ„ μ˜λ―Έν•œλ‹€ μ œλ„€λ¦­μ€ ν΄λž˜μŠ€λ‚˜ λ©”μ†Œλ“œ

sujl95.tistory.com

 

μžλ°”μ˜ μ œλ„€λ¦­ νƒ€μž… μ†Œκ±°, λ¦¬μŠ€νŠΈμ— κ΄€ν•˜μ—¬ (Java Generics Type Erasure, List)

1. μžλ°”μ˜ μ œλ„€λ¦­κ³Ό λ‘œνƒ€μž… (Java Generics and Raw Type) public class Example{ private T member; } μœ„μ™€ 같이 클래슀 및 μΈν„°νŽ˜μ΄μŠ€ 선언에 νƒ€μž… λ§€κ°œλ³€μˆ˜ T κ°€ μ‚¬μš©λ˜λ©΄ μ œλ„€λ¦­ 클래슀, μ œλ„€λ¦­ μΈν„°νŽ˜μ΄μŠ€λΌ..

jyami.tistory.com

 

'Programming > Java' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

F015 - Set (μž‘μ„± 쀑)  (0) 2021.05.31
F014 - List (ArrayList, LinkedList, Vector, Stack)  (0) 2021.05.30
F012 - Annotation  (0) 2021.05.24
F011 - java.lang.ref  (0) 2021.05.19
F010 - System.out.println(), Logger  (0) 2021.05.19