-
제너릭 (Generic)JAVA 2022. 9. 24. 17:31
Generic
클래스 선언 및 객체화 할 때 원하는 타입만을 넣기 위해서 쓰는 것
-> 어떤 타입이 들어 있는지 정보가 없기 때문에 확인 작업이 필요하다.
-> 제네릭을 사용하면 확인 작업을 안해도 된다.
package chap08.ex03.obj; public class Box { private Object value; // 이 안에 뭐가 들어올지 몰라서 Object로 만들어 둔다. public void setValue(Object value) { this.value = value; } public Object getValue() { return value; } }
package chap08.ex03.obj; public class Main { public static void main(String[] args) { // 박스에 무엇인가 넣는다. Box box = new Box(); box.setValue(123); // 박스에서 물건을 꺼낸다. // box에 무엇이 들었는지 정보가 없음 // 그래서 확인 작업이 필요 int val = (int)box.getValue(); System.out.println(val); } }
Generic 사용법
클래스나 인터페이스 선언 시 <T>를 붙인다.
T의 타입에 따라 데이터 타입이 변경된다.
package chap08.ex04.generic; public class Box<T> { // 뭐가 들어올지 모르므로 일단 T라고 해둔다. private T value; // T 타입에 따라 변수의 데이터 타입이 변경된다. public T getValue() { return value; } public void setValue(T value) { this.value = value; } }
package chap08.ex04.generic; public class Main { public static void main(String[] args) { // 박스에 들어갈 물건의 종류를 명시해준다. Box<Integer> box = new Box<Integer>(); box.setValue(123); // 박스를 열어본다. // 내용물을 알 수 있으므로 확인이 필요없다. int val = box.getValue(); System.out.println(val); } }
복수개의 제네릭을 사용 가능하다. (콤마로 구분하여)
package chap08.ex05.multi; public class MultiBox<K,V> { // 두 개의 타입을 지정할 수 있다. private K key; private V value; public K getKey() { return key; } public void setKey(K key) { this.key = key; } public V getValue() { return value; } public void setValue(V value) { this.value = value; } }
package chap08.ex05.multi; public class Main { public static void main(String[] args) { // 첫 변수는 String 타입, 두 번째 변수는 Integer가 데이터 타입이 된다. MultiBox<String, Integer> box = new MultiBox<String, Integer>(); //넣기 box.setKey("홍길동"); box.setValue(90); //꺼내기 String name = box.getKey(); int score = box.getValue(); System.out.println(name+" : " + score); } }
Generic의 클래스 사용
객체화 부분 제네릭에 데이터 타입을 명시하지 않아도 작동은 하지만 이를 다이아몬드 연산자라고 부른다 -> 사용은 편리하지만 효율성이 떨어진다.
package chap08.ex06.multi; public class Employee<A,B,C,D,E,F,G,H> { private A number; private B name; private C age; private D money; private E asset; private F pay; private G marry; private H hobby; public A getNumber() { return number; } public void setNumber(A number) { this.number = number; } public B getName() { return name; } public void setName(B name) { this.name = name; } public C getAge() { return age; } public void setAge(C age) { this.age = age; } public D getMoney() { return money; } public void setMoney(D money) { this.money = money; } public E getAsset() { return asset; } public void setAsset(E asset) { this.asset = asset; } public F getPay() { return pay; } public void setPay(F pay) { this.pay = pay; } public G getMarry() { return marry; } public void setMarry(G marry) { this.marry = marry; } public H getHobby() { return hobby; } public void setHobby(H hobby) { this.hobby = hobby; } }
package chap08.ex06.multi; public class Main { // 제너릭 타입을 클래스로 사용하지 않은 경우 public static void main(String[] args) { // 객체화 부분 제너릭에 데이터 타입을 명시해주지 않는 것을 다이아몬드 연산자라고 부른다. // 사용은 편리하지만 효율성이 떨어진다. Employee<Integer, String, Integer, Integer, Long, Float, Boolean, String> emp = new Employee<>(); // 데이터 넣기 emp.setAge(25); emp.setAsset((long) 50000000); emp.setHobby("독서"); emp.setMarry(true); emp.setMoney(10000); emp.setName("홍길동"); emp.setNumber(12); emp.setPay(1.0f); // 데이터 가져오기 int age = emp.getAge(); System.out.println(age); } }
제네릭 부분이 길어질 경우 클래스를 사용할 수 있다.
클래스를 사용하지 않을 때 데이터를 setter/getter로 바로 꺼내올 수 있지만 코드가 길어지고 실수가 생길 수 있다는 단점이 있다.
클래스를 사용한다면 데이터를 넣고 가져오는데 한 번씩의 작업을 더 해야하지만 코드를 줄일 수 있다. (제네릭이 많을 때 유리하다.)
package chap08.ex07.classtype; public class Info { private int emp_no; private String name; private int age; private int salary; private long assets; private float commision; private boolean married; private String hobby; public int getEmp_no() { return emp_no; } public void setEmp_no(int emp_no) { this.emp_no = emp_no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } public long getAssets() { return assets; } public void setAssets(long assets) { this.assets = assets; } public float getCommision() { return commision; } public void setCommision(float commision) { this.commision = commision; } public boolean isMarried() { return married; } public void setMarried(boolean married) { this.married = married; } public String getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } }
package chap08.ex07.classtype; public class Employee <T>{ private T t; public T getT() { return t; } public void setT(T t) { this.t = t; } }
package chap08.ex07.classtype; public class Main { // 제너릭 타입을 클래스로 사용한 경우 public static void main(String[] args) { Employee<Info> emp = new Employee<Info>(); // 데이터 넣기 Info info = new Info(); info.setAge(25); info.setAssets(1000000); info.setCommision(1.0f); info.setEmp_no(2); info.setHobby("영화"); info.setMarried(false); info.setName("김철수"); info.setSalary(10000); emp.setT(info); //데이터 가져오기 info = emp.getT(); int age = info.getAge(); System.out.println(age); } }
method에서 Generic 사용
메소드에서 제네릭을 사용하면 각각 다른 매개변수 타입을 사용할 수 있다.
-> 상황에 따라 유연하게 사용 가능하다.
반환이 없는 메소드일 경우 접근제한자와 void 사이에 제네릭을 쓰고 매개변수도 제네릭 타입으로 사용한다.
반환이 있는 메소드일 경우 메소드의 반환타입도 제네릭 타입으로 적어야한다.
package chap08.ex08.gmethod; public class Gmethod { // 제너릭을 사용하면 사용 시마다 각각 다른 매개변수 타입을 사용할 수 있다. public <T> void method1(T t) { System.out.println("입력값 : " + t); } // 받은 그대로 반환해 주는 경우 public <T> T method2(T t) { return t; } }
package chap08.ex08.gmethod; public class Main { public static void main(String[] args) { Gmethod gm = new Gmethod(); gm.method1(100); gm.method1("감자"); System.out.println(gm.method2("고구마")); System.out.println(gm.method2(true)); } }
Generic의 상속
클래스에서 자식의 생성자 매개변수를 받아 부모의 생성자에 전달한 것처럼 자식에서 부모에서 사용할 제네릭 타입을 받아서 전달해야 한다.
package chap08.ex09.inherit; public class BasicInfo<N,A> { private N name; private A age; public N getName() { return name; } public void setName(N name) { this.name = name; } public A getAge() { return age; } public void setAge(A age) { this.age = age; } }
package chap08.ex09.inherit; public class DetailInfo<N, A, H> extends BasicInfo<N, A> { private H hobby; public H getHobby() { return hobby; } public void setHobby(H hobby) { this.hobby = hobby; } }
package chap08.ex09.inherit; public class Main { public static void main(String[] args) { DetailInfo<String, Integer, String> info = new DetailInfo<String, Integer, String>(); info.setName("홍길동"); info.setAge(25); info.setHobby("게임"); String name = info.getName(); int age = info.getAge(); String hobby = info.getHobby(); System.out.println(name + "/" + age + "/" + hobby); } }
'JAVA' 카테고리의 다른 글
thread - 1 (스레드 생성~join) (1) 2022.09.24 컬렉션 프레임워크(List, Set, Map) (1) 2022.09.24 문자열 (String) (1) 2022.09.24 예외 (Exception) (0) 2022.09.24 추상화 (abstract, interface) (0) 2022.09.24