์ž๋ฐ”์˜ ์ •์„ - ์ง€๋„ค๋ฆญ์Šค(Generics)

๋ธ”๋กœ๊ทธ ์˜ฎ๊ฒผ์Šต๋‹ˆ๋‹ค! ๐Ÿก’ integer.blog



์ž๋ฐ”์˜ ์ •์„(๋‚จ๊ถ์„ฑ ์ €) ํ•™์Šต๋‚ด์šฉ ์ •๋ฆฌ

1. ์ง€๋„ค๋ฆญ์Šค(Generics)

์ง€๋„ค๋ฆญ์Šค๋Š” ๋‹ค์–‘ํ•œ ํƒ€์ž…์˜ ๊ฐ์ฒด๋“ค์„ ๋‹ค๋ฃจ๋Š” ๋ฉ”์„œ๋“œ๋‚˜ ์ปฌ๋ ‰์…˜ ํด๋ž˜์Šค์— ์ปดํŒŒ์ผ ์‹œ์˜ ํƒ€์ž… ์ฒดํฌ๋ฅผ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ
๋‹ค์‹œ ๋งํ•ด, ๋‹ค๋ฃฐ ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ๋ฏธ๋ฆฌ ๋ช…์‹œํ•ด์คŒ์œผ๋กœ์จ ๋ฒˆ๊ฑฐ๋กœ์šด ํ˜•๋ณ€ํ™˜์„ ์ค„์—ฌ์ค€๋‹ค.

์ง€๋„ค๋ฆญ ํƒ€์ž…์€ ํด๋ž˜์Šค์™€ ๋ฉ”์„œ๋“œ์— ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค.

class Box<T>  { // ์ง€๋„ค๋ฆญ ํƒ€์ž… T๋ฅผ ์„ ์–ธ. T๋Š” ํƒ€์ž…๋ณ€์ˆ˜
  T item;
  
  void setItem(T item)  {
    this.item = item;
  }
  
  T getItem() {
    return item;
  }
}

์ง€๋„ค๋ฆญ ํด๋ž˜์Šค๊ฐ€ ๋œ Box ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š”
๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฐธ์กฐ๋ณ€์ˆ˜์™€ ์ƒ์„ฑ์ž์— ํƒ€์ž… T๋Œ€์‹  ์‚ฌ์šฉ๋  ์‹ค์ œ ํƒ€์ž…์„ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.

Box<String> b = new Box<String>();  // ํƒ€์ž… T๋Œ€์‹  ์‹ค์ œ ํƒ€์ž… ์ง€์ •
b.setItem(new Object());  // ์—๋Ÿฌ. String ์™ธ์˜ ํƒ€์ž…์€ ์ง€์ • ๋ถˆ๊ฐ€
b.setItem("ABC"); // OK. String ํƒ€์ž…์ด๋ฏ€๋กœ ๊ฐ€๋Šฅ

์˜ˆ๋ฅผ ๋“ค์–ด, Box๊ณผ Box๋Š”
์ง€๋„ค๋ฆญ ํด๋ž˜์Šค Box์— ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž…์„ ๋Œ€์ž…ํ•˜์—ฌ ํ˜ธ์ถœํ•œ ๊ฒƒ์ผ ๋ฟ, ์„œ๋กœ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ์˜๋ฏธํ•˜์ง€ ์•Š๋Š”๋‹ค.
์ปดํŒŒ์ผ ํ›„์— Box๊ณผ Box๋Š” ์ด๋“ค์˜ ์›์‹œํƒ€์ž…์ธ Box๋กœ ๋ฐ”๋€๋‹ค. ์ฆ‰, ์ง€๋„ค๋ฆญํƒ€์ž…์ด ์ œ๊ฑฐ๋œ๋‹ค.

