자바 제네릭(Generic)

dykwon·2024년 1월 16일

제네릭을 사용하는 이유

  1. 컴파일 시, 강한 타입 체크를 할 수 있다.
    • 자바 컴파일러는 코드에서 잘못 사용된 타입 때문에 발생하는 문제를 제거하기 위해, 제네릭 코드에 대해 강한 타입 체크를 진행한다.
  2. 타입 변환(Casting)을 제거한다.
    • 비제네릭 코드는 캐스팅을 불필요하게 진행하기때문에 프로그램 성능에 악영향을 미친다.

제네릭 타입

  1. 제네릭 타입은 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다.
  2. 제네릭 타입은 클래스 또는 인터페이스 이름뒤에 <> 부호가 붙고, 그 사이에 타입 파라미터가 위치한다.
// 아래에서 타압 파라미터는 T가 된다
public class clazz<T> { ... }
public interface interfaze<T> { ... }
  1. 최상위 클래스인 Object를 사용하면 다양한 Class를 Object 인스턴스에 담을 수 있지만, 항상 해당 Class로 강제형변환해야만 하는 단점이 있다.
  2. 이러한 문제를 타입 파라미터를 통해 코드 작성 시 구체적인 타입으로 대체되어 다양한 코드를 생성하도록 돕는다.
public class Box<T>{
	private T t;
    public T get() { return t; }
    public void set(T t) { this.t = t; }
}

public class BoxExample{
	Box<String> sBox = new Box<>();
    sBox.set("String");
    Box<Integer> iBox = new Box<>();
    iBox.set(123);
}

타입 매개변수의 보편적인 네이밍 규칙

● E Element
● K Key
● N Number
● T Type
● V Value

멀티타입 파라미터

  1. 제네릭 타입은 두개 이상의 멀티 타입 파라미터를 사용 할 수 있다.
  2. 이때 타입 파라미터들은 "," 로 구분한다.
  3. 예를들어 className<K, V, T> 또는 interfaceName<K, V>와 같이 나타낸다.
public class Box<T, M>{
	private T kind;
    private M model;
    
    public T getKind() { return this.kind; }
    public M getModel { return this.model; }
    
    public void set(T kind) { this.kind = kind; }
    public void set(M model) { this.model = model; }
}

public class BoxExample{
	Box<Tv, String> tvBox = new Box<>();
    tvBox.setKind(new Tv());
    tvBox.setModel("LG");
    
    Tv tv = tvBox.getKind();
    
    Box<Car, String> carBox = new Box<>();
    carBox.setKind(new Car());
    carBox.setModel("Tesla");
    
    Car car = carBox.gerKind();
}

제네릭 메소드

  1. 제네릭 메소드는 매개 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드를 말한다.
public <타입 파라미터> 리턴 타입 메소드명(매개변수 ....){ ... }
public <T> Box<T> boxing(T t) { ... }
public class Util {
	public static <T> Box<T> boxing(T t) {
    	Box<T> box = new Box<T>();
        box.set(t);
        return box;
    }
}

public class Exmaple{
	Box<Integer> iBox = Util.boxing(100);
    Box<String> sBox = Util.boxing("str");
}

제한된 타입 파리미터

  1. 제한된 타입 파라미터를 선언하려면 타입 파라미터 뒤에 extends 키워드를 붙이고 상위 타입을 명시한다.
  2. 상위 타입은 클래스와 인터페이스를 명시 할 수 있다. 단, 인터페이스라고 해서 implements가 아닌 extends를 사용한다.
Class Util {      
  public static <T extends Number> int compare(T t1, T t2) {
    double v1 = t1.doubleValue();
    double v2 = t2.doubleValue();

    return Double.compare(v1, v2);
  }
}

와일드카드 (Wildcard)

  1. 코드에서 일반적으로 *, ? 등 을 와일드 카드라고 부른다.
  2. 제네릭 타입을 매개 값이나 리턴 타입으로 사용할 때 구체적인 타입 대신 와일드 카드를 다음과 같이 사용할 수 있다.
  • < ? extends T > : 와일드 카드의 상한 제한. T와 그 자식 클래스만 가능
  • < ? super T > : 와일드 카드의 하한 제한. T와 그 조상들만 가능
  • < ? > : 모든 타입이 가능
  1. 예를 들어 매개 변수와 같은 값을 methodName(? extends Student)와 같이 작성하면, Student 클래스와 자식 클래스만 제네릭 타입으로 사용이 가능하다.

상속과 인터페이스 사용

  1. 제네릭 타입 클래스의 자식 클래스를 선언하는 경우 extends를 활용하여 선언이 가능하다.
    이때 타입 파라미터는 추가될 수 있으며 부모 제네릭 타입 클래스의 필드와 메소드를 그대로 사용할 수 있다.
  2. 제네릭 인터페이스를 선언한 경우 제네릭 타입 클래스를 선언하고 메소드 override를 통해 이를 구현할 수 있다.
profile
Programmer, who turns ideas into value

0개의 댓글