JiwonDev

μ œλ„€λ¦­(Generic)에 λŒ€ν•˜μ—¬

by JiwonDev

기쑴의 μžλ°”μ—μ„œλŠ” Object νƒ€μž…μ„ μ΄μš©ν•˜μ—¬ λ‹€ν˜•μ„±μ„ κ΅¬ν˜„ν•˜μ˜€λ‹€. 이 경우 λ°˜ν™˜λœ Object νƒ€μž…μ„ λ‹€μ‹œ μ›ν•˜λŠ” 객체둜 λ³€ν™˜ν•˜λŠ” κ³Όμ •μ—μ„œ λ¬Έμ œκ°€ λ°œμƒν•˜λ”λΌλ„ μ»΄νŒŒμΌνƒ€μž„μ—μ„œ ν•΄λ‹Ή 였λ₯˜λ₯Ό μž‘μ„ 수 μ—†μ—ˆλ‹€. 즉 λ‹¨μˆœν•œ νƒ€μž… μ‹€μˆ˜κ°€ λŸ°νƒ€μž„ 였λ₯˜λ‘œ λ„˜μ–΄κ°€ 앱이 λ©ˆμΆ°λ²„λ¦¬λŠ” μ΅œμ•…μ˜ μƒν™©κΉŒμ§€ 갈 수 μžˆμ—ˆλ‹€.

 

κ·Έλž˜μ„œ Java 5λΆ€ν„° Genericμ΄λΌλŠ” νƒ€μž… κΈ°λŠ₯을 μ œκ³΅ν•΄μ€€λ‹€. 컴파일 μ‹œμ μ— νƒ€μž…μ„ μ²΄ν¬ν•˜μ—¬ λ‹€μ–‘ν•œ 문제λ₯Ό λ°©μ§€ν•˜κ³  λ‹€ν˜•μ„±μ„ μ§€μ›ν•˜λŠ” μ½”λ“œλ₯Ό μ‰½κ²Œ λ§Œλ“€ 수 있게 ν•΄μ€€λ‹€.

 

# μ œλ„€λ¦­μ˜ μž₯점

μ œλ„€λ¦­μ˜ μ‚¬μš©μ—μ„œ μ–»λŠ” 이점은 컴파일 νƒ€μž„μ— κ°•ν•œ νƒ€μž… 체크λ₯Ό ν•  수 있게 λ§Œλ“€μ–΄μ€€λ‹€λŠ” 것이닀. νƒ€μž…μ„ λͺ…μ‹œμ μœΌλ‘œ ν‘œμ‹œν•˜λ©΄μ„œ λΆˆν•„μš”ν•œ νƒ€μž… μΊμŠ€νŒ…μ΄λ‚˜  λŸ°νƒ€μž„μ— λ°œμƒν•  수 μžˆλŠ” 였λ₯˜λ₯Ό μ˜ˆλ°©ν•΄μ€€λ‹€.

 

* μ œλ„€λ¦­μ„ μ‚¬μš©ν•œλ‹€κ³  ν•΄μ„œ λ°”μ΄νŠΈμ½”λ“œκ°€ λ³€ν•˜μ§€λŠ” μ•ŠλŠ”λ‹€.

더보기

μ œλ„€λ¦­μ€ 컴파일 νƒ€μž„μ— λ„μ™€μ£ΌλŠ” 도ꡬ이지, 컴파일 μ΄ν›„μ˜ λ°”μ΄νŠΈμ½”λ“œμ— λ³€ν™”λ₯Ό μ£Όκ±°λ‚˜ JVM의 μ„±λŠ₯을 ν–₯μƒμ‹œν‚€μ§€λŠ” μ•ŠλŠ”λ‹€. 컴파일 μ™„λ£Œ 된 λ°”μ΄νŠΈμ½”λ“œλ₯Ό λœ―μ–΄λ³΄λ©΄ μ œλ„€λ¦­μ€ java.lang.Object둜 μ„œμˆ λ˜μ–΄μžˆκΈ°μ— μžλ°” μ½”λ“œμ—μ„œ μ œλ„€λ¦­μ„ 일반 νƒ€μž…μœΌλ‘œ 바꿔도 λ°”μ΄νŠΈμ½”λ“œλŠ” λ™μΌν•˜λ‹€.

 