2. ์ง€๋„ค๋ฆญ์Šค ์ œํ•œ

  • ๋ชจ๋“  ๊ฐ์ฒด์— ๋Œ€ํ•ด ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•ด์•ผํ•˜๋Š” static๋ฉค๋ฒ„์— ํƒ€์ž…๋ณ€์ˆ˜ T๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
    T๋Š” ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋กœ ๊ฐ„์ฃผ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. (static ๋ฉค๋ฒ„๋Š” ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์—†๋‹ค.)

  • ์ง€๋„ค๋ฆญ ๋ฐฐ์—ด ํƒ€์ž…์˜ ์ฐธ์กฐ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ,
    new T[10] ๊ณผ ๊ฐ™์ด ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ ์•ˆ๋œ๋‹ค.
    new ์—ฐ์‚ฐ์ž ๋•Œ๋ฌธ์ธ๋ฐ, ์ด ์—ฐ์‚ฐ์ž๋Š” ์ปดํŒŒ์ผ ์‹œ์ ์— ํƒ€์ž… T๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ •ํ™•ํžˆ ์•Œ์•„์•ผ ํ•œ๋‹ค.
    instanceof ์—ฐ์‚ฐ์ž๋„ ๊ฐ™์€ ์ด์œ ๋กœ T๋ฅผ ํ”ผ์—ฐ์‚ฐ์ž๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

3. ์ง€๋„ค๋ฆญ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด ์ƒ์„ฑ๊ณผ ์‚ฌ์šฉ

Apple์ด Furuit์˜ ์ž์†์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ด๋„

Box<Fruit> appleBox = new Box<Apple>(); // ์—๋Ÿฌ. ๋Œ€์ž…๋œ ํƒ€์ž…์ด ๋‹ค๋ฅด๋‹ค.

๋‹จ, ๋‘ ์ง€๋„ค๋ฆญ ํด๋ž˜์Šค์˜ ํƒ€์ž…์ด ์ƒ์†๊ด€๊ณ„์— ์žˆ๊ณ , ๋Œ€์ž…๋œ ํƒ€์ž…์ด ๊ฐ™์€ ๊ฒƒ์€ ๊ดœ์ฐฎ๋‹ค.

Box<Apple> appleBox = new FruitBox<Apple>();  // OK. ๋‹คํ˜•์„ฑ

์ƒ์„ฑ๋œ Box์˜ ๊ฐ์ฒด์— ‘void add(T item)‘์œผ๋กœ ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ, ๋Œ€์ž…๋œ ํƒ€์ž…๊ณผ ๋‹ค๋ฅธ ํƒ€์ž…์˜ ๊ฐ์ฒด๋Š” ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†๋‹ค.

Box<Apple> appleBox = new Box<Apple>();
appleBox.add(new Apple());  // OK.
appleBox.add(new Grape());  // ์—๋Ÿฌ. Box<Apple>์—๋Š” Apple ๊ฐ์ฒด์™€ Apple์˜ ์ž์†๋งŒ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ

4. ์ œํ•œ๋œ ์ง€๋„ค๋ฆญ ํด๋ž˜์Šค

์ง€๋„ค๋ฆญ ํƒ€์ž…์— extends๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ํŠน์ • ํƒ€์ž…์˜ ์ž์†๋“ค๋งŒ ๋Œ€์ž…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ œํ•œํ•  ์ˆ˜ ์žˆ๋‹ค.

class FruitBox<T extends Fruit> { //Fruit์˜ ์ž์†๋งŒ ํƒ€์ž…์œผ๋กœ ์ง€์ • ๊ฐ€๋Šฅ
  ArrayList<T> list = new ArrayList<T>();
  ...
}

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ œ์•ฝ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด, ์ด๋•Œ๋„ implements ๋Œ€์‹  extends๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

interface Eatable {}
class FruitBox<T extends Eatable> {
  ...
}

ํด๋ž˜์Šค Fruit์˜ ์ž์†์ด๋ฉด์„œ Eatable ์ธํ„ฐํŽ˜์ด์Šค๋„ ๊ตฌํ˜„ํ•ด์•ผํ•˜๋ฉด & ๊ธฐํ˜ธ๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค.

class FruitBox<T extends Fruit & Eatable> {
  ...
}

5. ์™€์ผ๋“œ ์นด๋“œ

