본문 바로가기
IT 이야기/Java

[Java Study] 14일차 제네릭(generic)

by Dblog 2021. 2. 22.
728x90

학습할 것

  • 제네릭 사용법
  • 제네릭 주요 개념 (바운디드 타입, 와일드 카드)
  • 제네릭 메소드 만들기
  • Erasure

 


 

Generic

넓게보면 숨쉬듯 생겨나는 버그를 어느정도 방지해주는 역할을 하게 됩니다. 

이런 행위가 가능한 이유는 자바를 사용하면서 데이터의 타입 때문에 생기는 버그에 대해 강력하게 방지할 수 있습니다. 이는 미리 받을 데이터의 타입을 확인하기 때문에 가능합니다.

제너릭을 사용하는 이유로 oracle에선 3가지를 공유하고 있습니다. 

 

  • 컴파일 타임에 더욱 강력한 유형 검사

런타임전에 컴파일 단계에서 오류를 발생시켜 런타임에서의 오류를 감소 시킵니다.

 

  • cast 제거

그동안 타입을 변환할때 casting을 사용했습니다. 

List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);

 

하지만 이제 더이상 casting을 할 필요가 없습니다.

List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);   // no cast

 

 

  • 프로그래머가 알고리즘을 구현할 수 있도록 허용

프로그래머는 제너릭을 사용해 다양한 유형의 안전하고 읽기 쉬운 알고리즘을 구현할 수 있습니다.

 

제네릭 사용법

 

사용법

// https://docs.oracle.com/javase/tutorial/java/generics/types.html

/**
 * Generic version of the Box class.
 * @param <T> the type of the value being boxed
 */
public class Box<T> {
    // T stands for "Type"
    private T t;

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

제너릭은 형태를 가지고 있으며 아래 코드와 같은 방식으로도 자주 사용됩니다.

Box <Integer> integerBox;

 

명명규칙

E Element
K Key
N Number
T Type
V Value
S, U, V, ...etc 2nd, 3rd, 4th types

개발자의 의도에 따라 명명규칙을 지키지 않아도 상관없지만, 더욱 가독성 좋은 코드를 위해 명명 규칙에 따라 코드를 작성하는 것을 권장하고 있습니다. 

 

제네릭 주요 개념 (바운디드 타입, 와일드 카드)

 

  • Bounded Type

제네릭 타입의 범위를 제한하는 경우가 생길수 있습니다. 그럴 경우를 대비하여 만들어진게 Bounded Type입니다. 

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<Integer>();
        integerBox.set(new Integer(10));
        integerBox.inspect("some text"); // error: this is still String!
    }
}

 

 

  • Wildcard

와일드 카드는 제네릭으로 구현된 메소드에 어떤 타입이 와도 상관 없는 경우, 즉 타입이 애매할때 사용할 수 있다고 하는데 아직까진 크게 와닿지 않습니다. .

 

 

 

제네릭 메소드 만들기

메소드에 <K, V>로 제네릭을 선언할 수 있습니다. 

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

 

 

Erasure

 

Type Erasure는 살면서 처음봤습니다. 컴파일 단계에서만 제네릭을 적용하고 런타임 단계에서는 제네릭을 적용하지 않는것 처럼 보이는데 실제로 실습해봐야 할것 같 습니다. 

Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "pear");
boolean same = Util.<Integer, String>compare(p1, p2);

이 코드가 런타임에서는

Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "pear");
boolean same = Util.compare(p1, p2);

로 변경된다고 합니다.

 

728x90

'IT 이야기 > Java' 카테고리의 다른 글

JPA Default value 적용 - @DynamicInsert  (0) 2021.07.20
POJO Class  (0) 2021.06.28
[Java Study] 13일차 I/O [input/output]  (0) 2021.02.13
[Java Study] 12일차 Annotation  (0) 2021.02.04
[Java Study] 11일차 Enum  (0) 2021.01.26

댓글