즉, μ•„λž˜μ˜ 두 μ½”λ“œλŠ” μ œλ„€λ¦­μ„ μ‚¬μš©ν•˜λ˜, κ·Έλƒ₯ Listλ₯Ό μ‚¬μš©ν•˜λ˜ λ™μΌν•œ λ°”μ΄νŠΈ μ½”λ“œλ₯Ό 생성을 ν•œλ‹€.

// λ§Œμ•½ List에 λ‹€λ₯Έ μžλ£Œν˜•μ΄ 듀어간닀해도 컴파일 μ‹œμ μ— 확인할 방법이 μ—†λ‹€.
// list에 λ‹€λ₯Έ νƒ€μž…μ„ 잘λͺ» 넣은 사싀을 κ°œλ°œμžκ°€ λ†“μΉœλ‹€λ©΄ μ‹¬κ°ν•œ λŸ°νƒ€μž„ 버그λ₯Ό λ§Œλ“€ 수 μžˆλ‹€.
List list = new ArrayList();
list.add("hello");
String str = (String) list.get(0); // λΆˆν•„μš”ν•œ Object -> String μΊμŠ€νŒ…
// μ œλ„€λ¦­μ€ νƒ€μž…μ„ λͺ…μ‹œμ μœΌλ‘œ λ‚˜νƒ€λ‚΄κ³ , 컴파일 μ‹œμ μ— 체크가 κ°€λŠ₯ν•˜λ‹€.
// ν•„μš”ν•˜λ‹€λ©΄ < exnteds, super > 등을 μ΄μš©ν•˜μ—¬ 컴파일 μ‹œμ μ— νƒ€μž…μ„ κ°•μ œν•  μˆ˜λ„ μžˆλ‹€.
List<String> list = new ArrayList<String>();
list.add("hello");
String str = list.get(0); // list에 λ‹€λ₯Έ νƒ€μž…μ΄ λ“€μ–΄κ°ˆ 수 μ—†λ‹€. νƒ€μž…μ΄ String으둜 κ°•μ œλœλ‹€.

μ œλ„€λ¦­μœΌλ‘œ μ„ μ–Έλœ κ°μ²΄λŠ” 컴파일 μ‹œμ μ— νƒ€μž…μ΄ κ²°μ •λœλ‹€. κ·Έλž˜μ„œ 클래슀 μ œλ„€λ¦­μ˜ 경우 Static λ©€λ²„λ‚˜ new 의 경우 μΈμŠ€ν„΄μŠ€κ°€ λ§Œλ“€μ–΄μ§€κΈ° μ „κΉŒμ§€ νƒ€μž…μ„ μ•Œ μˆ˜μ—†κΈ° λ•Œλ¬Έμ— μ œλ„€λ¦­ νƒ€μž…λ³€μˆ˜(T)λ₯Ό μ‚¬μš© ν•  수 μ—†μŒμ„ μœ μ˜ν•˜μž. 


# 클래슀 μ œλ„€λ¦­

 public class 클래슀λͺ…<T> { ... }    
 public interface μΈν„°νŽ˜μ΄μŠ€λͺ…<T> { ... }

public class Box<T> {
  private T t;

  public T get() { return t; }

  public void set(T t) { this.t = t }
}
Box<Integer> box = new Box<Integer>();
Box<String> box = new Box<String>();

// μ•„λž˜μ™€ 같이 μƒλž΅ν•˜λ”λΌλ„ μ»΄νŒŒμΌλŸ¬κ°€ μœ„μ˜ μ½”λ“œλ‘œ λ³€ν™˜ν•΄μ€€λ‹€.
Box<Integer> box = new Box<>();
Box<String> box = new Box<>();

 


# μ œλ„€λ¦­ λ©”μ„œλ“œ 

