반응형
왜 제네릭을 사용하는가?
java 5부터 제네릭 타입이 새로 추가되었고 제네릭 타입을 이용해 잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 제거할 수 있다.
제네릭은 널리 사용된다.
- 컬렉션, 람다식, 스트림, NIC
- java API docs
- 클래스, 인터페이스, 메서드를 정의할 때 타입을 파라미터로 사용
제네릭의 특징
- 컴파일 시 강한 타입 체크를 할 수 있다.
- 타입 변환을 제거 한다.
List list = new ArrayList<>();
list.add("hello");
String str = (String) list.get(0);
List<String> list2 = new ArrayList<>();
list.add("hello");
String str2 = list2.get(0);
제네릭 타입 : class, Interface
Object를 대신 해 타입을 확정 짓는 용도로 사용한다.
public class Box {
private Object object; // 자바의 모든 타입을 저장하고 싶어서 만듬
public void set(Object object) {
this.object = object;
}
public Object get() {
return object;
}
}
public class Apple {
}
public static void main(String[] args) {
Box box = new Box();
box.set("Test");
String name = (String) box.get();
box.set(new Apple());
Apple apple = (Apple) box.get();
}
- 모든 타입을 담을 수 있는 Box를 만들었다
- 타입이 분명하지 않아 사용할 때면 형변환을 통해 사용해야 한다.
제네릭 타입 사용 방법
public class Box<T> { private T object; public void set(T object) { this.object = object; } public T get() { return object; } } public static void main(String[] args) { Box<String> box2 = new Box<>(); box.set("Test"); String name2 = box2.get(); Box<Apple> box3 = new Box<>(); box.set(new Apple()); Apple apple2 = box3.get(); }
- 지정한 타입으로 인식하여 형변환을 하지 않아도 된다.
멀티 타입 파라미터 : class<K, V, ...>, interface<K, V, ...>
제네릭 타입은 두대 이상의 멀티 타입 파라미터를 사용 할 수 있고 콤마로 구분한다.
public class Product <K, V>{
private K kind;
private V model;
public K getKind() { return this.kind; }
public V getModel() { return this.model; }
public void setKind(K kind) { this.kind = kind; }
public void setModel(V model) { this.model = model; }
}
public static void main(String[] args) {
Product<String, String> p = new Product<>();
p.setKind("1");
p.setModel("M");
}
제네릭 메서드 : <T, R> R method(T t)
제네릭 메서드는 매개 타입과 리턴 타입으로 타입 파라미터를 갖는 메서드를 말하며 리턴 타입 앞에 < > 기호를 추가하고 타입 파라미터를 기술한 다음 리턴 타입과 매개 타입으로 타입 파라미터를 사용하면 된다.
public <타입 파라미터, ...> 리턴 타입 메서드명(매개변수, ...) { } // 제네릭 메서드 선언 방법
리턴 타입 변수 = <구체적타입> 메서드명(매개값); // 명시적으로 구체적 타입을 지정
리턴 타입 변수 = 메서드명(매개값); // 매개값을 보고 구체적 타입을 추정
제한된 타입 파라미터 : <T extends 최상위타입>, <T super 최하위타입>
타입 파라미터에 지정되는 구체적인 타입을 제한해야 할 경우가 종종 있다.
예를 들어 숫자를 연산하는 제네릭 메서드는 매개값으로 Number타입 또는 하위 클래스 타입(Byte, Short, Integer, Long, Double)의 인스턴스만 가져와야 할 때 제한된 타입 파라미터가 필요하며 이경우에는 <T extends 최상위타입>를 사용하고 반대는 <T super 최하위타입>를 사용한다.
<T extends 최상위타입> : 자기 자신과 하위 클래스들로 제한
<T super 최하위타입> : 자기 자신과 상위 클래스들로 제한
public class BoundedTypeParameter {
public static void main(String[] args) {
// String str = Util.compare("a", "b");
int result1 = Util.compare(10, 20);
System.out.println(result1);
int result2 = Util.compare(3.5, 3);
System.out.println(result2);
}
private static class Util {
public static <T extends Number> int compare(T i, T i1) {
return Double.compare(i.doubleValue(), i1.doubleValue());
}
}
}
와일드카드 타입 : <?>, <? extends ...>, <? super ...>
코드에서 ?를 일반적으로 와일드 카드라고 부르며 세 가지 형태로 사용할 수 있다.
- 제네릭 타입<?> : 제한 없음 - 타입 파라미터를 대치하는 구체적인 타입으로 모든 클래스나 인터페이스 타입이 올 수 있다.
- 제네릭 타입<? extneds 상위타입> : 상위 클래스 제한 - 타입 파라미터를 대치하는 구체적인 타입으로 상위 타입이나 하위 타입만 올 수 있다.
- 제네릭 타입<? super 하위타입> : 하위 클래스 제한 - 타입 파라미터를 대치하는 구체적인 타입으로 하위 타입이나 상위 타입만 올 수 있다.
객체가 위 그림처럼 되어 있다면
- 제네릭 타입<?> : 수강생은 모든 타입(Person, Worker, Student, HighStudent)이 될 수 있다.
- 제네릭 타입<? extneds Student> : 수강생은 Studnet와 HightStudent만 될 수 있다.
- 제네릭 타입<? super Worker> : 수강생은 Worker와 Person만 될 수 있다.
public class Course <T>{
private String name;
private T[] students;
public Course(String name, int capacity) {
this.name = name;
this.students = (T[]) (new Object[capacity]);
}
public String getName() { return this.name; }
public T[] getStudents() { return this.students; }
public void add(T t) {
for (int i = 0; i < students.length; i++ ) {
if (students[i] == null ) {
students[i] = t;
break;
}
}
}
}
제네릭 타입의 상속과 구현
제네릭 타입도 다른 타입과 마찬가지로 부모 클래스가 될 수 있다.
public class ChildProduct<T, M> extends Prodct<T, M> { ... } // 상속만 받아 구현한 형태
public class ChildProduct<T, M, C> extends Prodct<T, M> { ... } // 상속만 받아 파라미터를 자식에서 추가한 형태
반응형
'개발(합니다) > Java&Spring' 카테고리의 다른 글
[java-기초-15] 컬렉션 프레임워크 (0) | 2021.02.22 |
---|---|
[java-기초-14] 람다식 (0) | 2021.02.14 |
[java-기초-12] 멀티 스레드 (5) | 2021.01.25 |
[java-기초-11-02] 기본 API 클래스 (2) | 2021.01.13 |
[java-기초-11-01] 기본 API 클래스 (4) | 2021.01.12 |