ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JAVA 제네릭스와 제네릭클래스
    back-end&DB/Java 2023. 5. 27. 23:57
    728x90

    1. 제네릭스

     

    다양한 타입의 객체를 지원하는 클래스나 인터페이스와 메소드를 정의하는 방법

    똑같은 동작을 하는 클래스와 메소드를 여러번 만들 필요가 없이,

    딱 한번만 정의하고 여러타입에 대해서 지원할수 있도록 주는것
       

    int[] iArray = {1, 2, 3, 4, 5};
    double[] dArray = {1.0, 2.0, 3.0, 4.0, 5.0};
    String[] sArray = {"A", "B", "C", "D", "E"};

    위의 내용을 출력하는 메소드를 만들게 된다면

    아래와 같은 코드로 작성하게 됩니다.

    private static void printStringArray(String[] sArray) {
            for (String s : sArray) {
                System.out.print(s + " ");
            }
            System.out.println();
        }
    
        private static void printDoubleArray(double[] dArray) {
            for (double d : dArray) {
                System.out.print(d + " ");
            }
            System.out.println();
        }
    
        private static void printIntArray(int[] iArray) {
            for (int i : iArray) {
                System.out.print(i + " "); // 1 2 3 4 5
            }
            System.out.println();
        }

     

     

    printIntArray(iArray);
    printDoubleArray(dArray);
    printStringArray(sArray);
    
    //1 2 3 4 5 
    //1.0 2.0 3.0 4.0 5.0 
    //A B C D E

    각각의 메소드를 만들어야 되지만.

     

    제네릭스를 이용하게 된다면,

    // T : Type의 약자로 사용했습니다.
        private static <T> void printAnyArray(T[] array) {
            for (T t : array) {
                System.out.print(t + " ");
            }
            System.out.println();
        }

    (파라미터)T 의 자리에 SimToo를 넣어도 작동을 하지만,

    K : Key, V: Value 등등

    쉽게 파악이 되는 단어로 설정하는것이 좋습니다.

     

     

    - 제네릭스에서 지원하는 것은 객체이므로 기본자료형은 사용을 못합니다.

     

    기본자료형의 경우 래퍼클래스 처리를 해야 됩니다.

    Integer[] iArray = {1, 2, 3, 4, 5};
    Double[] dArray = {1.0, 2.0, 3.0, 4.0, 5.0};
    String[] sArray = {"A", "B", "C", "D", "E"};
    
    printAnyArray(iArray);
    printAnyArray(dArray);
    printAnyArray(sArray);
    
    //1 2 3 4 5 
    //1.0 2.0 3.0 4.0 5.0 
    //A B C D E

     

     

    1.2 제네릭스 심화

    public static <T> void Coffee(T name) {
    	System.out.println(name + "님은 커피를 좋아 합니다.");
    }
    
    public static <T, V> void Coffee(T name, V coffee) {
    	System.out.println(name + "님은 " + coffee + "를 좋아 합니다.");
    }

     

    Coffee("심심");
    Coffee(1);
    
    Coffee("심투", "아메리카노");
    Coffee(2, "딸기라떼");
    //출력값
    //심심님은 커피를 좋아 합니다.
    //36님은 커피를 좋아 합니다.
    //심투님은 아메리카노를 좋아 합니다.
    //37님은 딸기라떼를 좋아 합니다.

     

     

    2. 제네릭 클래스의 활용

     

    번호로 주문받는 고객과 닉네임을 주문 받는 고객이 존재하는 커피점이 있다고 합니다.

    CoffeeByNumber c1 = new CoffeeByNumber(33); // 번호로 주문받은 고객
    c1.ready();
    
    CoffeeByNickname c2 = new CoffeeByNickname("심심군"); // 닉네임으로 주문 받은 고객
    c2.ready();
    //출력값
    //커피 준비 완료 : 33
    //커피 준비 완료 : 심심군
    public class CoffeeByNickname {
        public String nickname;
    
        public CoffeeByNickname(String nickname) {
            this.nickname = nickname;
        }
    
        public void ready() {
            System.out.println("커피 준비 완료 : " + nickname);
        }
    public class CoffeeByNumber {
        public int waitingNumber;
    
        public CoffeeByNumber(int waitingNumber) {
            this.waitingNumber = waitingNumber;
        }
    
        public void ready() {
            System.out.println("커피 준비 완료 : " + waitingNumber);
        }

     

     

    오브젝트를 활용한다면?

    public class CoffeeByName {
        public Object name; // 오브젝트로 만들어서 Integer, Double, String.. 등등 사용이 가능하다.
    
        public CoffeeByName(Object name) {
            this.name = name;
        }
    
        public void ready() {
            System.out.println("커피 준비 완료 : " + name);
        }
    }

     

    CoffeeByName c3 = new CoffeeByName(34); // 정수
    c3.ready();
    
    CoffeeByName c4 = new CoffeeByName("심투"); // 문자열
    c4.ready();

     

    다만 문제점이 발생을 하게 됩니다.

    형변환을 통해서만 넣을 수가 있으며,

    c4Name = (String) c3.name; 같이 정수를 문자열로 형변환이 불가능합니다.(에러발생)

     

    Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

     

    int c3Name = (int) c3.name;
    // 형 변환을 통해서만 넣을수있다.
    System.out.println("주문 고객 번호 : " + c3Name);
    
    String c4Name = (String) c4.name;
    System.out.println("주문 고객 이름 : " + c4Name);
    
    //  c4Name = (String) c3.name; 정수를 문자열로 형변환이 불가능하다.
           
    //출력값
    //커피 준비 완료 : 34
    //커피 준비 완료 : 심투

     

    그렇다면 제네릭 클래스를 사용한다면?

     

    형변환의 문제가 없이 잘 입력을 받습니다.

    public class Coffee <T>{ // 제네릭 클래스
        public T name;
    
        public Coffee(T name) {
            this.name = name;
        }
    
        public void ready() {
            System.out.println("커피 준비 완료 : " + name);
        }
            Coffee<Integer> c5 = new Coffee<>(35);
            c5.ready();
            int c5Name = c5.name; // 형변환없이 잘 입력받는다.
            System.out.println("주문 고객 번호 : " + c5Name);
    
            Coffee<String> c6 = new Coffee<>("심심이");
            c6.ready();
            String c6Name = c6.name; // 형변환없이 잘 입력받는다.
            System.out.println("주문 고객 이름 : " + c6Name);
            
            //출력값
            //커피 준비 완료 : 35
            //주문 고객 번호 : 35
            //커피 준비 완료 : 심심이
            //주문 고객 이름 : 심심이

     

     

    2.1 제네릭 클래스의 심화

     

    유저 관리를 원하는 커피 가게라고 생각을 해봅시다.

    public class User {
        public String name;
        public User(String name) {
            this.name = name;
        }
        public void addPoint() {
            System.out.println(this.name + "님, 포인트 적립되었습니다.");
        }

     

    유저 클래스를 상속(extends)받아서 만든 VIP 유저 클래스

     

    public class VIPUser extends User {
        public VIPUser(String name) {
            super("특별한 " + name); // super 로 부모 클래스를 호출
        }
    }

     

    - 형을 제한해서 사용하는 방법 정해진 클래스의 개체만 받는 방법.

    <T extends User>을 통해서 T는 User 클래스와 User를 상속하는 것(VIPUser)만 들어 올 수 있다.

    import chap_09.user.User;
    
    public class CoffeeByUser <T extends User>{
        public T user; // T 를
    
        public CoffeeByUser(T user) {
            this.user = user;
        }
    
        public void ready() {
            System.out.println("커피 준비 완료 : " + user.name);
            user.addPoint(); // addPoint 메소드 출력
        }
    }

     

    728x90

    'back-end&DB > Java' 카테고리의 다른 글

    Servlet URL  (0) 2023.06.13
    servlet 인코딩 방식  (0) 2023.06.13
    JAVA JDBC과 API  (0) 2023.05.24
    JAVA 추상과 인터페이스  (0) 2023.05.22
    JAVA MVC패턴  (0) 2023.05.22
Designed by Tistory.