본문 바로가기
Languages/Java

[Java] 제네릭 (2) 멀티 타입 파라미터, 제네릭 메소드

by 이래지 2021. 12. 28.
728x90

멀티 타입 파라미터(class<K,V,...>, interface<K,V,...>)


제네릭 타입은 두 개 이상의 멀티 타입 파라미터를 사용할 수 있다.

각 타입 파라미터를 콤마로 구분한다.

 

다음 예제문은 

Product<T, M> 제네릭 타입을 정의하고 ProductExample 클래스에서 Product<Tv, String> 객체와 Product<Car, String> 객체를 생성한다. 그리고 Getter와 Setter를 호출하는 방법을 보여준다.

 

제네릭 클래스

// 제네릭 클래스 
public class Product<T, M> {
	private T kind;
    private M model;
    
    public T getKind() { return this.kind; }
    public M getModel() { return this.model; }
    
    public void setKind(T kind) { this.kind = kind; }
    public void setModel(M model) { this.model = model; }
}

제네릭 객체 생성

public class ProductExample {
	public static void main(String[] args) {
    	Product<Tv, String> product1 = new Product<Tv, String>();
        product1.setKind(new Tv());
        product1.setModel("스마트Tv");
        Tv tv = product1.getKind();
        String tvModel = product1.getModel();
        
        Product<Car, String> product2 = new Product<Car, String>();
        product1.setKind(new Car());
        product2.setModel("디젤");
        Car car = product2.getKind();
        String carModel = product2.getModel();
    }
}

제네릭 타입 변수 선언과 객체 생성을 동시에 할 때 타입 파라미터 자리에 구체적인 타입을 지정하는 코드가 중복해서 나와 다소 복잡해질 수 있다. 

자바 7부터 제네릭 타입 파라미터의 중복 기술을 줄이기 위해 다이아몬드 연산자 < > 를 제공한다.

자바 컴파일러는 타입 파라미터 부분에 <> 연산자를 사용하면 타입 파라미터를 유추해서 자동으로 설정해준다.

ex) 자바 6 이전

Product<Tv, String> product = new Product<Tv, String>();

ex) 자바 7 부터

Product<Tv, String> product = new Product<>();

자바 7 부터는 다이아몬드 연산자로 이렇게 간단하게 작성이 가능

 

제네릭 메소드 (<T, R> R method(T t))


제네릭 메소드는 매개 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드를 말한다.

제네릭 메소드를 선언하는 방법은 리턴 타입 앞에 <> 기호를 추가하고 타입 파라미터를 기술한 다음, 리턴 타입과 매개 타입으로 타입 파라미터를 사용한다.

 

사용 방법

public <타입파라미터,...> 리턴타입 메소드명(매개변수,...) {...}

 

다음 예시 boxing() 제네릭 메소드는 <> 기호 안에 타입 파라미터 T를 기술한 뒤, 매개 변수 타입으로 T를 사용했고, 리턴 타입으로 제네릭 타입 Box<T>를 사용했다.

public <T> Box<T> boxing(T t) {...}

 

제네릭 메소드는 두 가지 방식으로 호출할 수 있다.

1. 코드에서 타입 파라미터의 구체적인 타입을 명시적으로 지정하기

2. 컴파일러가 매개값의 타입을 보고 구체적인 타입을 추정하도록 하기

리턴타입 변수 = <구체적타입> 메소드명(매개값); // 명시적으로 구체적 타입을 지정
리턴타입 변수 = 메소드명(매개값); 	// 매개값을 보고 구체적 타입을 추정

 

boxing() 메소드를 호출하는 코드

Box<Integer> box = <Integer>boxing(100); // 타입 파라미터를 명시적으로 Integer로 지정
Box<Integer> box = boxing(100);	// 타입 파라미터를 Integer로 추정

 

 

제네릭 메소드를 생성하고 호출하는 예제

1번 예제

  • 제네릭 메소드 (Util 클래스에 정적 제네릭 메소드로 boxing()을 정의)
public class Util {
	public static <T> Box<T> boxing(T t) {
    	Box<T> box = new Box<T>();
        box.set(t);
        return box;
    }
}
  • 제네릭 메소드 호출 (BoxingMethodExample 클래스에서 호출) 
public class BoxingMethodExample {
	public static void main(String[] args) {
    	Box<Integer> box1 = Util.<Integer>boxing(100);
        int intValue = box1.get();
        
        Box<String> box2 = Util.boxing("홍길동");
        String strValue = box2.get();
    }
}

 

 

 

2번 예제

  • 정적 제네릭 메소드로 compare()를 정의. 타입 파라미터는 K와 V로 선언되었다. 제네릭 타입 Pair가 K와 V를 가지고 있기 때문이다.
// 제네릭 메소드
// compare() 메소드는 두 개의 Pair를 매개값으로 받아 K와 V가 동일한지 검사하고 boolean값을 리턴한다.
public class Util {
	public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
    	boolean keyCompare = p1.getKey().equals(p2.getKey());
        boolean valueCompare = p1.getValue().equals(p2.getValue());
        return keyCompare && valueCompare();
    }
}
  • 제네릭 타입
public class Pair<K, V> {
	private K key;
    private V value;
    
    public Pair(K key, V value) {
    	this.key = key;
        this.value = value;
    }
    
    public void setKey(K key) { this.key = key; }
    public void setValue(V value) {this.value = value; }
    public K getKey() { return key; }
    public V getValue() { return value; }
}
  • 제네릭 메소드 호출
public class CompareMethodExample {
	public static void main(String[] args) {
    	Pair<Integer, String> p1 = new Pair<Integer, String>(1, "사과");
        Pair<Integer, String> p2 = new Pair<Integer, String>(1, "사과");
        boolean result1 = Util.<Integer, Sring>compare(p1, p2); // 구체적인 타입을 명시적으로 지정
        if (result1) {
        	System.out.println("논리적으로 동등한 객체입니다.");
        } else {
        	System.out.println("논리으로 동등하지 않는 객체입니다.");
        }
        
        Pair<String, String> p3 = new Pair<String, String>("user1", "홍길동");
        Pair<String, String> p4 = new Pair<String, String>("user2", "홍길동");
        boolean result2 = Util.compare(p3, p4); // 구체적인 타입을 추정
        if (result2) {
        	System.out.println("논리적으로 동등한 객체입니다.");
        } else {
        	System.out.println("논리적으로 동등하지 않는 객체입니다.");
        }
    }
}

실행 결과

논리적으로 동등한 객체입니다.
논리적으로 동등하지 않는 객체입니다.

댓글