ArrayList list = new ArrayList();
list.add(10)
list.add("20")
Integer i = (Integer)list.get(1);
//"20" 을 integer로 형변환하는것
클래스 작성 시 Object 타입 대신 타입 변수(E)를 선언해서 사용
기본적으로 타입 변수는 대문자 하나로 쓰는 것이 일반적임
객체 생성 시 타입 변수(E) 대신 실제 타입(Tv) 지정, 대입
타입 변수 E 대신 실제 타입 Tv를 넣어줘야 함
타입 변수 대신 실제 타입 지정 시, 형변환 생략 가능
용어 : 지네릭 클래스 / 타입 변수 / 원시 타입
다형성도 성립한다, 따라서 타입 매개변수의 자손들도 들어가기 가능 ㅇ
class TwoGen<T, V> {
T ob1;
V ob2;
TwoGen( T o1, V o2 ) {
ob1 = o1;
ob2 = o2;
}
void showTypes() {
System.out.println("Type of T : " + ob1.getClass().getName());
System.out.println("Type of V : " + ob2.getClass().getName());
}
T getob1() { return ob1; }
V getob2() { return ob2; }
}
public class Test2 {
public static void main(String[] args) {
TwoGen<Integer, String> x = new TwoGen<Integer, String>(55, "Hello");
x.showTypes();
int v = x.getob1();
System.out.println("value : " + v);
String w = x.getob2();
System.out.println("value : " + w);
}
}
Type parameter를 제한할 필요 시
Generics는 어떤 타입의 객체든 사용할 수 있도록 하겠다는 의미가 있음
그러나 특정 클래스들은 제한된 타입의 매개변수만 처리하기를 원함
class NumericFns<T> {
T num;
NumericFns(T n) {
num = n;
}
double reciprocal() {
return 1/num.doubleValue(); // num의 역수를 구하고자 함.
}
double fraction() {
return num.doubleValue() - num.intValue(); // num의 소수 부분만 구하고자 함.
}
}
doubleValue 이런 것은 Number class 타입들에게만 가능, 그러나 Generic은 모든 타입을 허용해서 에러,
에러인 이유 : Generics는 어떤 타입의 객체든 사용할 수 있도록 하겠다는 의미가 있는데 Number 클래스의 하위 클래스들에만 사용할 수 있는 메소드를 사용
따라서 위와 같은 경우 방지 위해 Type parameter를 명시할 때, 인수로 넣을 수 있는 클래스를 제한 필요
<T extends S>
T에는 클래스 S의 객체 또는 S의 하위 클래스 객체만 오도록 하기 가능
class Foo<T extends Number> {
T num;
Foo ( T n ) { num = n; }
boolean same( Foo<T> ob ) {
// *** same 메소드를 호출하는 객체와 패러미터 ob에 전달
// 되는 객체는 같은 타입이어야 한다.
if (Math.abs(num.doubleValue()) == Math.abs(ob.num.doubleValue()))
return true;
return false;
}
}
public class Test5 {
public static void main(String[] args) {
Foo<Float> x = new Foo<Float>(2.5f);
Foo<Double> y = new Foo<Double>(-2.5);
// 따라서 x의 same 메소드 매개변수는 무조건 Float여야 하는데,
// float이 들어갔다구 에러를 튕기게 되는 것
if ( x.same(y) ) System.out.println("same"); // 에러 발생
else System.out.println("different");
}
}
따라서 하나의 매개변수로 확정짓는 것이 아니라, 여러 종류의 타입을 허용해주는 것이 필요함 => 그것이 바로 wild card
와일드 카드로 위 코드를 수정해내보자 (아래코드로)
class Foo<T extends Number> {
T num;
Foo ( T n ) { num = n; }
boolean same( Foo<?> ob ) {
// same에 들어가는 매개변수를 와일드카드로 정의
if (Math.abs(num.doubleValue()) == Math.abs(ob.num.doubleValue()))
return true;
return false;
}
}
public class Test6 {
public static void main(String[] args) {
Foo<Integer> i = new Foo<Integer>(6);
Foo<Double> d = new Foo<Double>(-6.0);
Foo<Long> l = new Foo<Long>(5L);
// 그럼 SAME의 매개변수로 일치하는 타입이 오지 않아도 OK
if ( i.same(d) ) System.out.println("i, d -> equal");
else System.out.println("i, d -> different");
if ( i.same(l) ) System.out.println("i, l -> equal");
else System.out.println("i, l -> different");
}
}
◆ Generic 메소드는 parameter에 generics를 적용한다.
◆ Generic 메소드에서는 type parameter가 return type 앞에 와야 한다.
◆ Generic 클래스가 아니어도 generic 메소드 가질 수 있다.
◆ Generic 메소드는 static / nonstatic 모두 가능