DEV&OPS/Java
Generic
ALEPH.GEM
2022. 4. 21. 14:36
제네릭 타입은 JDK5부터 지원됩니다.
제네릭은 잘못 사용된 데이터 타입 때문에 발생하던 문제를 컴파일 과정에서 제거하고 불필요한 casting을 하지 않도록 해줍니다.
제네릭 타입
public class BoxExample {
public static void main(String[] args) {
Box<String> box1 = new Box<String>();
box1.set("BOX");
String str = box1.get();
System.out.println(str);
Box<Integer> box2 = new Box<Integer>();
box2.set(4);
int value = box2.get();
System.out.println(value);
}
}
class Box<T>{
private T t;
public T get() {return t;}
public void set(T t) {this.t = t;}
}
제네릭 메서드
public class BoxingMethodEx {
public static void main(String[] args) {
Box<Integer> box1 = Util.<Integer>boxing(100);
int intValue = box1.get();
System.out.println(intValue);
Box<String> box2 = Util.boxing("글자");
String strValue = box2.get();
System.out.println(strValue);
}
}
class Util{
//제네릭 메소드
public static <T> Box<T> boxing(T t){
Box<T> box = new Box<T>();
box.set(t);
return box;
}
}
제네릭 (타입, 메소드) 추정
public class CompareMethodEx {
public static void main(String[] args) {
Pair<Integer, String> p1 = new Pair<Integer, String>(1, "과자");
Pair<Integer, String> p2 = new Pair<Integer, String>(2, "주스");
boolean result1 = Util2.<Integer, String>compare(p1, p2); //타입을 명시적으로 지정
if(result1) {
System.out.println("동등한 객체입니다.");
}else {
System.out.println("동등하지 않은 객체입니다.");
}
Pair<String, String> p3 = new Pair<String, String>("1", "과자");
Pair<String, String> p4 = new Pair<String, String>("1", "과자");
boolean result2 = Util2.compare(p3, p4); //타입을 지정하지 않아도 자동으로 타입을 추정
if(result2) {
System.out.println("동등한 객체입니다.");
}else {
System.out.println("동등하지 않은 객체입니다.");
}
}
}
//제네릭 타입
class Pair<K, V>{
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public void setKey(K key) {
this.key = key;
}
public void setValue(V value) {
this.value = value;
}
public K getKey() {return key;}
public V getValue() {return value;}
}
//제네릭 메서드
class Util2{
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
boolean keyCompare = p1.getKey().equals(p2.getKey());
boolean valueCompare = p1.getValue().equals(p2.getValue());
return keyCompare && valueCompare;
}
}
제한된 타입 파라미터
제네릭을 사용할 때 타입을 제한해야 하는 경우가 있습니다.
<T extends 상위 타입> 처럼 사용합니다.
클래스가 아니라 비록 인터페이스라도 implements가 아닌 extends로 지정해야 합니다.
public class BoundedTypeEx {
public static void main(String[] args) {
//String str = Util3.compare("a", "b"); //Number 타입이아님
int result1 = Util3.compare(10, 20); //자동 boxing int -> Integer
System.out.println(result1);
int result2 = Util3.compare(4.5, 3); //자동 boxing double -> Double
System.out.println(result2);
}
}
class Util3{
public static <T extends Number> int compare(T t1, T t2) {
double v1 = t1.doubleValue();
double v2 = t2.doubleValue();
return Double.compare(v1, v2);
}
}
와일드카드 타입 <?>
와일드카드 문자인 ?을 이용해서 제네릭 타입을 <?> , <? extends 상위타입>, <? super 하위타입>
으로 지정해줄 수 있습니다.
제네릭 타입의 상속과 구현
제네릭 타입도 일반적인 데이터 타입들 처럼 부모 클래스가 될수 있고, 아래처럼 자식 타입에서 추가적으로 타입 파라미터를 가질 수 있습니다.
public class ChildProduct<T, M, C> extends Product<T, M> { ... }
public class GenericEX {
public static void main(String[] args) {
ChildProduct<Tv, String, String> product = new ChildProduct<>();
product.setKind(new Tv());
product.setModel("Smart TV");
product.setCompany("LG");
Storage<Tv> storage = new StorageImpl<Tv>(100);
storage.add(new Tv(), 0);
Tv tv = storage.get(0);
}
}
class Product<T, M>{
private T kind;
private M model;
public T getKind() {return this.kind;}
public M getModel() {return this.model;}
public void setKind(T kind) {this.kind = kind;}
public void setModel(M model) {this.model = model;}
}
class Tv{}
class ChildProduct<T, M, C> extends Product<T, M>{
private C company;
public C getCompany() { return this.company;}
public void setCompany(C company) {this.company = company;}
}
interface Storage<T>{
public void add(T item, int index);
public T get(int index);
}
class StorageImpl<T> implements Storage<T>{
private T[] array;
public StorageImpl(int capacity) {
this.array = (T[]) (new Object[capacity]); //타입 파라미터로 배열을 생성할 때 T[n] 으로 하지 않고 Object를 이용해 생성
}
@Override
public void add(T item, int index) {
array[index] = item;
}
@Override
public T get(int index) {
return array[index];
}
}
728x90