[Java] generics

ํ—Œ์น˜ยท2022๋…„ 9์›” 25์ผ
1

JAVA

๋ชฉ๋ก ๋ณด๊ธฐ
1/1
post-thumbnail

ํ•ด๋‹น ๊ธ€์€ CS ์Šคํ„ฐ๋””์—์„œ ๊ณต๋ถ€ํ•œ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

generics

1. ์ œ๋„ค๋ฆญ์ด ๋ญ์ง€?๐Ÿ‘€

JDK 1.5๋ถ€ํ„ฐ ๋„์ž…๋˜์—ˆ๋‹ค.

ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•  ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์™ธ๋ถ€์—์„œ ์ง€์ •ํ•˜๋Š” ๊ธฐ๋ฒ•์ด๋‹ค. ์ปดํŒŒ์ผ ํƒ€์ž„์— ํƒ€์ž…์„ ์ฒดํฌํ•จ์œผ๋กœ์จ ์ฝ”๋“œ์˜ ์•ˆ์ •์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค.

List<T> ์† T : ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜
List<String> strings = new ArrayList<String>(); ์† String : ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋œ ํƒ€์ž…

ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ ์ปจ๋ฒค์…˜

2. ์™œ ์“ฐ์ง€?๐Ÿง

1. ์ปดํŒŒ์ผ ํƒ€์ž„์— ๊ฐ•๋ ฅํ•œ ํƒ€์ž… ๊ฒ€์‚ฌ

๋Ÿฐํƒ€์ž„์ด ์•„๋‹Œ, ์ปดํŒŒ์ผ ํƒ€์ž„์— ๊ฐ•๋ ฅํ•œ ํƒ€์ž… ๊ฒ€์‚ฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.

์ œ๋„ค๋ฆญ ๋ฏธ์‚ฌ์šฉ

List stringList = new ArrayList<>();
stringList.add("hunch");
stringList.add(1);
String result = 
    (String) stringList.get(0) * (String) stringList.get(1)
//-> ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ!!๐Ÿ˜‚

์ œ๋„ค๋ฆญ ์‚ฌ์šฉ

List<String> stringList = new ArrayList<>();
stringList.add("hunch");
stringList.add(1);
//-> ์ปดํŒŒ์ผ ์—๋Ÿฌ!!๐Ÿ˜

2. ์บ์ŠคํŒ…(ํƒ€์ž… ๋ณ€ํ™˜) ์ œ๊ฑฐ

๋งŒ์•ฝ ๋งค๋ฒˆ ์บ์ŠคํŒ…(ํƒ€์ž… ๋ณ€ํ™˜)์„ ํ•˜๊ฒŒ ๋˜๋ฉด ๊ท€์ฐฎ๊ณ , ๋น ๋œจ๋ฆด ์ˆ˜ ์žˆ๋‹ค.

์ œ๋„ค๋ฆญ์„ ์“ฐ๋ฉด ์บ์ŠคํŒ…์„ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ์ฝ”๋“œ๋„ ๊ฐ„๊ฒฐํ•ด์ง„๋‹ค.

์ œ๋„ค๋ฆญ ๋ฏธ์‚ฌ์šฉ

List stringList = new ArrayList<>();
stringList.add("hunch");
String result = (String) stringList.get(0);
//-> ๋งค๋ฒˆ ์บ์ŠคํŒ…์ด ํ•„์š”ํ•จ๐Ÿ˜‚

์ œ๋„ค๋ฆญ ์‚ฌ์šฉ

List<String> stringList = new ArrayList<>();
stringList.add("hunch");
String result = stringList.get(0);
//-> ์บ์ŠคํŒ… ์•ˆํ•ด๋„ ๋จ!๐Ÿ˜

3. ์ œ๋„ค๋ฆญ ํƒ€์ž…๊ณผ ๋ฉ”์„œ๋“œ๐Ÿ˜„

์–ด๋–ป๊ฒŒ ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์„ ์–ธํ•˜๊ณ  ์ƒ์„ฑํ• ๊นŒ?

1. ํด๋ž˜์Šค์—์„œ ์ƒ์„ฑ

class MyArray<T> {
    private T element;

    public MyArray(T element) {
        this.element = element;
    }

    public T get() { 
        return element; 
    }
}

์‚ฌ์šฉ

MyArray<Integer> myArr = new MyArray<Integer>(1);

// Java SE 7๋ถ€ํ„ฐ ๊ฐ€๋Šฅํ•จ.
MyArray<Integer> myArr2 = new MyArray<>(1);

2. ๋ฉ”์†Œ๋“œ์—์„œ ์ƒ์„ฑ

class MyArray<T> {
    private T element;

    public MyArray(T element) {
        this.element = element;
    }

    //...
    public<T> void printArray(T parameter) {
        System.out.println("ํด๋ž˜์Šค ํ•„๋“œ์— ์ •์˜๋œ ํƒ€์ž…: " + element.getClass().getName());
        System.out.println("๋ฉ”์†Œ๋“œ ํ•„๋“œ์— ์ •์˜๋œ ํƒ€์ž…: " + parameter.getClass().getName());
    }
}

์‚ฌ์šฉ

