Generic

2 minute read

Generic

Object 는 모든 자바 객체를 받을 수 있다.

Box<Object> b = new Box<Object>(); // 오브젝트로 타입 지정.
b.setItem("ABC"); // 경고 발생 안함.
b.setItem(new Object()); // 경고 발생 안함.
  • Box 클래스의 인스턴스 변수를 Object로 선언하면 다양한 객체를 보관할 수는 있지만, 특정 타입의 객체로 제한할 수 없다.
  • 그렇다고 각 타입 별로 Box 클래스를 정의하는 것은 바람직하지 않다.
    • 각 타입 별로 Box 클래스를 정의하면 코드가 중복된다.

제네릭이란?

  • 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능.
  • 객체 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어든다.
  • 타입 체크와 형변환을 생략할 수 있으므로 코드가 간결해진다.
Box<String> b = new Box<String>(); // 타입 지정.
b.setItem(new Object()); // 에러. String 이외의 타입은 지어 불가.
b.setItem("ABC"); // String 타입이므로 가능.
String item = /*(String)*/ b.getItem(); // 형변환 불필요.

T 변수

  • T 변수는 Box 클래스가 다루는 객체의 타입을 가리킨다.
    • 그래서 T 변수를 타입 파라미터라고 부른다.
  • 타입 파라미터도 변수이기 때문에 다음과 같이 이름을 짓는다.
    • dataType, obj, element 등
    • 그러나 보통 코드를 간략히 하기 위해 한 개의 알파벳으로 표현한다.
      • T : type
      • E - element
      • K - key
      • V - value
      • N - number
    • 여러 개의 타입 파라미터를 선언해야 할 경우 , 로 연결한다.

제네릭의 제한

  • static 멤버는 인스턴스 변수를 참조할 수 없다.
    • 모든 객체에 대해 동일하게 동작해야 하기 때문에 제네릭을 사용할 수 없다.
  • 제네릭 타입의 배열을 생성하는 것도 허용되지 않는다.
    • 배열을 생성할 때 컴파일 시점에 제네릭의 타입이 무엇인지 정확하게 알아야 하기 때문이다.

제한된 제네릭

  • 제네릭에 extends 를 사용하면 특정 타입과 그 자손들을 대입할 수 있게 제한할 수 있다.
  • 인터페이스를 구현해야 한다면 extends 와 & 를 사용해서 구현한다.

와일드 카드

  • 메서드 중복 정의가 되었을 때 사용하는 것이 와일드 카드이다.
  • 와일드 카드는 기호 ? 로 표현한다.
  • 와일드 카드는 어떠한 타입도 될 수 있다.
  • <? extends T> : 와일드 카드의 상한 제한. T와 그 자손들만 가능.
  • <? super T> : 와일드 카드의 하한 제한. T와 그 조상들만 가능.
  • <?> : 제한 없음. 모든 타입이 가능. <? extends Object> 와 동일.

제네릭 메서드

  • 메서드의 선언부에 제네릭 타입이 선언된 메서드를 제네릭 메서드라고 한다.
  • 제네릭 타입의 선언 위치는 반환 타입 바로 앞이다.
  • static 멤버에는 제네릭을 사용할 수 없지만, 메서드에 제네릭 타입을 선언하고 사용하는 것은 가능하다.
    • 지역 변수를 선언한 것과 같다.
    • 제네릭으로 타입이 선언된 변수는 메서드 내에서만 지역적으로 사용될 것이므로 메서드가 static이든 아니든 상관없다.

제네릭의 형변환

  • 제네릭 타입과 원시 타입 간의 형변환은 가능하다. 하지만 경고가 뜬다.
  • 각기 다른 제네릭 타입 간의 형변환은 불가능하다.
  • 일반적인 제네릭 타입을 와일드 카드 형으로 형변환 하는 것은 가능하다. 매개변수의 다형성이 적용될 수 있다.
    • 반대로의 형변환도 성립하지만 확인되지 않은 형변환이라는 경고가 발생한다.
    • 와일드 카드 타입을 여러 타입으로 변형될 수 있기 때문이다.

제네릭의 제거

  • 메서드 도입부의 제네릭을 제거한다.
  • 각 객체들을 적절하게 형변환을 해준다.

Categories:

Updated: