반응형

- 제네릭

/** Generic 사용 안 할 시 **/
//public class Box {
//	
//	private Object t;
//	public Object get() {return t;}
//	public void set(Object t) {this.t = t;}
//	
//}

/** Generic 사용 할 시 **/
public class Box<T> {
	
	private T t;
	public T get() {return t;}
	public void set(T t) {this.t = t;}
	
}

// 1. 실행시 타입 에러가 나는 것보다는 컴파일시에 미리 타입을 강하게 체크해 에러를 사전에 방지할 수 있다.
// 2. 타입 변환을 제거할 수 있다.
// → 이와 같은 방법으로 컬렉션프레임워크가 탄생하게 되었다.

Box.java

public class GenericBox {

	public static void main(String[] args) {

		/** Generic 사용 안 할 시 **/
//		Box box = new Box();
//		box.set("Apple");
//		String boxContent = (String) box.get();
//		
//		Box boxInteger = new Box();
//		boxInteger.set(10);
//		int boxContentInteger = (int) boxInteger.get();
		
		
		
		/** Generic 사용 할 시 **/
		Box<String> box = new Box();
		box.set("Apple");
		String boxContent = box.get();

		Box<Integer> boxInteger = new Box();
		boxInteger.set(10);
		int boxContentInteger = boxInteger.get();
		
		
	}

}

GenericBox.java

 

- 제네릭<멀티타입>

public class Product<T, M> {

	private T kind;
	private M model;
	
	public void setModel(M model) {
		this.model = model;
	}

	public void setKind(T kind) {
		this.kind = kind;
	}
	
	public T getKind() {
		return kind;
	}
	
	public M getModel() {
		return model;
	}
	
}

// Product<Tv, String> product = new Product<>(); 이와 같이 사용

Product.java 이렇게 멀티타입도 가능하다.

 

 

- 제네릭 메소드, 제네릭 <멀티타입> 메소드

public class Util {
	// 기본 구조 : <T> 리턴타입 메소드명
	// return type : box<T> 제너릭으로 선언된 Box Class
	// 동작 : box 객체 선언 후 T 타입의 값을 box에 넣는다.
	public <T> Box<T> boxing(T t){ 
		
		Box<T> box = new Box<T>();
		box.set(t);
		return box;
	}
	
	// 멀티타입 제너릭 메소드 (두 객체의 키와 값을 비교하기)
	public <Key,Value> boolean compare(Pair<Key,Value> p1, Pair<Key,Value> p2) {
		
		boolean isSameKey = p1.getKey().equals(p2.getKey());
		boolean isSameValue = p1.getValue().equals(p2.getValue());
		
		boolean isSame = (isSameKey && isSameValue) ? true : false; 
		System.out.println("isSame ? : " + isSame);
		
		return isSame;
	}
	
}

Util.java

/** Generic 사용 할 시 **/
public class Box<T> {
	
	private T t;
	public T get() {return t;}
	public void set(T t) {this.t = t;}
	
}

Box.java

 

import java.util.HashMap;

public class GenericMethod {

	public static void main(String[] args) {

		/**  제너릭 메소드  **/
		Util util = new Util();
		Box<Integer> box = util.<Integer>boxing(100);
		int intValue = box.get();
		System.out.println(intValue);
		
		Box<String> box1 = util.<String>boxing("홍길동");
		String intValue1 = box1.get();
		System.out.println(intValue1);
		
		
		/**  멀티타입 제너릭 메소드  **/
		// 어디서 많이 본듯한 형태 → 컬렉션프레임워크 hashMap
		Pair<Integer,Integer> pair = new Pair<>(100,200);  
		Pair<Integer,Integer> pair1 = new Pair<>(100,200); 
		
		System.out.println(util.compare(pair, pair1));
		
		HashMap<String, String> at = new HashMap<>();
	}

}

GenericMethod.java

 

 

 

- 제네릭 상속

public class Util {
	// Number로 구현된 클래스만 사용 가능 int, double 등...
	// Number에서 상속받은 메소드 사용 가능 
	// return type : int
	public static <T extends Number> int compare(T t1, T t2) {

		
		double v1 = t1.doubleValue();
		double v2 = t2.doubleValue();
		
		return (int) (v1 + v2);
	}
	
}

Util.java

 

 

 

 

- 와일드카드

public class WileCard {

	public static void registerCourse(Course<?> course) {

	}

	public static void registerCourseStudent(Course<? extends Student> course) {

	}

	public static void registerCourseWorker(Course<? super Student> course) {
		
	}
	public static void main(String[] args) {

		/** 모든 클래스 사용 가능 **/
		registerCourse(new Course<Person>("일반인 과정", 5));
		registerCourse(new Course<Student>("학생", 5));
		registerCourse(new Course<Worker>("근로자", 5));
		registerCourse(new Course<HighStudent>("고등학생 과정", 5));

		/** 하위 클래스만 사용 가능 **/
		registerCourseStudent(new Course<Person>("일반인 과정", 5)); // Student 클래스 상속 안 받은 Person 클래스 이기 때문에 사용 불가
		registerCourseStudent(new Course<Student>("학생", 5));
		registerCourseStudent(new Course<Worker>("근로자", 5)); // Student 클래스 상속 안 받은 Worker 클래스 이기 때문에 사용 불가
		registerCourseStudent(new Course<HighStudent>("고등학생 과정", 5));

		/** 상위 클래스만 사용 가능 **/
		registerCourseWorker(new Course<Person>("일반인 과정", 5));
		registerCourseWorker(new Course<Student>("학생", 5));
		registerCourseWorker(new Course<Worker>("근로자", 5)); // Student의 상위 클래스가 아니라 사용 불가
		registerCourseWorker(new Course<HighStudent>("고등학생 과정", 5)); // Student의 상위 클래스가 아니라 사용 불가
	}

}

WildCard.java

 

public class Course<T> {
	
	private String name;
	private T[] students;
	public Course(String name, int capacity) {
		
		this.name = name;
		students = (T[]) (new Object[capacity]); 
		// T가 정해지지 않았는데 바로 사용 불가능 최상위 클래스 Object로 구현 한 다음 타입 변환 필요
	}
	
	public String getName() {
		return name;
	}
	
	public T[] getStudents() {
		return students;
	}
	
	
}


Course.java

 

public class Person {

	private String name;

	public Person(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

Person.java

public class Worker extends Person{
	public Worker(String name) {
		super(name);
	}
}

Worker.java

public class Student extends Person{
	public Student(String name) {
		super(name);
	}
}

Student.java

public class HighStudent extends Student{
	public HighStudent(String name) {
		super(name);
	}
}

HightStudent.java

 

 

-  제네릭 상속

public class Product<T,M> {

	private T kind;
	private M model;
	
	public T getKind() {
		return kind;
	}
	public void setKind(T kind) {
		this.kind = kind;
	}
	public M getModel() {
		return model;
	}
	public void setModel(M model) {
		this.model = model;
	}	
}

Product.java

 

// 자식 클래스는 무조건 부모 클래스의 제너릭 타입 이상을 가져야한다. (K, V 반드시 포함)
public class ChildProduct<K,V,C> extends Product<K, V> {

	
}

ChildProduct.java

 

public class ExtendsGeneric {

public static void main(String[] args) {

		ChildProduct<String, String, Integer> childProduct = new ChildProduct<>();
		
	}

}

ExtendsGeneric.java

반응형