MyArray<Integer> myArr = new MyArray<>();
myArr.printArray("ํŒŒ๋ผ๋ฏธํ„ฐ");

// ํด๋ž˜์Šค ํ•„๋“œ์— ์ •์˜๋œ ํƒ€์ž…: java.lang.Integer
// ๋ฉ”์†Œ๋“œ ํ•„๋“œ์— ์ •์˜๋œ ํƒ€์ž…: java.lang.String

4. ์ œ๋„ค๋ฆญ ๋ณ€์„ฑ๐ŸงŠ

List<Object> objectList = new ArrayList<String>();

โ†’ ๋ฌธ๋ฒ•์ƒ ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค! ์ปดํŒŒ์ผ ์˜ค๋ฅ˜!

๋ณ€์„ฑ์„ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๋ ค๋ฉด "ํƒ€์ž… S๊ฐ€ T์˜ ํ•˜์œ„ ํƒ€์ž…์ผ ๋•Œ, Box[S]๊ฐ€ Box[T]์˜ ํ•˜์œ„ ํƒ€์ž…์ธ๊ฐ€?" ๋ผ๋Š” ์งˆ๋ฌธ์—์„œ ์‹œ์ž‘ํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค.

๋ณ€์„ฑ(variance)์ด๋ž€?

ย ํƒ€์ž…์˜ ๊ณ„์ธต ๊ด€๊ณ„(Type Hierarchy)์—์„œ ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž… ๊ฐ„์— ์–ด๋–ค ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐœ๋…์ด๋‹ค.

๋ฌด๊ณต๋ณ€(invariance)- <T>

ํƒ€์ž… S๊ฐ€ T์˜ ํ•˜์œ„ ํƒ€์ž…์ผ ๋•Œ, Box[S]์™€ Box[T] ์‚ฌ์ด์— ์ƒ์† ๊ด€๊ณ„๊ฐ€ ์—†๋Š” ๊ฒƒ

  • java์˜ ์ œ๋„ค๋ฆญ์€ ๋ฌด๊ณต๋ณ€์ด๋‹ค!

๊ณต๋ณ€(covariance) - <? extends T>

// Number ๋ฐฐ์—ด์— ํ•˜์œ„ ํƒ€์ž… ๊ฐ’์„ ์ถ”๊ฐ€
Number[] numbers = new Number[3];
numbers[0] = new Integer(42);
numbers[1] = new Double(3.14);
numbers[2] = new Byte((byte) 0);

// Number ๋ฐฐ์—ด์— Interger ๋ฐฐ์—ด์„ ํ• ๋‹น
Integer[] ints = { 1, 2, 3, 4};
Number[] nums = ints;

ํƒ€์ž… S๊ฐ€ T์˜ ํ•˜์œ„ ํƒ€์ž…์ผ ๋•Œ, Box[S]๊ฐ€ Box[T]์˜ ํ•˜์œ„ ํƒ€์ž…์ธ ๊ฒƒ

  • Java์˜ ๋ฐฐ์—ด์€ ๊ณต๋ณ€์ด๋‹ค!

๋ฐ˜๊ณต๋ณ€(contravariance) - <? super T>

ํƒ€์ž… S๊ฐ€ T์˜ ํ•˜์œ„ ํƒ€์ž…์ผ ๋•Œ, Box[S]๊ฐ€ Box[T]์˜ ์ƒ์œ„ ํƒ€์ž…์ธ ๊ฒƒ

5. ์™€์ผ๋“œ ์นด๋“œ๐Ÿƒ

์ œ๋„ค๋ฆญ ๊ฐ์ฒด๋ฅผ ๋ฉ”์†Œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์„ ๋•Œ, ๊ทธ ๊ฐ์ฒด์˜ ํƒ€์ž… ๋ณ€์ˆ˜๋ฅผ ์ œํ•œํ•˜๋Š” ๊ฒƒ!

@Test
void genericTest() {
    List<Integer> list = Arrays.asList(1, 2, 3);
    printCollection(list);   // ์ปดํŒŒ์ผ ์—๋Ÿฌ!!๐Ÿ˜‚
}

void printCollection(Collection<Object> c) {
    for (Object e : c) {
        System.out.println(e);
    }
}

์ œ๋„ค๋ฆญ์€ ๋ถˆ๊ณต๋ณ€๐Ÿฅฒ

  • Collection<Object>๋Š” Collection<Integer>์˜ ํ•˜์œ„ํƒ€์ž…์ด ์•„๋‹ˆ๋ฏ€๋กœ ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
  • ์˜คํžˆ๋ ค ์ œ๋„ค๋ฆญ ์ด์ „๋ณด๋‹ค ์‹ค์šฉ์„ฑ์ด ๋–จ์–ด์ง„๋‹คโ€ฆ

์ด์— ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค!

1) Unbounded Wlidcards : <?>

๋ชจ๋“  ํƒ€์ž…์ด ๊ฐ€๋Šฅ!

2) Upper Bounded Wlidcards : <? extends MyArray>

