JAVA

배경

같은 로직을 가지고, 두 타입의 자료를 다루는 경우를 생각해보자.

새우만 담을 수 있는 통과, 조개만 담을 수 있는 통이 있을 때 안에 들어있는 조개와 새우를 넣고 뺴는 행위(공통 로직)에는 변함이 없지만 통을 따로 나누어야만 한다.(코드의 분리) 하지만 따로 통에 들어갈 수 있는 해산물을 정하지 않고, 해산물 통으로 분류하고, 들어오는 해산물에 따라서 담는다면 편할 것이다.(코드의 재사용)

제네릭의 사용으로 코드 재사용과 타입 안정성을 모두 잡을 수 있다.

제네릭의 핵심은 사용할 타입을 미리 정하지 않는다는 것이다.

제네릭

  • 제네릭(Generic)
  • 제네릭 타입(Generic Type)
    • 클래스나 인터페이스를 정의할 때 타입 매개변수를 사용하는 것
  • 타입 매개변수(Type Parameter)
    • 제네릭 타입이다 메서드에서 사용되는 변수로, 실제 타입으로 대체된다.
  • 타입 인자(Type Argument)
    • 제네릭 타입을 사용할 때 제공되는 실제 타입

타입 매개변수 제한

기본적인 제네릭 타입으로 타입인자를 받을 경우, 제네릭 타입은 Object라면 모두 받을 수 있기 떄문에 타입을 제한할 수 없음

제약을 걸어 사용을 가능하게 함. ex) T extends Animal

제네릭 메서드

  • 정의 : <T> T genenricMethod(T t)
  • 타입 인자 전달 : 메서드를 호출하는 시점
  • 호출 : GenericMethod.<타입 인자>genericMethod(i) 타입 추론이 지원되기 때문에 매번 타입 인자를 적어주지 않아도 됨

와일드카드

와일드카드는 제네릭 타입, 제네릭 메서드를 선언하는 것이 아니다. 와일드카드는 이미 만들어진 제네릭 타입을 활용할 때 주로 사용한다.

제네릭 메서드와 와일드 카드의 사용 기준

기본적으로 사용하기 간단한 와일드 카드를 사용한다. 하지만 전달된 제네릭 타입 인자를 사용하거나 반환해야 하는 경우에는 제네릭 메서드를 사용해야 한다.

상한과 하한
  • extends : 상한 지정 ? extends Animal : Animal 하위 타입 지정 가능
  • super : 하한 지정 ? super Animal : Animal 상위 타입만 지정 가능 ex) Object

타입 이레이져

[!개념] 제네릭은 자바 컴파일 단계에서만 사용되고, 컴파일 이후에는 제네릭 정보가 삭제된다. .java 단계에서는 타입 매개변수가 존재하지만, 컴파일 이후 자바 코드인 .class 단계에서는 타입 매개변수가 존재하지 않는다.

컴파일 이전

public class GenericBox<Integer> {
 
private Integer value;
	public void set(Integer value) {
		this.value = value;
	}
	
	public Integer get() {
		return value;
	}
}

컴파일 이후

public class GenericBox {
	private Object value;
	
	public void set(Object value) {
		this.value = value;
	}
 
	public Object get() {
		return value;
	}
}

상한 제한이 없는 경우 T는 Object로 모두 변환


타입 이레이져 방식의 한계

instanceof, new 사용 불가하다.