์ง€๋„ค๋ฆญ ํƒ€์ž…์€ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ปดํŒŒ์ผํ•  ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜๊ณ  ์ œ๊ฑฐํ•ด๋ฒ„๋ฆฐ๋‹ค.
๋•Œ๋ฌธ์— ์ง€๋„ค๋ฆญ ํƒ€์ž…์ด ๋‹ค๋ฅธ ๊ฒƒ๋งŒ์œผ๋กœ๋Š” Overloading์ด ์„ฑ๋ฆฝํ•˜์ง€ ์•Š๊ณ  ‘๋ฉ”์„œ๋“œ ์ค‘๋ณต ์ •์˜’๊ฐ€ ๋œ๋‹ค.
์ด๋Ÿด ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์™€์ผ๋“œ ์นด๋“œ์ด๋ฉฐ, ์™€์ผ๋“œ ์นด๋“œ๋Š” ์–ด๋–ค ํƒ€์ž…๋„ ๋  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐํ˜ธ ?๋กœ ํ‘œํ˜„ํ•œ๋‹ค.

?๋งŒ์œผ๋กœ๋Š” Objectํƒ€์ž…๊ณผ ๋‹ค๋ฅผ ๊ฒŒ ์—†์œผ๋ฏ€๋กœ,
extends์™€ super๋กœ ์ƒํ•œ๊ณผ ํ•˜ํ•œ์„ ์ œํ•œํ•  ์ˆ˜ ์žˆ๋‹ค.

<? extends T> T์™€ ๊ทธ ์ž์†๋“ค๋งŒ ๊ฐ€๋Šฅ
<? super T> T์™€ ๊ทธ ์กฐ์ƒ๋“ค๋งŒ ๊ฐ€๋Šฅ
<?> ๋ชจ๋“  ํƒ€์ž… ๊ฐ€๋Šฅ. <? extends Object>์™€ ๋™์ผ

์™€์ผ๋“œ ์นด๋“œ์—๋Š” &์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

6. ์ง€๋„ค๋ฆญ ๋ฉ”์†Œ๋“œ

๋ฉ”์†Œ๋“œ์˜ ์„ ์–ธ๋ถ€์— ์ง€๋„ค๋ฆญ ํƒ€์ž…์ด ์„ ์–ธ๋œ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ง€๋„ค๋ฆญ ๋ฉ”์†Œ๋“œ๋‹ค.
์ง€๋„ค๋ฆญ ๋ฉ”์†Œ๋“œ๋Š” ์ง€๋„ค๋ฆญ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ํด๋ž˜์Šค์—๋„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

class FruitBox<T> {
    ...
  static <T> void sort(List<T> list, Comparator<? super T> c) {
    ...
  }
}
  • ์ง€๋„ค๋ฆญ ํด๋ž˜์Šค์— ์ •์˜๋œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ง€๋„ค๋ฆญ ๋ฉ”์†Œ๋“œ์— ์ •์˜๋œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์ „ํ˜€ ๋ณ„๊ฐœ์˜ ๊ฒƒ์ด๋‹ค.
  • static ๋ฉค๋ฒ„์—๋Š” ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์ง€๋งŒ, ์ด์ฒ˜๋Ÿผ ๋ฉ”์†Œ๋“œ์— ์ง€๋„ค๋ฆญ ํƒ€์ž…์„ ์„ ์–ธํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ๋ฉ”์†Œ๋“œ์— ์„ ์–ธ๋œ ์ง€๋„ค๋ฆญ ํƒ€์ž…์€ ์ง€์—ญ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•œ ๊ฒƒ๊ณผ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๋‹ค.
    • ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๋ฉ”์†Œ๋“œ ๋‚ด์—์„œ๋งŒ ์ง€์—ญ์ ์œผ๋กœ ์‚ฌ์šฉ๋  ๊ฒƒ์ด๋ฏ€๋กœ ๋ฉ”์†Œ๋“œ๊ฐ€ static์ด๊ฑด ์•„๋‹ˆ๊ฑด ์ƒ๊ด€์—†๋‹ค.
    • ๊ฐ™์€ ์ด์œ ๋กœ, ๋‚ด๋ถ€ ํด๋ž˜์Šค์— ์„ ์–ธ๋œ ํƒ€์ž… ๋ฌธ์ž๊ฐ€ ์™ธ๋ถ€ ํด๋ž˜์Šค์˜ ํƒ€์ž… ๋ฌธ์ž์™€ ๊ฐ™์•„๋„ ๊ตฌ๋ณ„๋  ์ˆ˜ ์žˆ๋‹ค.