티스토리 뷰

Programming Language/JAVA

제네릭

광식'S Story 2009. 2. 19. 17:02
제네릭 
: Generics는 컬렉션(자료구조) 즉, 객체들을 저장(수집)하는 구조적인 성격을 보강하기 위해 제공되는 것이다. 
  간단히 예를 들자면 컵이라는 특정 객체가 있다. 이 컵은 물만 담을 수 있는 물컵, 또는 이 컵은 주스만 담을 수 있는 주스 컵!
  이렇게 상징적인 것이 바로 Generics다!
 
제네릭의 필요성 
: JDK5.0에 프로그래머가 특정 컬렉션(자료구조)에 원하는 객체 타입을 명시하여 실행하기 전에 컴파일단계에서 확인하여 지정된 객체가
  아니면 절대 저장이 불가능하게 할 수 있다. 
  (이전 버전까지는 반드시 실행하여 컬렉션(자료구조)에 있는 자원들을 하나씩 검출하여 확인할 수 밖에 없었다.)
 
   컬렉션 클래스들은 Object형으로 요소를 저장한다.
   별도의 형 변환(Casting)이 필요 없이 <>사이에 선언하였던 객체자료 형으로 검출되어 편리하다.
 

ex)  백터와 같은 컬렉션 객체는 다양한 원소로 저장될수 있다. add메서드의 전달인자가 모든 객체의 최상위 클래스인 Object형으로
       정의되어 있기때문에  다양한 원소를 add메서드로 추가할수 있고 Object형으로 관리된다.
       이로 인해 편리한점도 있지만 불편한점도 있다. 예제를 통해 살펴보자
            
아래 예제는 백터 객체에 저장된 문자열을 대문자로 변환하여 출력하는 예이다.
       import java util.*;
       class  test{
             public static void main(String[] args){
                    Vector vec = new Vector();
                    vec.add("Apple");                        //내부적으로 요소들을 Object형으로 관리하고 있음
                    vec.add("oRange");
 
                    String temp;
                    for(int i=0; i<vec.size();i++){
                             //temp = vec.get(i);               -> 이렇게 사용하면 에러발생한다.
                             temp = (String) vec.get(i);     // 그렇게 때문에 Ojbect형으로 관리되는 요소를 사용할때는 다운캐스팅을 해야함
                             System.out.println(temp.toUpperCase());
                    }
             }
       }
 
 하지만 제네릭을 사용하면 다운캐스팅하지 않아도 된다.
       import java util.*;
       class  test{
             public static void main(String[] args){
                    Vector<String> vec = new Vector<String>();  //제네릭 형태로 백터객체를 생성하였기때문에
                    vec.add("Apple");                                               
                    vec.add("oRange");
 
                    String temp;
                    for(int i=0; i<vec.size();i++){
                             temp = vec.get(i);                                    // String객체에 벡터 객체의 get메서드 결과값을 저장하기 위해
                                                                                              다운캐스팅 하지 않아도 된다.
                             System.out.println(temp.toUpperCase());
                    }
             }
       }
 
 
 
제네릭은 확장for문을 사용할수 있다.
확장for문은 배열이나 컬렉션과 같이 여러개체가 모여 있는 경우에 개체의 끝을 체크하지 않고도 하나씩 차례대로 접근할 수 있도록 한다
 
   형식)  for(자료형 접근변수명 : 배열이나 컬렉션 변수명){ 반복코드 }
 
ex)  import java util.*;
       class  test{
             public static void main(String[] args){
                    Vector<String> vec = new Vector<String>();  
                    vec.add("Apple");                                               
                    vec.add("oRange");
 
                    for(String temp : vec){                         
                             System.out.println(temp.toUpperCase());
                    }
             }
       }
 
 
 
 
 
제네릭을 사용한 클래스의 작성
: 제네릭을 지원하기 위해서는 템플릿 형태의 정해지지 않은 가상의 자료형을 클래스 정의해서 정해야 한다.
  보통 1글자의 영문자 대문자를 사용한다.
 ( API에서는 전달되는 객체가 현 객체 내에서 자료형(Type)으로 쓰일 때 <T>로 유도를 하고 있으며
   만약 전달되는 객체가 현 객체 내에서 하나의 요소(Element)로 자리를 잡을 때는 <E>로
   그리고 전달되는 객체가 현 객체 내에서 Key값으로 사용될 때는 <K>로,
   만약 전달되는 객체가 현 객체 내에서 Value값으로 사용될 때 <V>로 표현하고 있다. )
 
<T>는 아직 아무것도 확정되지 않은 자료형이다 즉 객체 생성시 어떤 자료형으로도 될수 있다.
 
ex)
class Gener<T>{
     private  T member;
     public void setValue(T  value){ member = value;}
     public  T     getValue(){return member;}
}
 
class test{
    public static void main(String[] args){
         
            Gener<Integer> obj1 = new Gener<Integer>();
            obj1.setValue(10);
            System.out.println(obj1.getValue());
 
            Gener<String> obj1 = new Gener<String>();
            obj1.setValue("이것이 제네릭");
            System.out.println(obj1.getValue());
 
    }
}
 
 
 
 
와일드카드 : 제네릭으로 선언된 객체들은 상속 관계에서도 형변환이 암시적으로 이루어지지 않는다. 그래서 와일드 카드를 사용한다.
                   하나의 객체만 저장 할 수 없는 경우 사용하는 것이 와일드 카드이다.
                   모든 객체를 저장하고 싶을 때 또는  특정 객체로 부터 상속 받은 객체들만 저장하고 싶을 때 사용되어 진다.
 

  와일드카드타입
------------------------------------------------------------------------------  
<?>
 -모든 객체자료형에 대한 배치를 의미
 
<? super 객체자료형>
 -명시된 객체자료형 또는 객체자료형의 상위 객체들의 배치를 의미
 
<? extends 객체자료형>
 -명시된 객체자료형 또는 객체자료형으로부터 상속받는 하위 객체들의 배치를 의미
------------------------------------------------------------------------------
 
ex)
 
import static java.lang.System.out;
class GenEx1{
   String msg = "GenEx1";
   public String getMsg(){ return msg;}
}

class GenEx2 extends GenEx1{
   String msg = "GenEx2";
   public String getMsg(){ return msg; }
}

class GenEx3 extends GenEx2{
   String msg = "GenEx3";
   public String getMsg(){ return msg; }
}
 

class GenericEx4<T>{
   T v;
   public GenericEx4(T n){ v = n; }
   public void set(T n){ v = n; }
   public T get(){ return v; }
   public static void main(String[] args){
      GenEx3 g3 = new GenEx3();
      GenericEx4<? super GenEx2> g4 =  new GenericEx4<GenEx1>(g3);
      GenEx3 test = (GenEx3)g4.get();
      // GenEx3 test = g4.get();//오류
      out.println("g4의 결과 : "+ test.msg+","+test.getMsg());
    }
}

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함