ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ch12 자바 지네릭스] 개념, 다형성, Generic 타입 클래스
    프로그래밍 언어/JAVA 2023. 2. 27. 17:04

     

    📑 지네릭스란? (Generics)

     

    지네릭스는 다양한 타입 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능이다. 객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안전성을 높이고 형변환의 번거로움이 줄어든다. 

     

    ArrayList<Integer> list = new ArrayList<Integer>(); 
    list.add(2); //ok
    list.add("2"); // 컴파일 에러, Integer 타입 외에 다른 타입은 저장 불가 

     

    그리고 저장된 객체를 꺼낼 때는 형변환이 필요 없어서 편리하다. 이미 어떤 타입의 객체들이 저장되어 있는지 알고 있기 때문이다. 

     

     


     

     

    아래 코드를 통해 개념을 이해해보자. 

     

    //1. 지네릭스 사용 x
    
    ArrayList list = new ArrayList();
    list.add(10);
    list.add(20);
    list.add("30"); //String을 추가, 컴파일 에러 발생 x
    
    /*컴파일 ok, why?? list는 object형인데 이를 Integer로 형변환 했으므로
     * 컴파일러가 봤을때는 문제가 없다. 그러나 실행 시키면 ClassCastException 발생 -> 컴파일 한계*/
    Integer i = (Integer) list.get(2); 
    
    System.out.println(list);

     

    list에 int형과 string 형의 값을 추가한 다음, list의 2번째 값을 조회해서 Integer 형 i 변수에 값을 할당하는 과정이다. 컴파일 에러는 나지 않지만 run 했을 시 타입 변환 에러가 발생한다. 이는 Integer 형 변수에 String 값을 할당했기 때문이다. 

     

     

    제너릭스는 이러한 컴파일의 한계를 보완하는 장점이 있다. 

     

    1. 타입 안전성을 제공한다.
    2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해진다. 

     

     

    //2. 지네릭스 사용
    ArrayList<Integer> list2 = new ArrayList<Integer>();
    list2.add(10); //list.add(new Integer(10));
    list2.add(20);
    list2.add(30); //String을 추가할 경우, 컴파일러가 에러를 발생시킴.
    
    Integer i2 = list2.get(2); //Integer 밖에 못들어가는 걸 아니까 형변환할 필요가 없다. 
    
    System.out.println(list2);

     

    지네릭스를 사용하면 list2.add("30")을 입력했을 시 컴파일 에러를 발생시킨다. 따라서 코드를 작성할 때 이부분이 잘 못 됐구나 개발자가 즉각으로 판단할 수 있다. 

     

    또한 Integer 타입이 저장될것이라 이미 선언했기에 Integer로 형변환할 필요가 없다. 

     

     

     

    package ch12;
    
    import java.util.ArrayList;
    
    
    class Tv{}
    class Audio{}
    
    public class GeneficTest2 {
    
    	public static void main(String[] args) {
    		ArrayList list = new ArrayList();
    		//어느 타입이든 저장 가능 
    		list.add(new Tv());
    		list.add(new Audio());
    
    		Tv t = (Tv) list.get(0);
    	
    		ArrayList<Tv> list2 = new ArrayList<Tv>();
    		//Tv 타입만 저장 가능 
    		list2.add(new Tv());
    		//list2.add(new Audio());
    		
    		Tv t2 = list2.get(0);
    
    	
    	}
    
    }

     

     

     

     


     

    ★ 참고로 모든 타입의 객체들을 저장하려면 Object를 사용하면 된다. 그럼 모든 타입을 받으려면 <Object> 제너릭스 사용하지 않아도 되는 거 아닌가? 라고 생각할 수 있지만 JDK 1.5 이후에는 지네릭스를 꼭 써줘야한다. 

     

    ArrayList list = new ArrayList(); //JDK1.5 이전. 지네릭스가 도입 이전
    ArrayList<Object> list = new ArrayList<Object>(); //JDK1.5 이후 지네릭스 타입 입력! 

     

     

     

    📑 지네릭 타입과 다형성

     

    지네릭 클래스의 객체를 생성할 떄, 참조변수에 지정해준 지네릭 타입과 생성자에 지정해준 지네릭 타입은 같아야 한다. 클래스 Tv와 Product가 서로 상속관계에 있어도 일치해야한다. 

     

    ArrayList<Tv> list = new ArrayList<Tv>() ; //ok, 일치 
    ArrayList<Product> list = new ArrayList<Tv>() ; // 에러, 불일치 

     

    그러나 지네릭 타입이 아닌 클래스의 타입 간에 다형성을 적용하는 것은 가능하다. 

     

    List<Tv> list = new ArrayList<Tv>(); //ok
    List<Tv> list = new LinkedList<Tv>(); //ok

     

    package ch12.generics;
    
    import java.util.ArrayList;
    
    class Product{}
    class Tv1 extends Product{}
    class Audio1 extends Product{}
    
    
    public class Ex1 {
    
    	public static void main(String[] args) {
    		
    		ArrayList<Product> productList = new ArrayList<Product>();
    		ArrayList<Tv1> tvList = new ArrayList<Tv1>(); // 에러
    //		ArrayList<Product> tvList = new ArrayList<Tv>(); // 에러
    //		List<Tv> tvList = new ArrayList<Tv>(); //ok . 다형성
    		
    		productList.add(new Tv1()); // product와 그 자손들은 모두 추가 가능하다. 
    		productList.add(new Audio1());
    
    		tvList.add(new Tv1()); // product와 그 자손들은 모두 추가 가능하다. 
    //		tvList.add(new Audio1()); Audio1는 Tv1의 자손이 아니기 때문에 대입 불가. 
    
    		printAll(productList);
    		
    	}
    	
    	public static void printAll(ArrayList<Product> list) {
    		for(Product p : list) {
    			System.out.println(p);
    		}
    	}
    
    }

     

     

     

     

    반응형

    댓글

Designed by Tistory.