ν΄λž˜μŠ€κ°€ μ•„λ‹Œ λ©”μ„œλ“œ λ‹¨μœ„μ—μ„œλ„ μ œλ„€λ¦­ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€. λ°˜ν™˜κ°’ μ•žμ— <νƒ€μž…>을 λͺ…μ‹œν•΄μ£Όλ©΄ λœλ‹€.

 public <νƒ€μž…νŒŒλΌλ―Έν„°,...> λ¦¬ν„΄νƒ€μž… λ©”μ†Œλ“œλͺ…(λ§€κ°œλ³€μˆ˜,...) { ... }
 
 // λ°˜ν™˜κ°’ μ•žμ— νƒ€μž…μ„ λͺ…μ‹œν•΄μ£Όμ–΄μ•Όν•œλ‹€.
 public <T> Box<T> boxing(T t) { ... }
// μ‚¬μš©ν•  λ•Œλ„ λ§ˆμ°¬κ°€μ§€λ‘œ λ°˜ν™˜ κ°’ μ•žμ— νƒ€μž…μ„ λͺ…μ‹œν•΄μ£Όλ©΄ λœλ‹€.
Box<Integer> box = <Integer>boxing(100); 
Box<Integer> box = boxing(100); //java 7λΆ€ν„° νƒ€μž…μ„ μƒλž΅ν•  수 있게 λ˜μ—ˆλ‹€.

 


# λ©€ν‹°νƒ€μž… νŒŒλΌλ©”νƒ€

참고둜 μ œλ„€λ¦­μ— μ—¬λŸ¬νƒ€μž…μ„ μ‚¬μš©ν•˜λŠ” 건 Java 7λΆ€ν„° μ§€μ›ν•˜λŠ” κΈ°λŠ₯이닀.

class<K,V,...> { ... }
interface<K,V,...> { ... }
Product<TV, String> product = new Product<Tv,String>();
Product<Tv,String> product = new Product<>(); // νƒ€μž…μ„ μƒλž΅ν•΄λ„ λœλ‹€. μΆ”λ‘  κ°€λŠ₯
public class Pair<K, V> {
  private K key;
  private V value;

  public Pair(K key, V value) {
    this.key = key;
    this.value = value;
  }
  public void setKey(K key) {
    this.key = key;
  }

  public void setValue(V value) {
    this.value = value;
  }

  public K getKey() {
    return key;
  }

  public V getValue() {
    return value;
  }
}
public class Util {
  public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
    boolean keyCompare, valueCompare;
    keyCompare = p1.getKey().equals(p2.getKey());
    valueCompare = p1.getValue().equals(p2.getValue());

    return keyCompare && valueCompare;
  }
}

 


# μ œλ„€λ¦­ νƒ€μž… μ œν•œ

extends 와 superλ₯Ό μ΄μš©ν•˜μ—¬ νƒ€μž…μ„ μ œν•œ ν•  수 μžˆλ‹€. 참고둜 μ—¬λŸ¬ 클래슀 μ œμ•½μ„ λ™μ‹œμ— κ±Έκ³  μ‹Άλ‹€λ©΄ & μ—°μ‚°μžλ₯Ό μ“°λ©΄ λœλ‹€.

// ν•΄λ‹Ή νƒ€μž… λ˜λŠ” ν•΄λ‹Ή νƒ€μž…μ˜ μžμ‹ νƒ€μž…λ§Œ μ‚¬μš©κ°€λŠ₯
public <T extends νƒ€μž…> λ¦¬ν„΄νƒ€μž… λ©”μ†Œλ“œ(λ§€κ°œλ³€μˆ˜, ...) { ... }

// ν•΄λ‹Ή νƒ€μž… λ˜λŠ” ν•΄λ‹Ή νƒ€μž…μ˜ λΆ€λͺ¨ νƒ€μž…λ§Œ μ‚¬μš©κ°€λŠ₯
public <T super νƒ€μž…> λ¦¬ν„΄νƒ€μž… λ©”μ†Œλ“œ(λ§€κ°œλ³€μˆ˜, ...) { ... }

// 닀쀑상속은 μ•ˆλ˜μ§€λ§Œ, μΈν„°νŽ˜μ΄μŠ€μ˜ 경우 μ—¬λŸ¬ 클래슀의 μ œμ•½μ„ λ™μ‹œμ— κ±°λŠ” κ²½μš°λ„ 생긴닀.
public class Item<T extends Book & List> { }
// λ‹€μŒκ³Ό 같은 μ œλ„€λ¦­μ΄ μžˆμ„ λ•Œ
public class Item<T extends Book> { }

