ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA] Generics 정의 및 타입변수, 다형성
    JAVA 2022. 8. 23. 11:43
    728x90
    반응형

    Generics란 무엇인가?

    컴파일 시 타입을 체크해주는 기능을 말하며 객체의 타입 안정성을 높이고 형변환의 번거로움을 줄일 수 있다.

    • 실행시 에러가 발생하는 것을 컴파일 에러로 만들어 준다.
    • JDK 1.5 이후 Generics를 꼭 사용해주는 것이 좋다.
    ArrayList<Tv> tvList = new ArrayList<Tv>();
    tvList.add(new Tv()); // ok
    tvList.add(new Audio()); // Error!
    • Tv 타입의 객체만 저장할 수 있는 ArrayList타입의 참조변수 tvList가 만들어졌다.

    예제

    ArrayList list = new ArrayList();
    list.add(10);
    list.add(20);
    list.add("30");
    Integer i = (Integer)list.get(2); // 컴파일 에러 x But 실행시 형변환 에러 발생
    // 인덱스 2는 String이다.
    
    ArrayList<Integer> list = new ArrayList<Integer>();
    list.add(10);
    list.add(20);
    list.add("30"); // Error!
    list.add(30);
    
    Integer i = list.get(2); // (Integer) 생략가능
    // 이미 Integer만 저장되게 만들었기 때문이다.

    타입 변수

    클래스를 작성할때 Object타입 대신 타입변수(E)를 선언해서 사용한다.

    public class ArrayList extends AbstractList{
        private transient Object[] elementData;
        public boolean add(Object o){내용생략}
        public Object get(int index){내용생략}
    }

    위에 코드를 Generics를 사용하면 아래와 같은 코드로 변형된다.

    public class ArrayList<E> extends AbstractList<E>{
        private transient E[] elementData;
        public boolean add(E o){내용생략}
        public E get(int index){내용생략}
    }
    • 객체 생성시에는 타입변수(E) 대신 실제 타입을 지정(대입) 해야한다.
    ArrayList<Tv> tvList = new ArrayList<Tv>();
    
    Public class ArrayList extends AbstractList{
        private transient Tv[] elementData;
        public boolean add(Tv o){내용생략}
        public Tv get(int index){내용생략}
    }

    예제

    class Product{}
    class Tv extends Product{}
    class Audio extends Product{}
    
    ArrayList list = new ArrayList();
    list.add(new Tv()); // ok
    list.add(new Audio()); // ok
    
    Tv t = (Tv)list.get(0); // ok
    
    ArrayList<Tv> list = new ArrayList<Tv>();
    list.add(new Tv()); // ok
    // list.add(new Audio()); >> Error!
    Tv t = list.get(0); // ok 형변환(Tv)를 생략할 수 있다.

    Generics 용어 정리

    용어 내용
    Box<T> 제네릭스 클래스 "T의 Box" 또는 "T Box"라고 읽는다.
    T 타입변수 또는 타입 매개변수
    Box 원시타입(raw type) 또는 일반 클래스
    class Box<T>{ } 제네릭스 클래스 선언
    Box<String> b = new Box<String>(); String 타입만 저장되는 Box타입의 참조변수 b

    Generics 타입과 다형성

    참조변수와 생성자의 대입된 타입은 꼭 일치해야한다.

    class Product{}
    class Tv extends Product{}
    class Audio extends Product{}
    
    ArrayList<Tv> list1 = new ArrayList<Tv>(); // ok
    ArrayList<Product> list2 = new ArrayList<Tv>(); // Error! 타입변수는 상속과 상관없이 일치해야한다.

    Generics 클래스간의 다형성은 성립하지만 타입변수는 일치해야한다.

    List<Tv> list1 = new ArrayList<Tv>(); // ok
    List<Tv> list2 = new LinkedList<Tv>(); // ok
    • ArrayList와 LinkedList는 List 인터페이스를 구현한 클래스들이다.

    매개변수의 다형성도 성립한다.

    ArrayList<Product> list = new ArrayList<Product>();
    list.add(new Product()); // ok
    list.add(new Tv()); // ok
    list.add(new Audio()); // ok

    예제

    class Product{}
    class Tv extends Product{}
    class Audio extends Product{}
    
    ArrayList<Product> ProductList = new ArrayList<Product>();
    ArrayList<Tv> TvList = new ArrayList<Tv>();
    // ArrayList<Product> tvList = new ArrayList<Tv>(); >> Error!
    // List<Tv> TvList = new ArrayList<Tv>(); >> ok 다형성
    
    ProductList.add(new Tv()); // ok Generics의 다형성 >> Product와 그의 자식 객체는 ok
    ProductList.add(new Audio());
    
    printAll(ProductList);
    
    // Method
    static void printAll(ArrayList<Product> list){
        for (int i = 0; i < list.size(); i++){
            System.out.println(list.get(i));
        }
    }

    Iterator<E>

    클래스를 작성할때 Object타입 대신 E같은 타입 변수를 사용한다.

    public interface Iterator<E>{
        boolean hasNext();
        E next();
        void remove();
    }

    예제

    class Student{
        String name = "";
        int ban;
        int no;
        
        Student(String name, int ban, int no){
            this.name = name;
            this.ban = ban;
            this.no = no;
        }
    }
    
    ArrayList<Student> list = new ArrayList<Student>();
    list.add(new Student("Java",1,1);
    list.add(new Student("JS",1,2);
    list.add(new Student("Python",2,1);
    
    Iterator<Student> it = list.iterator();
    
    while(it.hasNext()){
        Student s = it.next();
        // Generics 사용하지 않았을 경우>> Student s = (Student)it.next();
        System.out.println(s.name);
        // 위에 두줄을 System.out.println(it.next().name); 한줄로 변경할 수 있다.
    }

    HashMap<K,V>

    여러개의 타입 변수가 필요한 경우 콤마(",")를 구분자로 선언한다.

    HashMap<String, Student> map = new HashMap<String, Student>(); // 생성
    HashMap<String, Student> map = new HashMap<>();
    // 타입이 일치해야하기 때문에 뒤에는 생략이 가능하다.
    
    map.put("Java", new Student("Java",1,1,100,100,100); // 데이터 저장
    
    public class HashMap<K,V> extends AbstractMap<K,V>{
        public V get(Object key){내용생략}
        public V put(K key, V value){내용생략}
        public V remove(Object key){내용생략}
    }

    예제

    class Student{
        String name = "";
        int ban;
        int no;
        int kor;
        int eng;
        int math;
        
        Student(String name, int ban, int no, int kor, int eng, int math){
            this.name = name;
            this.ban = ban;
            this.no = no;
            this.kor = kor;
            this.eng = eng;
            this.math = math;
        }
    }
    
    HashMap<String, Student> map = new HashMap<String, Student>();
    // HashMap<String, Student> map = new HashMap<>(); 동일하다.
    
    map.put("Java", new Student("Java",1,1,80,50,70));
    
    Student s = map.get("Java"); // 지정된 키(key)에 해당하는 value를 반환한다.
    // 생성시 Generics를 사용하지 않으면?
    // Student s = (Student)map.get("Java");
    728x90
    반응형

    'JAVA' 카테고리의 다른 글

    Java로 만든 스케줄 관리 프로그램  (1) 2022.08.23
    Collections & Collection class 정리  (0) 2022.08.23
    Java 객체지향 공부 다형성, interface, 상속, 포함 등  (0) 2022.08.22
    [JAVA] Map 관련 내용  (0) 2022.08.19
    [JAVA] TreeSet  (0) 2022.08.19
Designed by Tistory.