제네릭 프로그래밍

  • 무엇이든 담을 수 있는 프로그래밍

제네릭 자료형

  • 클래스에 사용하는 변수의 자료형이 다양하고 그 기능은 동일한 경우, 클래스의 자료형을 지정하지 않고 나중에 그 클래스를 사용할 때 지정할 수 있도록 선언하는 것
  • 컬렉션 프레임워크에 많이 사용된다

제네릭 프로그래밍을 사용하지 않으면

  • 다양한 재료를 이용해 3d 프린터를 하는 프린터가 있다
  • 각각 다른 재료로 프린트하는 프린터를 만들어야 한다
    powder로 만드는 경우
public class ThreeDPrinter1 {
    private Powder material;
    public Powder getMaterial() {
        return material;
    }
    public void setMaterial(Powder material) {
        this.material = material;
    }
}

plastic으로 만드는 경우

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

Object 클래스로 만드는 경우

public class ThreeDPrinter3 {
    private Object material;
    public Object getMaterial() {
        return material;
    }
    public void setMaterial(Object material) {
        this.material = material;
    }
}

main에서

Powder p = (Powder) printer3.getMaterial(); 
//반환이 Object 타입으로 되기 때문에 Powder로 형변환을 해야함

제네릭 프로그래밍을 사용하면

프린터의 재료 부분을 지정하지 않는다

public class GenericPrinter<T> {    
    private T material;
    public T getMaterial() {
        return material;
    }
    public void setMaterial(T material) {
        this.material = material;
    }    
    public String toString(){
        return material.toString();
    }
}

사용하는 부분에서

public class GenericPrinterTest {
    public static void main(String[] args) {
        Powder powder = new Powder();
        GenericPrinter<Powder> powderPrinter = new GenericPrinter<>(); 
        //T 를 다 Powder로 바꿔줌

        powderPrinter.setMaterial(powder);
        Powder p = powderPrinter.getMaterial(); // 형변환을 하지 않아도 된다
        System.out.println(powderPrinter.toString());
    }
}

다이아몬드 연산자 <>

  • ArrayList list = new ArrayList<>(); //다이아몬든 연산자 내부에서 자료형은 생략가능 함

  • 제네릭에서 자료형 추론(자바 10부터)
    ArrayList list = new ArrayList() => var list = new ArrayList();

문제점

  • T 자리에 어떤 자료형이든 올 수 있는데, 이 경우 정의되지 않은 자료형이 사용될 수 있다
  • T 자료형의 범위를 제한하는 T extends를 사용한다

T extends 사용하기

  • T에 아무 클래스나 들어갈 수 없게, 상위 클래스를 상속받은 클래스로 한정한다
  • T의 자료형의 범위를 제한할 수 있다
  • 상위 클래스에서 선언하거나 정의한 메서드를 사용할 수 있다
    그렇지 않을 경우 Object로 변환되어 Object 클래스가 기본적으로 제공하는 메서드만 사용 가능

제네릭 메서드

제네릭 메서드란

  • 자료형 매개변수를 메서드의 매개변수나 반환값으로 가지는 메서드
  • 자료형 매개변수가 하나 이상인 경우도 있다
  • 제네릭 클래스가 아니어도 내부에 제네릭 메서드는 구현해서 사용할 수 있다
  • public <자료형 매개변수> 반환형 메서드 이름 (자료형 매개변수 ..) {}

제네릭 메서드 활용 예제

  • 두 점(top, bottom)을 기준으로 사각형을 만들 때 사각형의 너비를 구하는 메서드를 만들어 보자

  • 두 점은 정수인 경우도 있고, 실수인 경우도 있으므로 제네릭 타입을 사용하여 구현한다.

Point.java

  • 점의 좌표 타입을 T, V로 지정한다
public class Point<T, V>{

    T x; //T는 x좌표의 타입
    V y; //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

public class GenericMethod {

    public static <T, V> double makeRectangle(Point<T ,V> p1, Point<T, V> p2){	 
    //p1, p2의 자료형은 Point<T, V>

        double left = ((Number)p1.getX()).doubleValue(); //계산을 위해 모두 double형으로 바꿈
        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); 
        //p1을 선언할 때 Point자료형에 들어갈 타입을 지정
        Point<Integer, Double> p2 = new Point<>(10, 10.0);
		//다음부터는 안 적어도 된다
        double size = GenericMethod.<Integer,Double>makeRectangle(p1,p2);
        System.out.println(size);
    }
}
profile
안녕하세요. Chat JooPT입니다.

0개의 댓글