| 제네릭이란?
[사전] Generic = 일반적이다
[정의] 하나의 코드로 여러 타입을 동시에 처리하는 기술
1. 타입 변수 표기법
- 제네릭에 지정하는 타입 변수 이름은 지정하는 사람의 마음이지만,
적어도 그 타입 이름을 사용하는 클래스 또는 인터페이스 내에서는 통일성있게 사용하게 한다.
- 일반적으로 변수명과의 구분을 위해 한 개의 대문자로 표시하는 것이 관례이다.
- 타입 매개 변수는 기초 자료형으로 객체화될 수 없다.
T | Type |
E | Element(요소) |
N | Number |
K | Key |
V | Value |
S,U,V..... |
2. 제네릭 클래스
- 최상위 클래스 Object를 사용하면 어떤 타입의 인스턴스건 참조할 수 있다. (업캐스팅, 다형성)
- 이러한 원리를 이용해서 클래스를 작성할때 데이터 타입을 Object로 하면 여러 타입의 데이터를 담을 수 있게 된다.
public class Box {
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
- 다만, 이럴 경우, 아래와 같이 객체 안의 데이터를 가져올 때 형변환이 불가피하게 된다.
import LibraryPractice.MyClass.Box;
public class GenericTest {
public static void main(String[] args) {
Box box = new Box();
box.setData(123);
int x = (Integer)box.getData(); //cast(형변환)필요
}
}
- 이럴 때 제네릭을 사용하여 미리 타입을 지정한다면 사용시의 형변환의 번거러움을 줄일 수 있게 된다.
public class Box<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
import LibraryPractice.MyClass.Box;
public class GenericTest {
public static void main(String[] args) {
Box<Integer> box = new Box<>();
box.setData(123);
int x2 = box.getData(); // 형변환 필요 없음
}
}
- 만약에 여러 개의 맴버변수에 서로다른 제네릭을 지정해야하는 경우(ex. key와 value가 타입이 다른 경우), 아래와 같이 작성할 수 있다.
public class Box3<K, V> {
private K key;
private V value;
public void setData(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey(V key) {
return this.key;
}
public V getValue(K key) {
return this.value;
}
}
3. 제네릭 메소드
- 제네릭 메소드의 경우 아래와 같이 반환타입 앞에 <E> 와 같은 형식으로 작성을 해준다.
public class Basket<T> {
T data;
public Basket(T data){
this.data = data;
}
// 외부 배열 print
public <E> void print(E[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
- 만약에 타입 변수를 특정 타입(예를 들어 String)으로 제한하고 싶은 경우, 아래와 같이 사용할 수 있다.
public <E extends String> 반환타입 method(E item){
/* 생략 */
}
[ 제네릭 메소드로 만든 코드 ]
import java.util.ArrayList;
import java.util.Arrays;
public class Basket2<T> {
private ArrayList<T> basket;
public Basket2(T[] arr) {
this.basket = new ArrayList<T>(Arrays.asList(arr));
}
public <E extends String> void printWithOwner(E str) { // E를 String으로 제한
if (str.length() == 0) {
System.out.println("please type Owner Name");
return;
}
StringBuffer sb = new StringBuffer();
sb.append(str + " : ");
for (int i = 0; i < basket.size(); i++) {
if (i != basket.size() - 1) {
sb.append(basket.get(i) + ", ");
}else{
sb.append(basket.get(i));
}
}
System.out.println(sb);
}
}
import LibraryPractice.MyClass.Basket2;
public class GenericTest2 {
public static void main(String[] args) {
String owner = "sir.Tim Berners-Lee";
String[] fruit = {"apple", "orange", "dragon fruit"};
Basket2<String> basket = new Basket2<>(fruit);
basket.printWithOwner(owner);
}
}
>> 결과
sir.Tim Berners-Lee : apple, orange, dragon fruit
'Language > Java' 카테고리의 다른 글
SOLID 원칙 (0) | 2022.08.29 |
---|---|
JAVA 라이브러리 - 컬렉션 (0) | 2022.08.11 |
JAVA 라이브러리 - 날짜, 시간 관련 클래스(java.util/java.time..) (0) | 2022.08.10 |
JAVA 라이브러리 - Java.lang 패키지 (0) | 2022.08.08 |
객체지향 언어의 특징 4_캡슐화 (정보 은닉) (0) | 2022.07.22 |