sussa
컴퓨터가 할 일은 컴퓨터가.
sussa
전체 방문자
오늘
어제

블로그 메뉴

    • 분류 전체보기 (58)
      • Language (58)
        • JAVA (58)

    공지사항

    인기 글

    태그

    • inheritance
    • tree
    • Stream
    • Database
    • Til
    • recursion
    • 재귀
    • 자료구조
    • 스파르타코딩클럽
    • Web
    • Method
    • DI
    • spring
    • 최종연산
    • 개발자
    • Instance
    • singleton
    • CSS
    • 캡슐화
    • 다형성
    • 조건문
    • Thread
    • java
    • 상속
    • binaryTree
    • Class
    • 웹개발종합반
    • HTML
    • Algorithm
    • BinarySearchTree

    최근 댓글

    최근 글

    티스토리

    hELLO · Designed By 정상우.
    sussa

    컴퓨터가 할 일은 컴퓨터가.

    Java Generics
    Language/JAVA

    Java Generics

    2022. 9. 3. 18:13

     

    🎯 목표 : 제네릭의 개념과 활용 이해

    📒 Generics

    👉 다양한 타입의 객체들을 다루는 메소드나 컬렉션 클래스에 컴파일 시 타입체크를 해주는 기능

    ArrayList< E > list = new ArrayList< E >(); // 뒤의 T는 생략가능하다
    // 타입 변수는 T,E등 다른것을 사용해도된다
    • <>에 데이터 타입을 정의하여 선언한다.

    📌 특징

    • 제네릭 객체를 생성할때 클래스 간의 다형성은 성립되며, 양 변의 데이터 타입 T는 동일해야된다.
    • 타입의 안정성을 보장해주는 기능을 한다. 의도하지 않은 타입의 객체가 저장되는 것을 막고 저장된 객체를 꺼내올때 원래의 타입과 다른 타입으로 잘못 형변환 되어 발생할수 있는 에러를 줄일수 있다.
    • 즉 다룰 객체의 타입을 미리 명시해줘 객체를 꺼내어 사용할때 타입 체크, 형변환 등 번거로운 작업을 줄여주고 에러를 방지한다.

    📌 선언

    class CageList< T > {
        ArrayList<T> list = new ArrayList<>();
        void setCage (T animal){
            list.add(animal); }
        T getCage(int index) {
            return list.get(index);
        }
    }
    • <T> T 데이터 타입만 저장가능하다.
    • <T extends Class> Class의 자신을 포함한 모든 자식 데이터 타입이 저장가능하다.
    • <T extends Interface> extends 키워드를 사용하여 해당 인터페이스를 구현한 데이터 타입 저장이 가능하다는것을을 명시해줄수 있다.
    • <T extends Class & Interface> Class 자신을 포함한 자식 클래스중 인터페이스를 구현한 타입만 저장 가능하다는 것을 명시해준다.  
    • 클래스에 타입변수로 제네릭을 선언하지 않고 클래스 내부의 메소드에만 타입변수로 제네릭을 선언할수 있다.
    • 클래스에 타입변수로 제네릭을 선언한 경우 클래스 내부에 Static 멤버는 타입변수를 선언할수 없다. (제네릭의 제한)
    class CageList<T> {
        ArrayList<T> list = new ArrayList<>();
        
        static void setCage (T animal){ // 에러발생
            list.add(animal); 
        }
        T getCage(int index) {
            return list.get(index);
        }
    }
    • Static 멤버는 선언된 제네릭 타입변수와 상관없이 동일한 것이어야 하기 때문에 에러가 발생한다.

    👉 선언 예제

    import java.util.ArrayList;
    
    interface Thisinfo { String info();}
    
    class Animal implements Thisinfo { public String info(){return "This Animal";} }
    
    class Cat extends Animal implements Thisinfo { public String info() {return "This Cat";} }
    
    class Dog extends Animal implements Thisinfo { public String info() {return "This Dog";} }
    
    class Cow extends Animal { }
    
    class Person implements Thisinfo { public String info() {return "This Person";} }
    
    class CageList<T extends Animal> {
        ArrayList<T> list = new ArrayList<>();
        void setCage (T animal){
            list.add(animal); }
        T getCage(int index) {
            return list.get(index);
        }
    }
    
    public class Study {
        public static void main(String[] args) {
            CageList <Animal> list = new CageList<>();
            list.setCage(new Cat());
            list.setCage(new Dog());
            list.setCage(new Cow()); //부모 클래스가 인터페이스를 구현했기 때문에 저장가능하다.
    //        list.setCage(new Person()); // 자식 클래스가 아니기때문에 에러발생.
    
            for (Animal i : list.list) {
                System.out.println(i);
            }
        }
    }
    • Interfacd Thisinfo를 구현한 Animal, Cat, Dog, Person 클래스가 있다.
    • CageList는 ArrayList 내부에 생성하여 일부 기능을 구현하도록 만들었다.
    • CageList 클래스는 <T extends Animal & Thisinfo> 를 Generic 선언을 하였다.
    • CageList 객체를 생성할때 Generic의 데이터 타입으로는 Animal 와 상속관계이고 인터페이스 Thisinfo를 구현한 클래스만 데이터 타입으로 저장가능하다.
    • public 클래스 부분에서 확인해보면, Animal의 상속을 받은 Cat,Dog,Cow 객체는 생성되어 데이터로 저장될수 있다.
    • Person은 Animal과 상속관계가 아니기 때문에 호출되어 저장할수 없다.
    • 만약 아래와 같이 CageList 객체를 Person 데이터 타입으로 생성하려하면 에러가 발생할것이다. Person은 제네릭으로 선언한 클래스 범위에 포함되지 않는다.
     CageList<Person> list1 = new CageList<Person>();

     

    📌  와일드 카드 <?>

    class Tostr {
        static String str = "";
        static String listtoString(CageList<? extends Animal> list) {
            for (int i=0; i<list.cageSize(); i++){
               str += ", " + list.getCage(i).info();
            }
            str = str.substring(1);
            return str;
        }
    }
    • 위와 같이 CageList 요소의 info 메소드를 호출하여 출력값을 나열하는 클래스를 만들었다.
    • Tostr 클래스 내부의 메소드는 static 메소드며, 타입변수를 사용할수 없고 데이터 타입을 확정지어줘야된다.
    • 메소드의 데이터 타입을 확정 지어 주게되면, 해당데이터 타입 외에는 Tostr 클래스의 listtoString 메소드에 접근할수 없게된다.
    • 선언 예제에서 상속관계를 가지고 있는 여러 Animal 자식 클래스들이 CageList 클래스에 참조되어 생성되었을때 Animal 상속관계의 데이터 타입이 listtoString 메소드에 접근할수 있게 만들기 위해서 와일드 카드로 상속관계의 데이터 타입은 접근할수 있도록 만들었다. 
    • 와일드 카드의 선언 방식은 아래와 같다.
    < ? > // 제한 없이 모든 타입 가능 Object의 자식 클래스는 모두 가능.
    < ? super T > // T를 포함한 부모 클래스들만 가능하다.
    < ? extends T >// T를 포함한 자식 클래스들만 가능하다.

    📌  제네릭 타입의 제거

    • 컴파일러는 제네릭 타입을 제거하고 필요한 부분에 자동으로 형변환을 시킨다.
    • 제네릭스 기능 자체가 컴파일 단게에서 런타임 에러를 발견하기 위한 기능이기 때문이고,
    • 이런 방식이 성능적으로는 떨어지지만 하위 호환성 때문에 컴파일 단계에서 제네릭 타입을 제거한다.

    'Language > JAVA' 카테고리의 다른 글

    Java Annotation  (1) 2022.09.04
    Java 열거형  (0) 2022.09.03
    Java Memory Structure  (0) 2022.09.03
    Java Object, Class, Instance_02 - OOP  (0) 2022.09.02
    Java Collection Framework 요약  (0) 2022.08.29
      'Language/JAVA' 카테고리의 다른 글
      • Java Annotation
      • Java 열거형
      • Java Memory Structure
      • Java Object, Class, Instance_02 - OOP
      sussa
      sussa
      Efforts to take on a challenge

      티스토리툴바