-
JAVA 제네릭스와 제네릭클래스back-end&DB/Java 2023. 5. 27. 23:57728x90
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