Recent Posts
Recent Comments
Link
11-22 03:39
Today
Total
관리 메뉴

삶 가운데 남긴 기록 AACII.TISTORY.COM

Generic 본문

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

'DEV&OPS > Java' 카테고리의 다른 글

List 컬렉션  (0) 2022.05.09
람다식  (0) 2022.05.06
Thread Pool  (0) 2022.04.20
JAVA Thread  (0) 2022.04.19
Format 클래스  (0) 2022.04.12