Generic programming
하나의 참조 자료형이 아닌 여러 참조 자료형을 사용할 수 있도록 프로그래밍하는 기법
public class ThreeDPrinter{
private Powder material;
public void setMaterial(Powder material){
this.material=material;
}
public Powder getMaterial(){
return material;
}
}
public class ThreeDPrinter{
privatte Plastic material;
public void setMaterial(Plastic material){
this.material=material;
}
public Plastic getMaterial(){
return material;
}
}
abvoe two codes can be unity by ‘Object class'
public class ThreeDPrinter{
private Object material;
public void setMaterial(Object material){
this.material=material;
}
public Object getMaterial(){
return material;
}
}
ThreeDPrinter printer=new ThreeDPrinter();
Powder p1=new Powder();
printer.setMaterial(p1);
Powder p2=(Powder)printer.getMaterial();
위와 같이 프로그래밍을 하면 형변환을 매번 해줘야 하는 번거로움이 있다.
이를 해결하기 위해서 제네릭 클래스를 사용한다.
Generic class
public class GenericPrinter<T>{
prinvate T material;
public void setMaterial(T material){
this.material=material;
}
public T getMaterial(){
return material;
}
}
자료형 매개변수 T는 제네릭 클래스의 인스턴스가 생성되는 순간 정해진다.
따라서 T의 자료형이 결정되는 시점보다 빠르기 때문에
static 변수의 자료형이나 static 메서드 내부 변수의 자료형으로 T를 사용할 수 없다.
< >
ArrayList<String> list=new ArrayList<String>();
ArrayList<String> list=new ArrayList<>();
after java7 can omit diamond operator(< >)
var list=new ArrayList<String>();
after java10 지역 변수에 한해서 자료형을 추론할 수 있다.
E ; element
K ; key
V ; value
T ; type
Using Generic class
GenericPrinter<Powder> powderPrinter=new GenericPrinter<Powder>();
powderPrinter.setMaterial(new Powder());
Powder powder=powderPrinter.getMaterial();
Material.java
package generics;
public abstract class Material{
public abstract void doPrinting();
}
Powder.java
package generics;
public class Powder extends Material{
public void doPrinting(){
System.out.println("Powder 재료로 출력합니다.");
}
public String toString(){
return "재료는 Powder 입니다.";
}
}
Plastic.java
package generics;
public class Plastic extends Material{
public void doPrinting(){
System.out.println("Plastic 재료로 출력합니다.");
}
public String toString(){
return "재료는 Plasic 입니다.";
}
}
GenericPrinter.java
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();
}
}
GenericPrinterTest.java
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> plasticPrinter=new GenericPrinter<Plastic>();
plasticPrinter.setMaterial(new Plastic());
Plastic plastic=plasticPrinter.getMaterial();
System.out.println(plasticPrinter);
}
}
재료는 Powder 입니다.
재료는 Plasic 입니다.
<T extends class>
제네릭 클래스에서 T 자료형에 사용할 자료형에 제한을 둘 때 사용한다.
T의 범위를 class를 상속받은 class로 제한 한다.
extends abstract class와 implements interface 모두 extends 예약어로 제한할 수 있다.
Generic method
public <자료형 매개변수> 반환형 메서드이름 (자료형 매개변수 …){}
메서드 선언부나 메서드의 매개변수로 자료형 매개변수 T를 사용한 메서드를 ‘Generic method’라고 한다.
제네릭 메서드는 일반 메서드 뿐 아니라 static 메서드에서도 활용할 수 있다.
단, static 메서드에서 선언덴 type T는 메서드 내부에서만 유효하게 사용할 수 있다.
Point.java
package generics;
public class Point<T,V>{
T x;
V y;
Point(T x, V y){
this.x=x;
this.y=y;
}
public T getX(){
return x;
}
public V getY(){
return y;
}
}
GenericMethod.java
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();
double right=((Number)p2.getX()).doubleValue();
double top=((Number)p1.getY()).doubleValue();
double bottom=((Number)p2.getY()).doubleValue();
double width=right-left;
double height=bottom-top;
return width*height;
}
public static void main(String[] args){
Point<Integer, Double> p1=new Point<Interger, Double>(0,0.0);
Point<Integer, Double> p2=new Point<>(10,10.0);
double rect=GenericMethod.<Integer,Double>makeRectangle(p1,p2);
System.out.println("두점으로 만들어진 사각형의 넓이는 "+rect+" 입니다.");
}
}
두점으로 만들어진 사각형의 넓이는 100.0 입니다.