Bounded Type Parameters

๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋œ ํƒ€์ž… (Parameterized Type) ์„ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์—๋Š” ํ•ด๋‹น ํƒ€์ž…์„ ์ œํ•œํ•˜๊ธฐ ์œ„ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

๊ฐ€๋ น ์ˆซ์ž๋กœ๋งŒ ์ž‘์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ์˜ ๊ฒฝ์šฐ Number ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค ํ˜น์€ ๊ทธ์— ๋Œ€ํ•œ ํ•˜์œ„ ํด๋ž˜์Šค๋งŒ ํ—ˆ์šฉํ•˜๋ ค๊ณ  ํ•  ๋•Œ ํšจ๊ณผ์ ์ด๋‹ค.












ย 







ย 



public class Box<T> {
  private T t;

  public void set(T t) {
    this.t = t;
  }

  public T get() {
    return t;
  }

  public <U extends Number> void inspect(U u) {
    System.out.println("T: " + t.getClass().getName());
    System.out.println("U: " + u.getClass().getName());
  }

  public static void main(String[] args) {
    Box<Integer> integerBox = new Box<>();
    integerBox.set(new Integer(10));
    integerBox.set("some text");      // error: this is still String!
  }
}

์œ„ ์ฝ”๋“œ๋Š” Number ์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋งŒ ๋ฐ›๊ฒŒ ๋” ํŒŒ๋ผ๋ฉ”ํ„ฐ ํƒ€์ž…์„ ์ œํ•œํ•ด๋†“์•˜๋Š”๋ฐ ๋ฌธ์ž์—ด ์œ ํ˜•์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋„˜๊ฒจ์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค.

์ถ”๊ฐ€์ ์œผ๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.









ย 



public class NaturalNumber<T extends Integer> {
  private T n;

  public NaturalNumber(T n) {
    this.n = n;
  }

  public boolean isEven() {
    return n.intValue() % 2 == 0;
  }
}

isEven() ๋ฉ”์„œ๋“œ์—์„œ ์‚ฌ์šฉ์ค‘์ธ n ๋ณ€์ˆ˜๋Š” Integer ํด๋ž˜์Šค์— ์ •์˜๋œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค.

Covariant & Contravariant Generic

๊ณต๋ณ€ (covariant)

ํ•จ๊ป˜(ๅ…ฑ) ๋ณ€ํ•œ(่ฎŠ)๋‹ค ๋ผ๋Š” ๋œป์œผ๋กœ a ๊ฐ€ A ์˜ ํ•˜์œ„ ํƒ€์ž…์ด๋ผ๋ฉด a[] ๋Š” A[] ํ•˜์œ„ ํƒ€์ž…์ด ๋œ๋‹ค.

๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™ ์ด ์ ์šฉ๋œ ์‚ฌ๋ก€๋กœ ์ž์‹ (ํŒŒ์ƒ) ํด๋ž˜์Šค๋Š” ์–ธ์ œ๋‚˜ ๋ถ€๋ชจ (๊ธฐ๋ฐ˜) ํƒ€์ž…๊ณผ ํ˜ธํ™˜์ด ๋˜์–ด์•ผ ํ•œ๋‹ค๋ผ๋Š” ํŠน์ง•์ด ์žˆ๋‹ค. <? extends T>

์ด๋Š” ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋ฐฐ์—ด์€ ๊ณต๋ณ€ ํƒ€์ž…์œผ๋กœ ๋ถ€๋ชจ์˜ Super[] ์˜ ํƒ€์ž…์ด ์ƒ์†๋˜๋Š” Sub[] ๊ณผ ํƒ€์ž…ํ˜ธํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ฐ˜๊ณต๋ณ€ (contravariant)

์ถ”์ƒ์ ์ธ ๋ฐฉํ–ฅ์œผ๋กœ ํƒ€์ž… ๋ณ€ํ™˜์„ ํ—ˆ์šฉ ํ•˜๋Š”๊ฒƒ <? super T>

๋ฌด๊ณต๋ณ€ (๋ถˆ๊ณต๋ณ€ : invariant)

์˜ค๋กœ์ง€ ์ž๊ธฐ ํƒ€์ž…๋งŒ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. <T>

์ œ๋„ค๋ฆญ (๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž… : Parameterized Types) ์ด ๋Œ€ํ‘œ์ ์ด๋ฉฐ ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž… List<Type1> ์€ List<Type2> ์˜ ์ƒ์œ„ํƒ€์ž…๋„ ํ•˜์œ„ํƒ€์ž…๋„ ์•„๋‹ˆ๋‹ค.

์ด๋Š” ์ œ๋„ค๋ฆญ์˜ ์†Œ๊ฑฐ ํƒ€์ž… (Type Erasure) ์— ์˜ํ•ด ๋‚˜ํƒ€๋‚˜๋Š” ํ˜„์ƒ ์ด๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ

https://ojava.tistory.com/32

Multiple Bounds

๋งค๊ฐœ๋ณ€์ˆ˜ ์œ ํ˜•์„ ๋‘๊ฐœ์ด์ƒ ์ œํ•œ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•œ๋‹ค.

<T extends A & B & C>

์œ„์˜ T ๋Š” A B C ์˜ ๊ฐ๊ฐ์˜ ๋ชจ๋“  ์„œ๋ธŒํƒ€์ž…์ด๋‹ค.

๋งŒ์•ฝ A B C ์ค‘ ํ•˜๋‚˜๊ฐ€ ํด๋ž˜์Šค์ธ ๊ฒฝ์šฐ์—๋Š” ๋ฐ˜๋“œ์‹œ ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ๋จผ์ € ๊ธฐ์ž…ํ•ด์•ผ ํ•œ๋‹ค.






ย 

Class A { /* statement */ }
interface B { /* statement */ }
interface C { /* statement */ }

class D <T extends A & B & C> { /* ... */ }
class E <T extends C & B & A> { /* ... */ }   // compile error

์œ„ ์ฝ”๋“œ์˜ E ํด๋ž˜์Šค๋Š” A ๊ฐ€ ๋จผ์ € ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•œ๋‹ค.