GitHub

https://github.com/Backcoder-June

BackCoder 기록 그리고 숙달

Back to the Java

Generic < T > 제너릭

Backcoder 2022. 7. 7. 21:42

< Generic >

 

- Data 타입을 미정 < T > 로 줘놓고, 나중에 정하기   

- class 내부에서 사용할 data type 을 나중에 instance 를 생성할 때, 확정 하는 것
      [1] instance 별로 필요한 data type 으로 바꾸어 class 를 사용할 수 있게 함으로서 코드 중복 방지
      [2] Type safety - 용도와 맞지않는 data type 이 들어가지 않도록 안전보장
      [3] generic 은 참조형 data type 만 가능 ( wrapper class ) 


- 명시적 형변환 필요 X ( instanceof )

if (bb instanceof Apple){
System.out.println(((Apple)bb).origin);}

 Generic 을 사용하지않고, Object 타입으로 받아서 사용했을 시, 

- 다양한 Type 을 다 받을 수 있다는 장점이 있으나 BUT 

- 위와같이 매번  객체타입이 맞는지 확인 ( instanceof ) 해야하고,

- Object => (Apple)  으로 형변환을 해줘야 Apple 객체에 접근할 수 있다. 

 

 

 

< Generic 하나 사용 > 

 

class Student < T >
T  id;       <= id Type 이 어떨땐 int, 어떨땐 String 이어야 할것같다. 
=> 나중에 정해주겠다 데이터타입 : T (TYPE) (일반적 사용)
=> T Generic 쓸꺼면, 해당 클래스에도 <T> 표시 해줘야한다.

String name; 
Student( T id, String name) { 
this.id = id; 
this.name = name; } } 

 

main
Student < String >  s1 = new Student( "one", "June" );  
s1.id => one 
Student < Integer >  s2 = new Student( 2 , "Tom" );  
s2.id => 2

=> 생성자로 값을 줄 때, 필요에 따라 < T > 제너릭 타입을 다르게 주면서 사용할 수 있다. 

=> s1.id 해서 꺼낼 때, 형변환이나 instanceof 확인 등을 할 필요가 없다. ( Object 로 받았을 시 해줘야하는 귀찮은것들 )  

 

< Generic 두개 사용 >

 

class Student < T1, T2 > 
T1  id;  

T2 grade; 
Student( T1 id, T2 grade ) { 
this.id = id; 
this.grade = grade; } }

 

main
Student < String, String >  s1 = new Student( "one", "A+" );  
s1.id => one 

s1.grade => A+
Student < Integer, Integer >  s2 = new Student( 2 , 85 );  
s2.id => 2

s2.grade => 85 
Student < Integer, String > s3 = new Student( 3, "D+" );   

s3.id => 

s3.grade = D+ 

 

이렇게 필요에 따라 Generic 을 설정해 사용할 수 있다. 

 

 

 

 

< 클래스 타입 Generic 사용 > 

 

class Food {Int price; CONSTUCtOR;  }                    

class Restaurant { String location; CONSTRUCTOR; }

 

=> Food 클래스가 타입으로 사용되면, 객체 생성해서 price 를 출력하고 싶고 

     Restaurant 클래스가 사용되면, location 을 출력하고 싶다.  

 

class < T > Box{                        

T contents;          // 이 클래스들을 타입으로 사용할  변수 contents  

GETTER                => Food contents / Restaurant contents

SETTER  } 

 

main 

Food  F = new Foold(  17000 ); 

Restaurant R = new Restaurant( " 홍대 " ); 

 

Box<  > B = new Box( );            

 

Box<Food> B = new Box( );           // Food 클래스타입으로 Generic 주자  

                                                       // 이제 이 Box 는 Food 객체도 사용할 수 있는 Box가 되었다.

 

B.SetContents( F ) ;                       // 위에서 만들어 둔 Food 객체 F 를 Box에 담는다. ( 타입을 맞췄기 때문에 가능 ) 

Food  f1  =  B.GetContents( );            

 sout ( f1.price );                             

 

이렇게 형변환이나 타입비교 없이 뽑아쓸 수 있다.

 

- 마찬가지로 Food 가 아니라 Restaurant 클래스를 타입으로 썻다면  

Restaurant r1 = B.GetContents( ); 

sout ( r1.location );                              이렇게 사용할 수 있다. 

 

 

 

 <Generic  extends  상속 >     => 부모 class 의 자식들로만 datatype 제한


     class students < T extends Number >{  }   

=> Number 클래스의 자식들 Integer, Double, Byte 타입으로만 가능 

   

 

-  generic 에서 상속은  interface를 상속해도 extends 로 표현 한다.   

                                         ( 기존의 extends 와 다른 개념의 generic 전용 표현이라고 생각하자 ) 

 

 

<(참고) Generic  메소드 >  => Generic은 메소드에도 사용이 가능하다. 

 

public <T> void getresult( T result ) {};
     en1.<Language> getresult( L1 );