제네릭
제네릭은 클래스나 메서드에서 사용할 데이터 타입을 컴파일 과정에서 미리 지정하는 방법입니다.
컴파일 시에 미리 타입 검사를 수행함을 통해 러닝 과정에서 오류를 사전에 방지할 수 있습니다.
보통 대표적인 제네릭 사용으로 List<String> list = new ArrayList<>(); 등을 알고 있을탠데
여기선 <Object>, <T>, <?> 등에 대해 알아보고자 합니다.
< Object > : raw type
Element를 받을 때 Object에 포함되는 모든 클래스를 받을 수 있습니다.
가장 유연성이 높지만 컴파일 과정에서 타입 체크가 불가능하여 러닝중 오류가 발생할 확률이 높기 때문에
구현 과정에서 신중할 필요가 있고, 가급적 사용하지 않는 것이 좋습니다.
< T > : 타입 변수
<String>이나 <Integer> 등으로 지정할 경우 해당 블럭 내에선 지정한 Type 밖에 쓸 수 없지만
<T> 와 같은 타입 변수를 사용하여 클래스나 메서드에서 사용될 타입을 외부에서 지정한 타입으로 사용할 수 있습니다.
가장 많이 접하는 클래스로 Collection Framework 가 있는데
List와 Map을 디컴파일 해보면 List<E> / Map<K, V> 로 구현되어 있는 것을 볼 수 있습니다.
아래는 Class<T> 의 사용예시 입니다.
class GenericTest<T> {
private T element; // 제네릭 타입
void setElement(T element) {
this.element = element;
}
T getElement() {
return element;
}
}
class Main {
public static void main(String[] args) {
GenericTest<String> stringFunc = new GenericTest<>();
GenericTest<Integer> integerFunc = new GenericTest<>();
stringFunc.setElement("10");
integerFunc.setElement(10);
System.out.println("stringFunc.value : " + stringFunc.getElement());
System.out.println("stringFunc.type : " + stringFunc.getElement().getClass());
System.out.println("integerFunc.value : " + integerFunc.getElement());
System.out.println("integerFunc.type : " + integerFunc.getElement().getClass());
}
}
결과
stringFunc.value : 10
stringFunc.type : class java.lang.String
integerFunc.value : 10
integerFunc.type : class java.lang.Integer
타입 변수 표기의 대표적인 것들은 아래와 같습니다.
<T> | Type |
<E> | Element |
<K> | Key |
<V> | Value |
물론 위에 제한된 것이 아닌 개발자가 원하는 대로 지정하여 사용하는 것도 가능합니다.
또한 extends 를 사용하면 특정 클래스나 인터페이스를 상속받은 타입으로만 제한하는 것도 가능합니다.
< ? > : 와일드 카드
<Object> 와 같이 타입 변수에 모든 타입을 넣을 수 있습니다.
하지만 데이터의 가공이 불가능하여 put(), add() 등을 사용할 수 없다는 점에 차이점이 있습니다.
보통 데이터를 사용하기 보단 기능을 활용할 때 주로 사용합니다.
import java.util.*;
class LandAnimal { public void crying() { System.out.println("육지동물"); } }
class Cat extends LandAnimal { public void crying() { System.out.println("냐옹냐옹"); } }
class Dog extends LandAnimal { public void crying() { System.out.println("멍멍"); } }
class Sparrow { public void crying() { System.out.println("짹짹"); } }
class AnimalList<T> {
ArrayList<T> al = new ArrayList<T>();
public static void cryingAnimalList(AnimalList<? extends LandAnimal> al) {
LandAnimal la = al.get(0);
la.crying();
}
void add(T animal) { al.add(animal); }
T get(int index) { return al.get(index); }
boolean remove(T animal) { return al.remove(animal); }
int size() { return al.size(); }
}
public class Generic03 {
public static void main(String[] args) {
AnimalList<Cat> catList = new AnimalList<Cat>();
catList.add(new Cat());
AnimalList<Dog> dogList = new AnimalList<Dog>();
dogList.add(new Dog());
AnimalList.cryingAnimalList(catList);
AnimalList.cryingAnimalList(dogList);
}
}
결과
냐옹냐옹
멍멍
'Back-End > Java & Spring' 카테고리의 다른 글
[JAVA-Spring] Lombok 동작 원리 (0) | 2022.08.17 |
---|---|
[JAVA] 특정 클래스를 상속받은 모든 클래스를 찾는 방법 (0) | 2022.08.17 |
[JAVA-Spring] 가변적인 Parameter 처리 (0) | 2022.08.02 |
[JAVA] Log4j (0) | 2022.08.02 |
[JAVA] JNDI( Java Naming and Directory Interface ) (0) | 2022.08.02 |