JAVA

제네릭(Generics)

저스크라이크헤븐 2019. 11. 11. 20:56

제네릭은 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능이다. 

즉, 클래스 내부에서 사용할 데이터 타입을 나중에 인스턴스를 생성할 때 확정하는 것을 제네릭이라 한다.

객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어든다.

ArrayList와 같은 컬렉션 클래스는 다양한 종류의 객체를 담을 수 있긴 하지만 보통 한 종류의 객체를 담는 경우가 더 많다. 그런데도 꺼낼 때 마다 타입체크를 하고 형변환을 하는 것은 아무래도 불편할 수 밖에 없다.


1.자료형의 안전성에 대한 논의

 

예제 1.

class Orange
{
int sugarContent; // 당분 함량
public Orange(int sugar) { sugarContent=sugar; }
public void showSugarContent()
{
System.out.println("당도 "+sugarContent);
}
}
class FruitBox
{
Object item;

public void store(Object item) { this.item=item; }
public Object pullOut() { return item; }
}
class ObjectBaseFruitBox
{
public static void main(String[] args)
{
FruitBox fBox1=new FruitBox();
fBox1.store(new Orange(10));
Orange org1=(Orange)fBox1.pullOut();
org1.showSugarContent();
FruitBox fBox2=new FruitBox();
fBox2.store("오렌지");
Orange org2=(Orange)fBox2.pullOut(); //오류가 발생하는 코드, 이러한 코드는 실행 중간에 발생하는데 컴파일 과정에서 발견되는 오류상황보다 발견 및 정정이 어렵다. 즉, 이는 자료형에 안전한 형태가 아니다.
org2.showSugarContent();
}
}

 

위 예제를 실행하면 Class Casting Exception 에러가 발생한다.

 

2.제네릭 메소드의 정의와 호출


- 클래스의 메소드만 부분적으로 제네릭화 할 수 있다.
- 제네릭 메소드의 호출과정에서 전달되는 인자를 통해서 제네릭 자료형을 결정할 수 있으므로 자료형
의 표현은 생략 가능하다

 

class InstanceTypeShower
{
int showCnt=0;
public  void showInstType(T inst)
{
System.out.println(inst);
showCnt++;
}
void showPrintCnt()
{
System.out.println("Show count: "+showCnt);
}
}
class IntroGenericMethod
{
public static void main(String[] args)
{
AAA aaa=new AAA();
BBB bbb=new BBB();
InstanceTypeShower shower=new InstanceTypeShower();
shower.<AAA>showInstType(aaa);   //shower.showInstType(aaa); 일반적인 호출방법
shower.<BBB>showInstType(bbb);  //shower.showInstType(bbb);
shower.showPrintCnt();
}
}

 

예제 2.

class Orange
{
int sugarContent; // 당분 함량
public Orange(int sugar) { sugarContent=sugar; }
public void showSugarContent() { System.out.println("당도 "+sugarContent); }
}
class OrangeBox
{
Orange item;
public void store(Orange item) { this.item=item; }
public Orange pullOut() { return item; }
}
class OrangeBaseOrangeBox
{
public static void main(String[] args)
{
OrangeBox fBox1=new OrangeBox();
fBox1.store(new Orange(10));
Orange org1=fBox1.pullOut();
org1.showSugarContent();
OrangeBox fBox2=new OrangeBox();
fBox2.store("오렌지");   //해당 부분에서 오류가 생겨 메소드 store에 문자열 인스턴스가 전달될 수 없음이 발견된다.
Orange org2=fBox2.pullOut();
org2.showSugarContent();
}
}

 

 

 

3.제네릭 메소드와 둘 이상의 자료형


- T, U와 같은 문자는 상징적이다. 따라서 타 문자로도 대체 가능하다.
- 제네릭 클래스에도 적용된다.
예> class AAA<T, U> 

T a1; 

U a2; 

public void setA1(T a){a1=a;}
public void setA2(U a){a2=a;} }

 

4.제네릭 클래스 기반 인스턴스 생성

- T를 Orange로 결정해서 FruitBox의 인스턴스를 생성하고 이를 참조할 수 있는 참조변수를 선언해서
참조값을 저장한다.