각진 세상에 둥근 춤을 추자

[Java] 제네릭(Generic) 본문

Java

[Java] 제네릭(Generic)

circle.j 2022. 9. 28. 12:20

 

여러 참조 자료형을 사용할 수 있도록 프로그래밍하는 것을 '제네릭(Generic) 프로그래밍'이라고 한다. 

 

제네릭에서는 여러 참조 자료형을 사용해야 하는 부분에 Object가 아닌 'T'와 같이 하나의 문자로 표현한다.

그리고 객체를 생성할 때, T 자리에 구체적인 자료형을 적는다.

즉, Box 클래스 안에 저장되는 구체적인 자료형 대신, T라는 타입 매개 변수로 표시한 것이다.

이렇게 되면 Box로 생성된 객체는 어떤 타입의 데이터든 저장할 수 있다.

 

 

제네릭 클래스(generic class)는 타입을 변수로 표시한다.

이것을 타입 매개 변수 (type parameter)라고 하는데 타입 매개 변수는 객체 생성 시에 프로그래머가 결정한다.

 


3D 프린터 클래스 예제를 통해 제네릭 프로그래밍을  이해해 본다. 

 

1. 제네릭 클래스 정의하기

 

여러 자료형으로 바꾸어 사용할 material 변수의 자료형을 T라고 작성한다.

이때 T를 자료형 매개변수(type parameter)라고 한다.

클래스 이름을 GenericPrinter<T>라고 정의하고 나중에 클래스를 사용할 때는 T의 위치에 실제 사용할 자료형을 지정한다. 

클래스의 각 메서드에서 해당 자료형이 필요한 부분에는 모두 T 문자를 사용하여 구현한다. 

 

public class GenericPrinter<T> {

	private T material;
    
    public void setMaterial (T material) {
    	this.material = material;
    }
    
    public T get material(){
    	return material;
    }
    
}

 


2. 제네릭 클래스 사용하기

 

파우더를 재료로 사용하는 3D 프린터를 다음과 같이 선언하여 생성한다.

T로 정의한 부분에 Powder를 넣어주고, T형 매개변수가 필요한 메서드에 Powder 클래스를 생성하여 대입한다. 

 

GenericPrinter<Powder> powderPrinter = new GenericPrinter<>();

powderPrinter.setMaterial(new Powder());
Powder powder = powderPrinter.getMaterial();

T 위치에 사용한 Powder형을 '대입된 자료형'이라고 하고, 

Powder를 대입해 만든 GenericPrinter<Powder>를 '제네릭 자료형'이라고 한다. 

 

3D 프린터에 사용할 재료(Powder, Plastic) 클래스를 추가로 정의해 본다.

 

(1) Powder 클래스 정의하기 

package ch12_1;

// Powder 클래스 정의하기
public class Powder {

	public void doPrinting() {
		System.out.println("Powder 재료로 출력합니다.");
	}
	
	public String toString() {
		return "재료는 Powder입니다.";
	}
	
}

 

(2) Plastic 클래스 정의하기

package ch12_1;

//Plastic 클래스 정의하기
public class Plastic {
	public void doPrinting() {
		System.out.println("Plastic 재료로 출력합니다.");
	}
	
	public String toString(){
		return "재료는 Plastic입니다.";
			
	}
}

 

(3) 제네릭 클래스 정의하기 

package ch12_1;

// GenericPrinter 클래스 정의하기
public class GenericPrinter<T> {

	// T 자료형으로 선언한 변수
	private T material;

	public T getMaterial() {
		return material;
	}

	public void setMaterial(T material) {
		this.material = material;
	}
	
	public String toString() {
		return material.toString();
	}
	
}

 

(4) 제네릭 클래스를 사용할 테스트 클래스 정의하기

package ch12_1;

public class GenericPrinterTest {
	public static void main(String[] args) {
		
		// Powder형으로 GenericPrinter 클래스 생성
		GenericPrinter<Powder> powderPrinter = new GenericPrinter<Powder>();
		
		powderPrinter.setMaterial(new Powder());
		Powder powder = powderPrinter.getMaterial();
		System.out.println(powderPrinter);
		
		// Plastic형으로 GenericPrinter 클래스 생성
		GenericPrinter <Plastic> plasticPrinter = new GenericPrinter<Plastic>();
		
		plasticPrinter.setMaterial(new Plastic());
		Plastic plastic = plasticPrinter.getMaterial();
		System.out.println(plasticPrinter);
		
	}
}

 

 


3. 제네릭 메서드 활용하기

 

클래스의 메소드에서 타입 매개 변수를 사용하여 제네릭 메소드를 정의할 수 있다.

이 경우, 타입 매개 변수의 범위가 메소드 내부로 제한된다.

 

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

 

먼저 x, y 두 멤버 변수를 사용하는 Point 클래스를 생성한다.

한 점을 나타내는 Point 클래스의 두 좌표 x, y는 정수일 수도 있고 실수 일수도 있다. 

그래서 T와 V라는 자료형 매개변수를 통해 작성한다. 

 

package ch12_1;

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

 

위 Point 클래스를 활용하여 두 점(p1, p2) 을 생성한다. 

Point<Integer, Double> p1 = new Point<>(0, 0.0);
Point<Integer, Double> p2 = new Point<>(10, 10.0);

 

두 점을 매개변수로 받아 만들어지는 사각형의 넓이를 계산하는 makeRectangle()메서드를 만들어 본다.

두 점이 Integer형으로 만들어 질 수도 있고, Double형으로 만들어 질 수도 있기 때문에 해당 메서드는 제네릭 메서드로 만든다.

 

package ch12_1;

public class GenericMethod {
	
	// 제네릭 메서드 
	public static <T,V> double makeRectangle(Point<T, V> p1, Point<T, V> p2) {
		double x1 = ((Number)p1.getX()).doubleValue();
		double x2 = ((Number)p2.getX()).doubleValue();
		double y1 = ((Number)p1.getY()).doubleValue();
		double y2 = ((Number)p2.getY()).doubleValue();
		
		double width = x2-x1;
		double height = y2-y1;
		
		return width * height;
		
	}
	
	
	public static void main(String[] args) {
		
		// p1, p2 생성
		Point<Integer, Double> p1 = new Point<Integer, Double>(0, 0.0);
		Point<Integer, Double> p2 = new Point<Integer, Double>(10, 10.0);
		
		// 사각형 넓이 구하는 식 생성
		double rect = GenericMethod.<Integer, Double>makeRectangle(p1,p2);
		System.out.println("두 점으로 만들어진 사각형의 넓이는 " +rect +"입니다.");
	}
	
}

 

'Java' 카테고리의 다른 글

[Java] List 인터페이스  (0) 2022.09.29
[Java] 컬렉션 프레임워크  (0) 2022.09.28
[Java] Class 클래스  (0) 2022.09.28
[Java] 근의 공식  (0) 2022.09.26
[Java] Wrapper 클래스  (0) 2022.09.26