'제너릭 generic'을 잘 알고 썼다고 생각했지만, 모르겠는 것들이 점차 생기면서 내가 잘 알고 있지 못하다는 생각이 들어 차근차근 알아보려고 한다.
- 먼저 제네릭 클래스의 코드를 보자.
class FruitBox{
Object item;
public void store(Object item){
this.item = item;
}
public Object pullOut(){
return item;
}
}
class FruitBox<T>{ //제네릭 클래스를 사용하려는 형태. 타입 T에 <>꼭 써워야 한다.
T item;
public void store(T item){
this.item = item;
}
public T pullOut(){
return item;
}
}
<>는 제네릭 클래스를 사용하려는 형태이고, T는 임의로 정의한 이름이다. M, S, V등 도 있다.
참고로 제네릭은 기본자료형이 불가하다. 그런데 실제로 기본자료형인 데이터를 넣어보면 오류가 나지 않는다. 그 이유는 자동으로 wrapper클래스로 boxing unboxing 되기 때문이다.
제네릭 클래스를 사용했을 때 -> 클래스 선언할 때 타입 파라미터 사용 후, 컴파일 시 타입 파라미터가 구체적인 클래스로 변형된다.
- 제네릭 타입은 두개 이상의 타입 파라미터 사용도 가능하다.
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;
}
pulic void setModel(M model){
this.model = model;
}
]
Product<Tv, String> product = new Product<>();
제너릭 클래스 예제
class DBOx<L, R>{ private L left; private R = right; public void set(L o, R r){ this.left = o; this.right = r; } @Override public String toString(){ return left +"&"+ right; } } public static void main(String[] args){ DBox<String, Integer> box = new DBox<String, Integer>(); box.set("Apple", 25); System.out.print(box);//toString매소드 호출됨 }
- 제네릭은 클래스 전체에서 사용할 수도 있지만 메서드에서도 사용할 수 있다.
매개변수 타입과 리턴 타입으로 타입T 파라미터를 갖는 메서드
public <타입파라미터, ...> 리턴 타입 메서드명(매개변수,...) { ........ }
public <T, V> Box<T> boxing(T t, V v) { ............ }
이런 제네릭 메소드를 호출하는 두 가지 방법이 있다.
//1
리턴타입 변수 = <구체적 타입> 메소드명(매개값);
Box<Integer> box = <Integer> boxing(100);
//2
리턴타입 변수 = 메소드명(매개값);
Box<Integer> box = boxing(100);
1번은 명시적으로 구체적 타입을 지정했고 2번은 매개값을 보고 구체적 타입을 추정한다. ->int형인 100을 보고 Integer로 추정한다.
이처럼 제너릭 메소드는 메소드 뒤에 있는 매개값을 보고 타입을 정하는데, 제너릭 클래스는 인스턴스 앞에 있는 데이터 형을 보고 결정한다. 많이 보던 LinkedList<Integer> list = new LinkedList<>() 에서 =뒤쪽에선 타입을 지정하지 않아도 되는 것을 알 수 있다.
제너릭 메소드 예제 ( 2개 이상의 타입을 가지는 예제도 있음)
class BoxFactory{ public static <T> Box<T> makeBox(T o){ Box<T> = new Box<T>(); box.set(0); return box; } } Box<String> sBox = BoxFactory.<String>makeBox("toys"); Box<Double> dBox = BoxFactory.<Double>makeBox(3.14); //혹은 뒷부분 타입 생략 Box<String> sBox = BoxFactory.makeBox("toys"); Box<Double> dBox = BoxFactory.makeBox(3.14); //두개 이상의 타입을 가지는 매소드 class InstanceTypeShower2{ public <T, U> void showInstType(T inst1, U inst2){ System.out.println(inst1); System.out.println(inst2); } } public static void main(String[] args){ AAA aaa = new AAA(); BBB bbb = new BBB(); InstanceTypeShower2 shower = new InstanceTypeShower2(); shower.<AAA, BBB>showInstType(aaa, bbb); //메소드 호출시는 아래처럼 자료형의 정보를 생략 가능함 shower.showInstType(aaa, bbb); }
- 키워드 extends
extend를 이용하여 매개변수의 자료형을 제한할 수 있다.
class Box<T extends Number>{
private T ob;
public void set(T o){
ob = o;
}
public T get(){
return ob;
}
}
public static void main(String[] args){
Box<Integer> iBox = new Box<>();
iBox.set(30);
Box<Double> dBox = new Box<>();
dBox.set(99.9);
}
Box클래스로 인스턴스 생성시 인자 타입으론 Number클래스 자체나 Number클래스를 상속하는 클래스만이 올 수 있다.
-> Integer 와 Double이 Number를 상속하기 때문에 가능하다. = Number로 제한되어 있으니 Integer와 Double...만이 올 수 있다.
자료형 제한을 마지막으로 제네릭을 마무리한다.
명료하지 못했던 것이 선명해진 것 같다. 다시한번 상기시키며 공부하는 것이 좋다고 느껴진다.
한 블로그를 참고하며 정리했는데 링크는 아래다. 요약 같을 수 있지만,, 나의 말들로 정리를 하니 더욱 이해가 되는 것 같다.
참고 https://blog.naver.com/hke3255/222307555750
자바 제네릭 클래스 (Generics,제네릭 메소드,<>,,타입 인자,JAVA,java,안드로이드 자바,쉬운 예제,
JAVA 제네릭 제네릭 클래스의 이해와 설계 제네릭을 구성하는 다양한 문법적 요소 AppleBox와 Orang...
blog.naver.com
'java' 카테고리의 다른 글
java 중복 없애주는 set, 객체는? (0) | 2022.05.11 |
---|---|
java optional stream() (0) | 2022.02.03 |
[String] replace, replaceAll과 정규식 (0) | 2021.11.17 |
[java] 이중 콜론 연산자 :: (0) | 2021.09.12 |
댓글