블로그 이름 뭐하지
[JAVA] 제네릭 본문
타입을 일반화하는 것.
클래스 내부에서 개별적으로 타입을 지정하지 않고,
외부(인스턴스 생성 시, 메서드 호출 시)에서 타입을 지정한다.
class MyArray{
int element;
void setElement(int element) { this.element = element; }
int getElement() { return element; }
}
일반적인 타입지정△------제네릭사용▽
class MyArray<T> {
T element;
void setElement(T element) { this.element = element; }
T getElement() { return element; }
}
//외부에서 타입을 지정한다.
MyArray<Integer> myArr01 = new MyArray<Integer>;
MyArray<Double> myArr02 = new MyArray<Double>;
제네릭의 효용
1) 타입 언어에서 중복되거나 필요없는 코드를 줄여준다.
2) 타입 안정성을 해치지 않는다.
제네릭 문법
클래스, 메서드에 사용하며, 클래스 이름 뒤에 <>을 붙이고 타입변수를 지정한다.
타입변수는 임의의 참조형 타입을 의미하고, T 뿐 아니라 어떠한 문자가 들어가도 상관없다.
여러 개의 타입변수는 쉼표(,)로 구분하여 사용한다.
제한
1) 제네릭은 static 멤버에 사용할 수 없다.
(Bc static 멤버는 인스턴스 변수로 간주되고, 모든 객체에 동일하게 동작해야 하므로)
2) 제네릭 배열을 생성할 수 없다.
//제내릭 클래스(원시타입)
//<>안에 타입변수T
public class Generic<T> {
private T t;
public T get() {
return this.t;
}
public void set(T t) {
this.t = t;
}
public static void main(String[] args) {
//선언 >> T = String
Generic<String> stringGeneric = new Generic<>();
stringGeneric.set("Hello World");
String tValueTurnOutWithString = stringGeneric.get();
System.out.println(tValueTurnOutWithString);
}
}
문법
1) 다수의 타입변수 사용가능
public class Generic<T, U, E> { // 다수의 타입변수 T, U, E 사용
public E multiTypeMethod(T t, U u) { ... }
}
Generic<Long, Integer, String> instance = new Generic();
instance.multiTypeMethod(longVal, intVal);
2) 상속과 타입의 관계는 그대로 적용
(ex. 부모 클래스로 제네릭 타입 변수 지정 >> 그 안에 자식 클래스를 넘기는 것도 동작함)
3) 와일드 카드로 제네릭의 제한을 정할 수 있음
<? extends T> : T클래스와 그 자식클래스만 사용가능
<? super T> : T클래스와 그 부모클래스만 사용가능
<?> : 제한 없음
//<? extends class> : class와 그 자손들만 사용가능
public class ParkingLot<T extends Car> { ... }
ParkingLot<BMW> bmwParkingLot = new ParkingLot();
ParkingLot<Iphone> iphoneParkingLot = new ParkingLog(); // error!
4) 메서드를 스코프로 제네릭을 별도로 선언할 수 있음
반환 타입 앞에 제네릭을 사용한 경우 해당 메서드에만 적용되는 제네릭 타입 변수를 선언할 수 있다.
제네릭 클래스의 타입변수를 static 메서드에서는 사용할 수 없으나,
제네릭 메서드의 제네릭 타입변수는 메서드 하나를 기준으로 선언하고 사용할 수 있다.
같은 이름의 변수를 사용해도 제네릭 메서드의 타입변수는 제네릭 클래스의 타입 변수와는 다르다.
//불가능
//Student 클래스가 인스턴스화 하기 전에 static은 메모리에 올라가는데
//name의 타입인 T가 결정되어 있지 않기 때문.
public class Student<T> {
static T getName(T name) {
return name;
}
}
//가능
//제네릭 메서드는 호출시에 매개타입을 지정하기 때문.
//Student 클래스에서 지정한 <T>와 제네릭 메서드의 <T>는 별개의 타입변수다.
public class Student<T> {
static <T> T getOneStudent(T id) {
return id;
}
}
'JAVA' 카테고리의 다른 글
[JAVA] 모던 자바 : 람다식과 스트림 (0) | 2024.09.26 |
---|---|
[JAVA] 쓰레드 (0) | 2024.09.25 |
[JAVA] 예외 처리 (0) | 2024.09.24 |
[JAVA] 추상 클래스와 인터페이스 (0) | 2024.09.23 |
[JAVA] 상속 (0) | 2024.09.23 |