TIL) Java - 제네릭(Generics)

oatraspberry·2022년 12월 21일
post-thumbnail

제네릭(Generics)

변수의 선언이나 다양한 타입의 객체들을 다루는 메서드의 매개변수를 하나의 참조 자료형이 아닌 여러 자료형을 변환될 수 있도록 프로그래밍 하는 방식

컬렉션 프레임워크에서 많이 사용하고 있다.

객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어듦.

장점

  1. 타입 안정성을 제공한다.
  2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해 진다.

제네릭 클래스 정의하기

여러 참조 자료형으로 대체될 수 있는 부분을 하나의 문자로 표현한다.
이 문자를 자료형 매개변수라고 부름.

class Box<T>{ // 제네릭 타입 T를 선언
	T item;
    
    void setItem(T item) { this.item = item; }
    T getItem() { return item; }
}
Box<String> b = new Box<String>(); // 타입 T 대신, 실제 타입을 지정
b.setItem(new Object()); // 에러. String 이외의 타입은 지정 불가
b.setItem("ABC"); // OK. String 타입이므로 가능.
String item = (String) b.getItem(); // 형변환 필요없음.

제네릭의 용어

class Box<T> {}
/* Box<T> - 제네릭 클래스. 'T의 Box' 또는 'T Box'라고 읽음.
	T - 타입 변수 또는 타입 매개변수. (T는 타입 문자)
    Box - 원시타입(raw type) */

제네릭 타입 범위 제한(Bound)

모든 객체에 동일하게 동작해야하는 static 멤버에 타입 변수 T를 사용할 수는 없다. T가 인스턴스 변수로 간주되기 때문인데, static 멤버는 인스턴스 변수를 참조할 수 없다.

제네릭 타입의 배열을 생성하는 것도 허용되지 않는다. 제네릭 배열 타입의 참조변수를 선언하는 것은 가능하지만 new T[10]과 같이 배열을 생성하는 것은 불가능하다.

제네릭 타입에 특정 종류만을 사용하도록 제한하는 것

class Box<T> { // T : Type, K : Key, V : Value, E : Element
	T[] itemArr; // OK. T타입의 배열을 위한 참조변수
    	...
    T[] toArray() {
    	T[] tmpArr = new T[itemArr.length]; // 에러. 제네릭 배열 생성불가
        ...
        return tmpArr;
    	}
    }
  • 제네릭 클래스의 타입 제한
접근지정자 class 클래스명<T extends Fruit> { 
/* extends -> 클래스/인터페이스 상관없이 항상 extends 사용. 
	Fruit 또는 그 하위클래스만 가능*/
	// 타입 T를 사용한 코드
}

객체 생성 시 제네릭 타입을 지정하지 않으면 올 수 있는 Type 중 최상위 클래스(B)로 인식. 즉, 아래 두 코드는 동일한 의미임.

D d = new D();
D<B> d = new D<B>();
  • 제네릭 메서드의 타입 제한
접근지정자 <T extends 최상위클래스명> T 메서드이름(T t) { // 클래스/인터페이스 상관없이 항상 extends 사용
	// 부모클래스의 메서드 사용 가능
}
char charAt(int index)
- String 클래스의 메서드, String 문자열의 index 위치의 문자를 리턴
  • 일반메서드 매개변수로서의 제네릭 클래스 타입 제한
    메서드의 매개변수로 제네릭 클래스 객체가 오는 경우의 타입 제한

제네릭 클래스의 객체 생성

클래스명<실제 제네릭 타입> 참조 변수명 = new 클래스명<실제 제네릭 타입>();
클래스명<실제 제네릭 타입> 참조 변수명 = new 클래스명<>();

제네릭 클래스는 클래스를 정의하는 시점에 타입을 지정하는 것이 아니라 객체를 생성하는 시점에 타입을 지정함.

제네릭 메서드

리턴타입 또는 매개 변수의 타입을 제네릭 타입으로 선언
제네릭 메서드의 정의 문법 구조

  • 제네릭 타입 변수명이 한 개인 경우
접근지정자<T> T 메서드이름(T t) {
	// 타입 T를 사용한 코드
}
  • 제네릭 타입 변수명이 두 개인 경우
접근지정자<T, V> T 메서드이름(T t, V v) {
	// 타입 T를 사용한 코드
}
  • 매개변수에만 제네릭이 사용된 경우
접근지정자 int void 메서드이름(T t) {
	// 타입 T를 사용한 코드
}
  • 리턴타입에만 제네릭이 사용된 경우
접근지정자<T> T 메서드이름(int a) {
	// 타입 T를 사용한 코드
}
profile
개발자가 될테야

0개의 댓글