제네릭은 하나의 변수가 하나의 참조 자료형만 가지는게 아닌, 여러개의 참조자료형을 가질 수 있는 기능 중 하나이다.
만약 3D 프린터로 무언가를 만든다고 했을 때 그 안에 있는 재료는 무엇이든 될 수 있다.
그 재료가 바뀔 때마다 그 재료에 맞는 프린터를 사용하는 것은 비효율적이고, 비용이 많이 든다. 제네릭은 동일한 프린터기에 다른 재료들을 넣어서 생산할 수 있게끔 도와준다.
Powder 클래스
package generics;
public class Powder {
public void doPrinting() {
System.out.println("Poder 재료로 출력합니다.");
}
@Override
public String toString() {
return "재료는 Powder 입니다";
}
}
Plastic 클래스
package generics;
public class Plastic {
public void doPrinting() {
System.out.println("Plastic 재료로 출력합니다.");
}
@Override
public String toString() {
return "재료는 Plastic 입니다";
}
}
GenericPrinter
package generics;
public class GenericPrinter<T> {
private T material;
public void setMaterial(T material) {
this.material = material;
}
public T getMaterial() {
return material;
}
public String toString() {
return material.toString();
}
}
- 이 3D 프린터기는 어떤 재료로도 제품을 생산할 수 있다.
GenericPrinterTest - 프린트 출력
package generics;
public class GenericPrinterTest {
public static void main(String[] args) {
GenericPrinter<Powder> powderPrinter = new GenericPrinter<Powder>();
powderPrinter.setMaterial(new Powder());
Powder powder = powderPrinter.getMaterial();
System.out.println(powderPrinter);
GenericPrinter<Plastic> plastiPrinter = new GenericPrinter<Plastic>();
plastiPrinter.setMaterial(new Plastic());
Plastic plastic = plastiPrinter.getMaterial();
System.out.println(plastiPrinter);
}
}
- 각각 플라스틱과, 파우더 재료를 넣어 제품을 생산하였다.
제네릭의 T 자료형 제한.
만약 재료를 넣는데 엉뚱한 재료를 넣는다면, 프린터기가 망가질 수 있다. 그렇기 때문에 제네릭 자료형의 제한을 할 수 있다.
Material 클래스
package generics;
public abstract class Material {
public abstract void doPrinting();
}
기존재료들은 Material 클래스를 상속받음.
package generics;
public class Powder extends Material {
public void doPrinting() {
System.out.println("Poder 재료로 출력합니다.");
}
@Override
public String toString() {
return "재료는 Powder 입니다";
}
}
package generics;
public class Plastic extends Material {
public void doPrinting() {
System.out.println("Plastic 재료로 출력합니다.");
}
@Override
public String toString() {
return "재료는 Plastic 입니다";
}
}
제네릭 클래스에도 Material를 상속받는다.
package generics;
public class GenericPrinter<T extends Material> {
private T material;
public void setMaterial(T material) {
this.material = material;
}
public T getMaterial() {
return material;
}
public String toString() {
return material.toString();
}
public void printing() {
material.doPrinting();
}
}
테스트
- Material 클래스를 상속받지 않은 클래스를 제네릭 자료형으로 넘기면 오류가 발생!
- 이 친구도 상속을 받았다.
- 이제 오류가 안남.
제네릭 클래스에서 상위 클래스 메서드 사용하기.
GenericPrinter 클래스에 메서드 추가.
테스트
package generics;
public class GenericPrinterTest {
public static void main(String[] args) {
GenericPrinter<Powder> powderPrinter = new GenericPrinter<Powder>();
powderPrinter.setMaterial(new Powder());
Powder powder = powderPrinter.getMaterial();
// System.out.println(powderPrinter);
powderPrinter.printing();
GenericPrinter<Plastic> plastiPrinter = new GenericPrinter<Plastic>();
plastiPrinter.setMaterial(new Plastic());
Plastic plastic = plastiPrinter.getMaterial();
// System.out.println(plastiPrinter);
plastiPrinter.printing();
// Material 을 상속하지 않은 클래스
GenericPrinter<Water> water = new GenericPrinter<Water>();
}
}
여러개의 제네릭 자료형 받기.
제네릭 클래스
package generics;
public class Point<T, V> {
T x;
V y;
public Point(T x, V y) {
this.x = x;
this.y = y;
}
public T getX() {
return x;
}
public V getY() {
return y;
}
}
제네릭 메서드 구현
package generics;
public class GenericMethod {
public static <T, V> double makeRectangle(Point<T, V> p1, Point<T, V> p2) {
double left = ((Number)p1.getX()).doubleValue(); // 0
double right = ((Number)p2.getX()).doubleValue(); // 10
double top = ((Number)p1.getY()).doubleValue(); // 0.0
double bottom = ((Number)p2.getY()).doubleValue(); // 10.0
double width = right - left; // 10 - 0 = 10
double height = bottom - top; // 10.0 - 0.0 = 10.0
return width * height; // 10 * 10.0 = 100.0
}
public static void main(String[] args) {
Point<Integer, Double> p1 = new Point<>(0, 0.0);
Point<Integer, Double> p2 = new Point<>(10, 10.0);
double rect = GenericMethod.<Integer, Double>makeRectangle(p1, p2);
System.out.println("두 점으로 만들어진 사각형의 넓이는 " + rect + "입니다.");
}
}
- GenericMethod는 제네릭 클래스가 아니더라도 내부에 있는 제네릭 메서드를 구현할 수 있다.
- 제네릭 메서드는 static 으로 선언하였다.
- 제네릭 메서드의 매개변수 들어오는 자료형은 해당 메서드 안에서만 유효범위를 갖는다.
출처: do it 자바프로그래밍
'프로그래밍 > Java' 카테고리의 다른 글
Set (0) | 2019.12.17 |
---|---|
컬렉션 프레임워크 (0) | 2019.12.14 |
Class 클래스 (0) | 2019.12.12 |
wrapper클래스 (0) | 2019.12.11 |
String 클래스 (0) | 2019.12.10 |