2021-06-31 강의록_제네릭메소드

MIN.DI·2021년 7월 1일
0

강의록

목록 보기
25/54

제네릭 메소드

매개타입과 리턴타입으로 타입 파라미터를 갖는 메소드.
리턴타입 앞에 < > 기호 추가하고, 타입 파라미터 기술.
public void set(T t){ ;; }
위의 메소드는 리턴타입 앞에 < > 없으므로 제네릭메소드라고 할 수 없다. 제네릭 클래스를 매개변수로 받는 인스턴스 메소드임.
public <T> void set (T t){ ;; }
이처럼 타입파라미터를 기술해주어야 제네릭메소드가 된다.

제네릭 타입일지라도 제네릭메소드는 있을수도 있고, 없을수도 있다.

public class BoxingMethodEx {

	public static void main(String[] args) {
		//Util.boxing 메소드는 Generic method이기 때문에
		//이 메소드를 호출할 때(=사용할때) 는 타입파라미터에 **구체타입**을 지정해서 호출해야 함.
		Box<Integer> box1 = Util.<Integer>boxing(100);	// 구체타입으로 Integer 지정
		int intValue = box1.get();			// 따라서 box1의 값을 intValue로 받을 수 있음.
		
		//위 코드는 아래와 같음
//		Box box1 = Util.boxing(100);
//		int intValue = (int)box1.get();
		
		///////////////////////
		
		Box<String> box2 = Util.boxing("홍길동"); //<Integer>를 생략하면 타입추론 발생. 타입추론은 Lvalue가 아니라, Rvalue의 매개변수값을 보고 추론함
						 	 // >>하지만 제네릭메소드 사용법 익숙해질때까진 생략하지 말 것
		String strValue = box2.get();
		
	} //main
	
} //end class

Utility class (or Helper class)

보통 현실세계의 객체를 모델링해서 만든 클래스가 아니라,
여러 도움이 될만한 기능을제공하는 목적으로 만든 클래스를 의미함.

  • 구성 메소드는 대부분 정적메소드(static method)로 선언
  • 따라서 필드도 거의 없고, 생성자도 선언하지 않는다.
public class Util {

	//타입 파라미터 T를 가지고 있으므로 제네릭 메소드임.
	public static<T> Box<T> boxing(T t){
		Box<T> box = new Box<T>();
		box.set(t);
		return box;
	} //boxing
	
} //end class

제한된 타입 파라미터

타입 파라미터 <T>에 지정 가능한 구체타입을 제한하고 싶을 때 사용 (마치 Enum 타입처럼!)
extends 관계를 이용해 타입을 제한할 수 있다.
public <T extends 상위타입> 리턴타입 메소드(매개변수, ...) { ;; }
상위타입은 클래스 뿐만 아니라 인터페이스도 가능하지만,
그렇다고 implements 키워드를 사용하지는 않는다.
키워드는 무조건 extends임.

상위타입이거나, 상위타입을 extends하는 타입만 <T>의 구체타입으로 지정할 수 있다.(하위타입에만 있는 필드, 메소드는 사용할 수 없음)

상위타입 확인하려면 OpenTypeHierchy


public class Util {

	//타입파라미터 T에 지정가능한 구체타입의 범위를 제약 >> extends 키워드 사용
	//<T extends 부모타입> : 지정가능한 구체타입은, 부모타입이거나 / 부모타입을 상속받는 자식타입만 가능
	public static <T extends Number> int compare(T t1, T t2){
		double v1 = t1.doubleValue();
		//log.info(t1.getClass().getName());
		
		double v2 = t2.doubleValue();
		
		return Double.compare(v1, v2);
	} //compare
	
} //end class

public class CompareMethodEx {

	public static void main(String[] args) {
		//Generic Type Pair 객체를 2개 생성(사용) >> 이 때 구체타입 지정(K, V)
		//Pair(K, V> : K ==> key 필드의 타입, V ==> value 필드의 타입
		
		//그런데 우리가 배웠다시피 구체타입 지정할때 Lvalue와 Rvalue
		//양쪽에 두 번 지정할 필요 없음 >> Rvalue 구체타입은 생략!
//		Pair<Integer, String> p1 = new Pair<Integer, String>(1, "사과");
//		Pair<Integer, String> p2 = new Pair<Integer, String>(1, "사과");
		Pair<Integer, String> p1 = new Pair<>(1, "사과");		//타입추론
		Pair<Integer, String> p2 = new Pair<>(1, "사과");		//타입추론
		
		
		//Generic Method호출(사용) >> 이 때 구체타입 지정
		boolean result1 = Util.<Integer, String>compare(p1, p2);
		if(result1) {
			log.info("논리적으로 동등한 객체입니다.");
		} else {
			log.info("논리적으로 동등하지 않은 객체입니다.");
		} //if-else
		
		
		//////////////////////////////////////////
		
		Pair<String, String> p3 = new Pair<String, String>("user1", "홍길동");
		Pair<String, String> p4 = new Pair<String, String>("user2", "홍길동");
		
		boolean result2 = Util./*<K,V>*/compare(p1, p2);	//타입추론
			//구체타입을 생략할 때,
			//제네릭 *객체 생성*시에는 <> 다이아몬드 남겨놓고, 제네릭 *메소드 사용*시에는 <> 다이아몬드 기호까지 같이 생략함.
		
		if(result1) {
			log.info("논리적으로 동등한 객체입니다.");
		} else {
			log.info("논리적으로 동등하지 않은 객체입니다.");
		} //if-else
		
	} //main
	
} //end class

구체타입 생략할 때,
제네릭 객체 생성시에는 <> 다이아몬드기호 남겨놓고
제네릭 메소드 사용시에는 <> 다이아몬드 기호까지 같이 생략한다.


compare(value1, value2) 메소드

정렬 알고리즘 구현할 때 많이 사용함!

기본타입의 wrapper타입에서 모두 사용할 수 있음

compare(value1, value2) 메소드는
두 값을 비교해서, 비교 결과를 아래와 같이 반환한다.

  • value1 > value2 ==> +양수 반환 (일반적으로 +1 반환)
  • value1 == value2 ==> 0 반환
  • value1 < value2 ==> -음수 반환 (일반적으로 -1 반환)

자료구조에서 다시 다룰것임!

profile
내가 보려고 쓰는 블로그

0개의 댓글

관련 채용 정보