제너릭 : 클래스에서 다룰 객체를 미리(객체 생성시에) 명시해줌으로써 형 변환을 하지 않고 사용하는 것
필요성
public class genericTest {
public static void main(String[] args) {
Basket basket = new Basket();
basket.set('A');
char A = (char) basket.get(); // 매번 가져올 때마다 수동 형변환이 필요
}
class Basket {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
다운 캐스팅의 문제점
장점
제네릭 클래스(Generic Class)
제네릭 클래스 표현 방법, 예시
public class 클래스명<타입 매개변수>{ ... }
public interface 인터페이스명<타입 매개변수>{ ... }
--------------------------
class Basket2<T> {
private T t;
public T get() { return t; }
public void set(T t) { this.t = t; }
}
public class genericTest {
public static void main(String[] args) {
// 사용 방법
Basket2<Character> basket2 = new Basket2(); // 객체 생성시 특정 타입 지정
basket2.set('A');
char A = basket2.get();
// 객체 생성시 아래와 같이 생략 가능
Basket2<Character> basketExample1 = new Basket2();
Basket2<Character> basketExample2 = new Basket2<>();
Basket2<Character> basketExample3 = new Basket2<Character>();
}
}
타입 매개변수 예시
타입인자 | 설명 |
---|---|
< T > | Type |
< E > | Element |
< K, V > | Key, Value |
< R > | Result |
용어 정리
public class Basket<T>
-----------------------------
Basket // 원시 타입 (여기서 '원시'는 primitive가 아니라, raw를 의미)
Basket<T> // T Basket
T // 타입 매개변수, 타입 변수
<> // 다이아몬드 연산자
제네릭 메소드(Generic Method)
public class genericMethodTest {
public static void main(String[] args) {
String stringExample = UseGenericMethod.ToString(3453);
System.out.println(stringExample.getClass()); // 3453
System.out.println(UseGenericMethod.equal1234(1234)); // true
System.out.println(UseGenericMethod.equal1234("1234")); // false
}
}
class UseGenericMethod {
public static <T> String ToString(T t) {
return t.toString();
}
public static <T> boolean equal1234(T t) {
return t.equals(1234);
}
// 특정 타입에서만 사용 할 수 있는 메서드는 사용불가
// public static <T> int hashcode (T t1,T t2) {return Integer.sum(t1,t2);}
}
<?> //타입 매개변수에 모든 타입 사용
<? extends T> //T 타입과 T타입을 상속받는 하위 클래스 타입만 사용
<? super T> // T 타입과 T타입을 상속받은 상위 클래스 타입만 사용
public class WildcardTest {
public static void main(String[] args) {
LowerClass1 lowerClass1 = new LowerClass1();
LowerClass2 lowerClass2 = new LowerClass2();
CoverClass<LowerClass1> coverLowerClass1 = new CoverClass<>(lowerClass1);
CoverClass<LowerClass2> coverLowerClass2 = new CoverClass<>(lowerClass2);
UseWildcard.getVariable1(coverLowerClass1);
UseWildcard.getVariable1(coverLowerClass2);
UseWildcard.showAddress(coverLowerClass1);
// UseWildcard.showAddress(coverLowerClass2); // ERROR : super 조건에 어긋남
}
}
class UpperClass {int variable1 = 3;}
class LowerClass1 extends UpperClass {int variable2;}
class LowerClass2 extends UpperClass {int variable3;}
class CoverClass<T>{
T element;
CoverClass(T element){this.element = element;}
}
class UseWildcard{
// 기본 예시
static Number process(List<? extends Number> list){
return list.get(0);
}
// 활용 예시
static int getVariable1(CoverClass<? extends UpperClass> coverClass){
return coverClass.element.variable1;
}
static void showAddress(CoverClass<? super LowerClass1> coverClass){
// super 또는 ? 일 때는 Object의 메서드만 사용 가능
System.out.println(coverClass);
// System.out.println(coverClass.element.variable2); // 사용불가
}
}
https://jinbroing.tistory.com/228 참고해서 더 공부할 것