[Java] 제네릭(generic) 프로그래밍

rara_kim·2022년 7월 26일
0

Java

목록 보기
18/39
post-thumbnail

제네릭

제네릭(generic)이란 "타입을 일반화"것을 의미하며, 클래스 내부에서 정하는 것이 아닌 사용자 호출에 의해 타입이 지정되는 것을 의미한다.
클래스에서 사용하는 변수의 자료형이 여러개 일 수 있고, 그 기능(메서드)은 동일한 경우 클래스의 자료형을 특정하지 않고 후에 해당 클래스를 사용할 때 지정할 수 있도록 선언한다.

제네릭 타입

제네릭 타입은 타입(Type)을 파라미터로 가지는 클래스와 인터페이스를 말한다.
(그 외에 별도로 메소드에 한정한 제네릭도 사용 가능하다.)

즉, 제네릭 타입은 파라미터가 아닌 클래스 및 인터페이스 인데, 제네릭 타입은 클래스 및 인터페이스 이름 뒤에 <>를 쓰고 타입 파라미터(T)를 명시해야 한다.

public class 클래스명<T> {...}
public interface 인터페이스명<T>{...}

public <자료형 매개변수> 반환타입 메서드명(자료형 매개변수...) {}     //제네릭 메소드

💡타입 파라미터
타입 파라미터는 제네릭 클래스/인터페이스에 사용되며 타입이 정해지지 않은 파라미터이다.
대부분 참조 타입의 경우 T, 요소의 경우 E(Element), 키를 나타낼 경우 K(Key), 값을 나타낼 경우 V(Value)등을 사용한다. (무조건 T일 필요는 없다.)

분류타입 인자
Type<T>
Element<E>
Key<K>
Value<V>
Number<N>

제네릭 타입을 사용하는 이유

  • 재사용성 증가
  • 컴파일 시 타입 에러 발견 가능(런타임 단계에서의 문제 발생 방지)
  • 컴파일러가 타입 변환 수행(불필요한 형변환 불필요)

제네릭 클래스 사용

public class ClassName<K, V> {
	private K first;
    private V second;
    
    void set(K first, V second) {
    	this.first = first;
    	this.second = second;
    }
    
    K getFirst() {
    	return first;
    }
    
    V getSecont() {
    	return second;
    }
}


public class Main{
	public static void main(String[] args) {
    	ClassName<String, Integer> g = new ClassName<String, Integer>();
       	g.set("A", 10);
        
        System.out.println("1st Data: " + g.getFirst());
        System.out.println("2nd Data: " + g.getSecond());
    }
}

제네릭 메소드 사용

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<>(10, 1.0);

		double size = GenericMethod.<Integer, Double>makeRectangle(p1, p2);
		System.out.println(size);	
	}
}

<T extends 클래스> 사용

  • T자료형의 범위를 제한 할 수 있다.
  • 상위 클래스에서 선언하거나 정의하는 메소드를 활용할 수 있다.
  • 상속을 받지 않는 경우 T는 Object로 변환되어 Object클래스가 기본으로 제공하는 메소드만 사용가능하다.
public class GenericPrinter<T extends Material> {  //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 Main{
	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);
    }
}

profile
느리더라도 꾸준하게

0개의 댓글