public class Book { } // μžκΈ°μžμ‹ , Book 클래슀 μ‚¬μš©κ°€λŠ₯
public class JavaBook extends Book { } // Book의 μžμ‹ν΄λž˜μŠ€ μ‚¬μš©κ°€λŠ₯

public class Drink { } // μƒκ΄€μ—†λŠ” 클래슀. μ‚¬μš©λΆˆκ°€λŠ₯
public <T extends Number> int compare(T t1, T t2) {
    double v1 = t1.doubleValue();
    double v2 = t2.doubleValue();

    return Double.compare(v1, v2);
}

 


# μ™€μΌλ“œ μΉ΄λ“œ

μ œλ„€λ¦­μœΌλ‘œ λ§Œλ“€μ–΄μ§„ 클래슀λ₯Ό μ‚¬μš©ν•˜λŠ” μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄μž.

class Juicer {
    static Juice makeJuice(FruitBox<Fruit> box) {
        String names = "";
        for(Fruit fruit : box.getList()) { names += fruit }
        return new Juice(names);
    }
}

μ œλ„€λ¦­μ„ λ§Œλ“€ λ•Œμ—λŠ” 별 λ¬Έμ œκ°€ 없을 쀄 μ•Œμ•˜μ§€λ§Œ, μ‚¬μš©ν•  λ•Œ λ‹€μŒκ³Ό 같은 λ¬Έμ œκ°€ λ°œμƒν•œλ‹€.

FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
Juicer.makeJuice(fruitBox); // OK

FruitBox<Grape> grapeBox = new FruitBox<Grape>();
Juicer.makeJuice(grapeBox); // Err!, FruitBoxλŠ” Fruitνƒ€μž…μœΌλ‘œ κ²°μ •λ˜μ–΄ λ³€κ²½λΆˆκ°€λŠ₯.

 

이 λ•Œ μ‚¬μš©ν•΄λΌκ³  λ§Œλ“  것이 μ™€μΌλ“œμΉ΄λ“œ( <?> ) 이닀. μ™€μΌλ“œμΉ΄λ“œλŠ” μ–΄λ– ν•œ νƒ€μž…λ„ 받을 수 μžˆλŠ” μ œλ„€λ¦­μΈλ°, 여기에 μ œλ„€λ¦­ μ œν•œμ„ κ±Έμ–΄ λ‚΄κ°€ μ›ν•˜λŠ” νŠΉμ • νƒ€μž…μ„ μ§€μ •ν•˜μ—¬ μ‚¬μš© ν•  수 μžˆλ‹€.

<? extends T> // T와 μžμ†λ“€λ§Œ κ°€λŠ₯
<? super T> // T와 μ‘°μƒλ“€λ§Œ κ°€λŠ₯
<?> // λͺ¨λ“  νƒ€μž… κ°€λŠ₯. <? extends Object>와 κ°™μŒ. 보톡 μ΄λ ‡κ²Œ μ‚¬μš©ν•˜μ§€λŠ” μ•ŠμŒ
// μ™€μΌλ“œ μΉ΄λ“œλ₯Ό μ΄μš©ν•˜μ—¬ μ œλ„€λ¦­μ„ κ΅¬ν˜„ν•˜λ©΄ λ‹€ν˜•μ„±μ„ κ΅¬ν˜„ν•˜κΈ° μ‰¬μ›Œμ§„λ‹€.
static Juice makeJuice(FruitBox<? extends Fruit>) {
    ...
}

FruitBox<Grape> grapeBox = new FruitBox<Grape>();
Juicer.makeJuice(grapeBox); // OK!

μ‹€μ œλ‘œ μ—¬λŸ¬ μžλ£Œν˜•μ„ λ‹€λ£¨λŠ” Collection의 경우 μ™€μΌλ“œμΉ΄λ“œλ₯Ό μ΄μš©ν•˜μ—¬ λ§Œλ“  λ©”μ„œλ“œλ“€μ„ 많이 λ³Ό 수 μžˆλ‹€.

static <T> void sort(List<T> list, Comparator<? super T> cmp)

 

λΈ”λ‘œκ·Έμ˜ 정보

JiwonDev

JiwonDev

ν™œλ™ν•˜κΈ°