Generic이란?
- 클래스나 메소드에서 사용할 데이터 타입을 클래스 정의시에 결정하는 것이 아니라 인스턴스를 생성할 때나 메소드를 호출 할 때 결정하는 기법이다.
- 클래스나 메소드 사용시 타입을 지정할 수 있도록 하는 일반(Generic)화된 타입이라는 의미이다.
- 제너릭은 사용 타입을 지정하기 때문에 컴파일시 타입체크를 해주는 기능(Type Safety)를 통해 런타임시 에러를 사전에 방지할 수 있다.
- JDK1.7부터 클래스를 인스턴스화 할 때 클래스명<파라미터 타입>()의 '파라미터 타입'을 생략할 수 있다. 즉, new클래스명<>()로 인스턴스화 할 수 있다.
제너릭의 장점
- Complie시 타입 체크를 할 수 있기 때문에 Type Safety가 좋다.
- 형변환이 불필요하다.
- 코드의 중복을 줄일 수 있다.
제너릭 타입(Generic Type)
- 타입을 파라미터로 가지는 클래스(제너릭 클래스)와 인터페이스(제너릭 인터페이스)들을 제너릭 타입이라 한다.(즉, Integer타입, String 타입이 아닌 일반화된 타입이다.
- 타입 파라미터는 일반적으로 대문자 알파벳 한 글자로 보통 표현한다.
- 제너릭 타입은 두 개 이상의 멀티 파라미터를 이용할 수 있다. 이때 각 타입 파라미터는 콤마로 구분한다.
- 타입 파라미터는 static이 붙는 정적 맴버변수나 정적 메소드 그리고 new로 초기화하는 인스턴스 맴버변수에는 사용할 수 없다. => static은 인스턴스화 전에 메모리에 올라가는데 아직 타입이 정해지지 않았기 때문에 메모리를 만들 수 없기 때문이다.
- 단, 제너릭 메소드에는 static을 붙일 수 있다. => 제너릭 메소드는 호출 시에 타입을 지정하므로 가능하다.
제너릭 메소드(Generic Method)
- 클래스에 타입 파라미터를 선언하지 않고 메소드마다 타입 파라미터를 선언해 사용할 수 있다.
- 즉, 제너릭 클래스(제너릭 타입)가 아니어도 해당 클래스안에 제너릭 메소드를 만들 수 있다.
- 반환타입 이전에 <>로 타입 파라미터를 선언하면 제너릭 메소드가 되며 제너릭 타입의 타입파라미터와는 무관하다.
제너릭 메소드 호출
방법1)
클래스명 (혹은 인스턴스변수) . <자료형> 메소드명(데이터) : 타입에 맞는 데이터만 전달할 수 있다.
방법2)
클래스명 (혹은 인스턴스변수) . 메소드명(데이터) : 데이터의 타입을 보고 컴파일러가 타입을 추정한다.
타입 파라미터 제한하기
- 한정된 타입 파라미터(Bounded Type Parameter)
- 타입 파라미터를 구체적인 타입으로 제한
- <T extends 최상위 타입> 키워드는 무조건 extends. 최상위 타입 및 최상위 타입을
상속받은 클래스나 인터페이스로 제한
- <T super 최하위 타입> 최하위 타입 및 최하위 타입의 부모 클래스나 인터페이스로 제한
- 와일드카드 타입
- 와일드 카드는 메소드의 매개변수, 필드 타입에 사용
- 타입 파라미터를 알수 없는 타입(?)으로 제한
<?>
<? extends 최상위 타입>
<? super 최하위 타입>의 형태의 3가지
- 와일드 카드는 매개변수, 필드의 타입을 나타내는 등 다양하게 사용된다
- List<Integer>, List<Double>, List<Number>에 만 적용되는 메소드를 작성하고 싶다면
Integer, Double 클래스는 모두 Number 클래스를 상속받기 때문에 ?를 사용하여 아래와 같이 작성
public static void wiildCard(List<? extends Number> list) { ... }
<?>는 모든 타입 가능.
한정된 타입 파라미터에서 T는 특정 타입으로 지정이 되지만 ?는 타입이 지정되지 않는다는 의미이다
List<?>와 List<Object> 차이점
public static void wiildCard(List<?> list) { ... }
public static void wiildCard(List<Object> list) { ... }
List<?>는 모든 타입 출력
List<Object>는 Object 객체의 리스트만 출력.왜냐하면 List<Integer>, List<String>, List<Double>와 같은 클래스들은 Object의 자식이 아니다.
타입파라미터를 받는 MyGeneric이라는 제너릭 클래스를 만들고 안에 맴버변수와 맴버메소드들을 만들어보자.
▲ static맴버는 인스턴스화 전에 메모리에 올라가는데 타입이 정해지지 않았으므로 메모리 생성 불가하다
※ 제너릭 메소드의 타입파라미터는 제너릭 클래스의 타입파라미터와는 아무 관련이 없는 타입파라미터이다. 만약 제너릭 클래스의 타입이 String타입을 인스턴스화 시 정해주면 맴버변수 중 인스턴스형 변수나 맴버메소드 중 인스턴스형 메소드 타입또한 String 타입으로 결정된다. 하지만 제너릭 메소드 즉, 타입파라미터를 가진 메소드는 String 타입으로 정해지지않는다. 제너릭 메소드는 호출 시에 따로 타입을 정해지기 때문이다.
▲제너릭 메소드에는 static 사용이 가능하다 제너릭 메소드는 호출시에 타입이 정해지기 때문이다.
▲ static이 붙지않은 제너릭 메소드 즉, 인스턴스형 제너릭 메소드는 일반적인 인스턴스형 메소드와 동일하게 인스턴스화 후 인스턴스변수로 접근한다.
▲위 메소드는 반환타입 앞에 타입파라미터가 없으므로 제너릭메소드가 아닌 일반 메소드이다. 또한 static메소드이므로 클래스명.메소드명으로 호출시 Number클래스의 상속을 받은 모든 타입을 인자로 받을 수 있으며 그 인자들을 List형식으로 만든다는 것이다. 여기서 ?는 모든을 의미하는 와일드 카드이다.
▲ 위 메소드는 반환타입 앞에 타입파라미터가 있으므로 제너릭 메소드이다. static이 붙어있으므로 클래스명.메소드명으로 호출할 수 있으며 호출시에 인자로 Number클래스의 상속을 받은 모든 타입의 List컬렉션을 받는다.
'Java' 카테고리의 다른 글
[Java]Stream (0) | 2022.04.06 |
---|---|
[Java]람다식(Lambda Expressions) (0) | 2022.04.06 |
[Java]입력과 출력 - File (0) | 2022.03.27 |
[Java]입력과 출력 -part.7(Object InOutStream) (0) | 2022.03.27 |
[Java]입력과 출력 -part.6(Data InOutStream) (0) | 2022.03.27 |