[JAVA] 제네릭 프로그래밍

WOOK JONG KIM·2022년 9월 14일
0

패캠_java&Spring

목록 보기
15/103
post-thumbnail

제네릭 프로그래밍이란?

  • 클래스에서 사용하는 변수의 자료형이 여러개 일수 있고, 그 기능(메서드)은 동일한 경우 클래스의 자료형을 특정하지 않고 추후 해당 클래스를 사용할 때 지정 할 수 있도록 선언
  • 실제 사용되는 자료형의 변환은 컴파일러에 의해 검증되므로 안정적인 프로그래밍 방식
  • 컬렉션 프레임워크에서 많이 사용되고 있음

제네릭 타입을 사용하지 않는 경우의 예

public class ThreeDPrinter1{
	private Powder material;
	
	public void setMaterial(Powder material) {
		this.material = material;
	}
	
	public Powder getMaterial() {
		return material;
	}
}
public class ThreeDPrinter2{
	private Plastic material;
	
	public void setMaterial(Plastic material) {
		this.material = material;
	}
	
	public Plastic getMaterial() {
		return material;
	}

}

만드는 방식은 같으나 재료가 다른경우 각각 클래스를 만들어야 될 경우 생김

public class ThreeDPrinter{

	private Object material;
	
	public void setMaterial(Object material) {
		this.material = material;
	}
	
	public Object getMaterial() {
		return material;
	}
}
ThreeDPrinter printer = new ThreeDPrinter();

Powder powder = new Powder();
printer.setMaterial(powder);

Powder p = (Powder)printer.getMaterial();

여러 타입을 대체하기 위해 Object 사용시 나중에 클래스의 형 변환을 해주어야 함

제네릭 프로그래밍 활용 예시

// 나중에 쓸때 <T>에 실제로 사용할 자료형 입력해주면 됨!
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();
	}
}
public class GeneriPrinterTest {

	public static void main(String[] args) {
		//  <> 안에 자료형 생략 시 Object형이라고 추론
        //  위 경우 사용시 형변환이 필요!
		GenericPrinter<Powder> powderPrinter = new GenericPrinter<Powder>(); 
		powderPrinter.setMaterial(new Powder());
		System.out.println(powderPrinter);
		
		GenericPrinter<Plastic> plasticPrinter = new GenericPrinter<Plastic>();
		plasticPrinter.setMaterial(new Plastic());
		System.out.println(plasticPrinter);
		
	}

}

<T extends 클래스> 사용하기

  • T 자료형의 범위를 제한 할 수 있음
  • 상위 클래스에서 선언하거나 정의하는 메서드를 활용할 수 있음
  • 상속을 받지 않는 경우 T는 Object로 변환되어 Object 클래스가 기본으로 제공하는 메서드만 사용가능

  • GenericPrinter 에 material 변수의 자료형을 상속받아 구현

  • T에 무작위 클래스가 들어갈 수 없게 Material 클래스를 상속받은 클래스로 한정

public abstract class Material {
	// 공통으로 사용할 메서드 구현
	public abstract void doPrinting();
}
public class Powder extends Material{
		
	public void doPrinting() {
		System.out.println("Powder 재료로 출력합니다");
	}
	
	public String toString() {
		return "재료는 Powder 입니다";
	}
}
public class Plastic extends Material{

	public void doPrinting() {
		System.out.println("Plastic 재료로 출력합니다");
	}
	
	public String toString() {
		return "재료는 Plastic 입니다";
	}
}
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();
	}
}
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);
		
        // 자료형 추론 경우
		GenericPrinter powderPrinter2 = new GenericPrinter();
		powderPrinter2.setMaterial(new Powder());
		Powder powder = (Powder)powderPrinter.getMaterial();
		System.out.println(powderPrinter);
	
		// Water라는 클래스는 material 상속 X -> 자료형으로 사용 X
        //GenericPrinter<Water> printer = new GenericPrinter<Water>();	
	}
}

제네릭 메서드

public <자료형 매개 변수> 반환형 메서드 이름(자료형 매개변수.....) { }

제네릭 메서드의 활용 예

  • 두 점(top, bottom)을 기준으로 사각형을 만들 때 사각형의 너비를 구하는 메서드를 만들어 보자
  • 두 점은 정수인 경우도 있고, 실수인 경우도 있으므로 제네릭 타입을 사용하여 구현한다.
package ch07;

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;
	}

}
package ch07;

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<Integer, Double>(0, 0.0);
		Point<Integer, Double> p2 = new Point<Integer, Double>(10, 10.0);
		
		double size = GenericMethod.<Integer, Double>makeRectangle(p1,p2);
		System.out.println(size);
	}

}
profile
Journey for Backend Developer

0개의 댓글