728x90
Generic 

 

데이터 형식에 의존하지 않고 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법으로,

클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정된다.

 

ex)

객체<타입> 객체이름 = new 객체<타입>();

 

<주로 사용되는 타입>

타입 설명
<T> Type (데이터 타입)
<E> Element (요소)
<K> Key (키)
<V> Value (값)
<N> Number (숫자)

※ 타입이 설명과 반드시 일치해야 할 필요는 없지만 일반적으로 사용되는 선언이 보기에 편하다.


Generic의 장점

 

  1. 제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있다.
    =안정성이 높아진다.

  2. 클래스 외부에서 타입을 지정 해주기 때문에 따로 타입을 체크하고 변환해줄 필요가 없다.
    =관리하기가 편하다.

  3. 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다.

Generic 사용방법

1. 클래스 및 인터페이스 선언

타입 파라미터로 명시할 수 있는 것은 참조타입(R타입)만 사용할 수 있다.

(int, double, char... 등의 기본타입(P타입)은 사용할 수 없다.)

때문에 기본타입의 경우 Integer, Double, Character... 등의 랩퍼클래스로 사용된다.

public class ClassName <T, K> { ... }
//기본적으로 제네릭타입의 클래스나 인터페이스의 경우 위와같이 선언한다.
//선언된 <T, K>의 범위는 { ... } 까지이다.

public class Main {
	public static void main(String[] args) {
    	ClassName<String, Integer> a = new ClassName<String, Integer>();
        //a객체의 ClassName의 T는 String, K는 Integer가 된다.
    }
}

2. 제네릭 클래스

외부 클래스에서 제네릭 클래스를 생성할 때 괄호< > 안의 타입을 파라미터로 보내 제네릭 타입을 지정해 준다.

class ClassName<E> {	 		//제네릭 클래스
	
	private E element;		//제네릭 타입 변수 element
	
	void set(E element) {		//제네릭 파라미터 메소드
		this.element = element;
	}
	
	E get() {			//제네릭 타입 반환 메소드
		return element;
	}
}
 
public class Generic {
	public static void main(String[] args) {
		
		ClassName<String> a = new ClassName<String>();
		//a객체의 ClassName의 E제네릭타입은 String으로 모두 변환된다
        
		ClassName<Integer> b = new ClassName<Integer>();
		//b객체의 ClassName의 E제네릭타입은 Integer로 모두 변환된다
        
		a.set("10");
		b.set(10);
	
		System.out.println("a data : " + a.get());
		System.out.println("a E Type : " + a.get().getClass().getName());	
		//반환된 변수의 타입 출력 
            
		System.out.println();
        
		System.out.println("b data : " + b.get());
		System.out.println("b E Type : " + b.get().getClass().getName());
		//반환된 변수의 타입 출력 		
	}
}
  • getClass( ).getName( ) : 현재 실행중인 클래스의 클래스명 출력

[실행결과]

a data : 10
a E Type : java.lang.String

b data : 10
b E Type : java.lang.Integer

3. 제네릭 메소드

매개변수 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드

정적 메소드로 선언할 때 사용된다.

 

클래스에서와는 다르게 반환타입 이전에 제네릭 타입< >을 선언한다.

타입 파라미터를 리턴 타입과 매개변수에 사용한다.

 

 

※ 클래스는 인스턴스 앞에 있는 데이터형을 보고 제네릭 타입을 결정하고,

     메소드는 뒤에 있는 매개값을 보고 제네릭 타입을 결정한다.

 

ex)

제네릭 메소드 선언

public <T> T genericMethod(T t) {
		...
}
  • 접근제어자 <제네릭타입> 리턴타입 메소드명( 제네릭타입 파라미터 ) {
    }

제네릭 메소드 호출

T<Integer> T = genericMethod(100);		
//매개값이 100이기 때문에 타입 파라미터를 Integer로 추정

T<Integer> T = <Integer> genericMethod(100);	
//제네릭타입을 Integer로 지정했기 때문에 타입 파라미터를 Integer로 지정
  • 리턴타입 변수 = 메소드명(매개값);
  • 리턴타입 변수 = <구체적타입> 메소드명(매개값);

제네릭 클래스에서 사용한 예제에 제네릭 메소드 추가

  •  

[실행결과]

a data : 10
a E Type : java.lang.String

b data : 10
b E Type : java.lang.Integer

<T> returnType : java.lang.Integer
<T> returnType : java.lang.String
<T> returnType : ClassName


와일드 카드 <?>

 

  • <? extends a> : 상한 제한 (Upper bound)
    a와 a의 자식 타입만 사용 가능
    특정 타입만 제한하고 싶을 경우 사용한다.

  • <? super a> : 하한 제한 (Lower bound)
    a와 a의 부모 타입만 사용 가능
    해당 객체가 업캐스팅(Up Casting)이 될 필요가 있을 때 사용한다.

  • <?> : 제한 없음 (Un bound)
    모든 타입의 객체 사용 가능
    데이터가 아닌 기능의 사용에만 관심이 있는 경우 (어떤 타입으로 리턴받아도 상관 없을 경우) 사용한다.

※ <b extends a>와 <? extends a>는 비슷한 구조지만 차이점이 있다.

  • <b extends a>
    a와 이를 상속하는 Integer, Short, Double... 등의 타입이 지정될 수 있으며, 객체 혹은 매소드를 호출할 경우
    b는 지정된 타입으로 변환이 된다.

  • <? extends a>
    a와 이를 상속하는 Integer, Short, Double... 등의 타입이 지정될 수 있지만, 객체 혹은 메소드를 호출할 경우
    지정되는 타입이 없어 타입 참조를 할 수 없다.

 

다음 그림과 같이 서로 다른 클래스들이 상속관계를 갖고 있다고 가정했을 경우

 

extends

<T extends B>	// B와 C타입만 올 수 있음
<T extends E>	// E타입만 올 수 있음
<T extends A>	// A, B, C, D, E 타입이 올 수 있음
 
<? extends B>	// B와 C타입만 올 수 있음
<? extends E>	// E타입만 올 수 있음
<? extends A>	// A, B, C, D, E 타입이 올 수 있음
  • 뒤에 오는 타입이 최상위 타입으로 한계가 정해진다.

super

<K super B>	// B와 A타입만 올 수 있음
<K super E>	// E, D, A타입만 올 수 있음
<K super A>	// A타입만 올 수 있음
 
<? super B>	// B와 A타입만 올 수 있음
<? super E>	// E, D, A타입만 올 수 있음
<? super A>	// A타입만 올 수 있음
  • 뒤에 오는 타입이 최하위 타입으로 한계가 정해진다

<?>

<?> //A, B, C, D, E 타입이 올 수 있음
  • <? extends Object>와 동일하다

'JAVA' 카테고리의 다른 글

ArrayList  (0) 2021.07.22
컬렉션 (Collection)  (0) 2021.07.20
랩퍼 (Wrapper)  (0) 2021.07.19
메모리 (Memory)  (0) 2021.07.19
Enum  (0) 2021.07.19

+ Recent posts