MyArray์™€ MyArray์˜ ํ•˜์œ„ ํƒ€์ž…!

  • <? extends Collection>: Collection, Map, List โ€ฆ
  • ์ƒํ•œ ๊ฒฝ๊ณ„ : ํ•ด๋‹น ํด๋ž˜์Šค/ ํด๋ž˜์Šค์˜ ์ž์‹ ํด๋ž˜์Šค
  • โ†’ ๊ณต๋ณ€ ๊ฐ€๋Šฅ!

3) Lower Bounded Wlidcards : <? super MyArray>

MyArray์™€ MyArray์˜ ์ƒ์œ„ ํƒ€์ž…!

  • <? super Collection> : Object, Iterable, Collection โ€ฆ
  • ํ•˜ํ•œ ๊ฒฝ๊ณ„ : ํ•ด๋‹น ํด๋ž˜์Šค/ ํด๋ž˜์Šค์˜ ๋ถ€๋ชจ ํด๋ž˜์Šค
  • โ†’ ๋ฐ˜๊ณต๋ณ€ ๊ฐ€๋Šฅ!

6. ์™€์ผ๋“œ์นด๋“œ ์ œํ•œ

0) PECS

  • producer(์ƒ์„ฑ์ž) - extends(์ƒํ•œ ์ œํ•œ)
  • consumer(์†Œ๋น„์ž) - super(ํ•˜ํ•œ ์ œํ•œ)

1) ์ƒํ•œ(extends) ์ œํ•œ

public void pop(Test<? extends String> myArray) {
    String element = myArray.get();
    //๊บผ๋‚ด๋Š” ๊ฑด ๊ฐ€๋Šฅ!

    element.set(new String());
    //์ €์žฅ์€ ๋ถˆ๊ฐ€!
}
  • ์ƒ์„ฑํ•˜๋Š” ๊ณณ์—์„œ ์ƒํ•œ ์ œํ•œ์„ ์“ฐ์ž!

2) ํ•˜ํ•œ(super) ์ œํ•œ

public void push(Test<? super String> myArray) {
    element.set(new String());
    //์ €์žฅ์€ ๊ฐ€๋Šฅ!

    String element = myArray.get();
    //๊บผ๋‚ด๋Š” ๊ฑด ๋ถˆ๊ฐ€!
}
  • ์†Œ๋น„ํ•˜๋Š” ๊ณณ์—์„œ ํ•˜ํ•œ ์ œํ•œ์„ ์“ฐ์ž!

์ œ๋„ค๋ฆญ ํƒ€์ž… ์†Œ๊ฑฐโ›”๏ธ

์ œ๋„ค๋ฆญ์€ ํƒ€์ž…์— ์‚ฌ์šฉ๋œ ํƒ€์ž… ์ •๋ณด๋ฅผ ์ปดํŒŒ์ผ ํƒ€์ž„์—๋งŒ ์‚ฌ์šฉํ•˜๊ณ  ๋Ÿฐํƒ€์ž„์—๋Š” ์†Œ๊ฑฐํ•œ๋‹ค!

ํƒ€์ž…์†Œ๊ฑฐ ๊ณผ์ •

public static void main(String[] args) {
     ArrayList<String> objects = new ArrayList<>();
     objects.add("abc");
     String s = objects.get(0);
     System.out.println("s = " + s);
}

//->์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋‹ค์Œ ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ
public static void main(String[] args) {
     ArrayList<String> objects = new ArrayList();
     objects.add("abc");
     String s = (String) objects.get(0); //ํƒ€์ž…์บ์ŠคํŒ…
     System.out.println("s = " + s);
}
  1. ์ œ๋„ค๋ฆญ ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ”์šด๋“œ๋‚˜ Object๋กœ ๋ณ€๊ฒฝํ•ด์ค€๋‹ค.
    1. ์ƒํ•œ ์ œํ•œ : ๋ฐ”์šด๋“œ
    2. ํ•˜ํ•œ ์ œํ•œ/์–ธ๋ฐ”์šด๋“œ : Object
  2. ์ดํ›„ ํƒ€์ž…์ด ์ผ์น˜ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ํƒ€์ž… ์บ์ŠคํŒ…์„ ์ถ”๊ฐ€ํ•œ๋‹ค.
  3. ํ™•์žฅ๋œ ์ œ๋„ค๋ฆญ ํƒ€์ž…์—์„œ ๋‹คํ˜•์„ฑ์„ ๋ณด์กดํ•˜๊ธฐ ์œ„ํ•ด bridege method๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

๐Ÿ“š ์ฐธ๊ณ ์ž๋ฃŒ

[10๋ถ„ ํ…Œ์ฝ”ํ†ก] ๊ทธ๋ฆฐ๋ก ์˜ ์ œ๋„ค๋ฆญ
Type Erasure Deep Dive
http://www.tcpschool
https://sungjk.github.io/2021/02/20/variance.html
https://www.baeldung
https://jyami.tistory.com/99

profile
๐ŸŒฑ ํ•จ๊ป˜ ์ž๋ผ๋Š” ์ค‘์ž…๋‹ˆ๋‹ค ๐Ÿš€ rerub0831@gmail.com

0๊ฐœ์˜ ๋Œ“๊ธ€