제네릭은 C++의 템플릿이 발전한 형태
C++과는 달리 제네릭 대신 Object를 사용하면 모든 데이터 타입을 사용할 수 있지만, 경우에 따라 형변환 해줘야 되서 제네릭을 선호
제네릭(Generic) : 일반화, 범용화 라는 의미로
클래스나 메서드에서 사용하는 필드나 매개변수의 자료형(클래스형)을 호출하는 쪽에서 지정하도록 하는 기능
package chapter20230831;
class ObjectData {
private Object data; // 클래스의 데이터 타입이 Object라서 모든 데이터 타입이 사용 가능
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
public class Generic {
public static void main(String[] args) {
ObjectData stringCommonData = new ObjectData();
ObjectData integerCommonData = new ObjectData();
stringCommonData.setData("abc"); // 클래스의 데이터 타입이 Object라서 모든 데이터 타입이 사용 가능
integerCommonData.setData(100);
System.out.println("stringCommonData : " + stringCommonData.getData()); // stringCommonData : abc
System.out.println("integerCommonData : " + integerCommonData.getData()); // integerCommonData : 100
}
}
package chapter20230831;
class CommonData<T> { // 일반적인 방식으로는 클래스에서 미리 데이터 타입을 지정해야 하지만 제네릭을 사용하면 호출하는 쪽에서 데이터 타입을
private T data; //데이터 타입으로 T를 지정 Type의 약자 클래스 선언에서 <> 사이에 다른 문자를 넣어도 됨
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
public class Generic2 {
public static void main(String[] args) {
CommonData<String> stringCommonData = new CommonData<String>(); // 호출하는 쪽에서 타입을 지정
CommonData<Integer> integerCommonData = new CommonData<>(); // 선언하면서 타입을 지정하면 생성자에는 타입을 생략가능
stringCommonData.setData("abc");
integerCommonData.setData(100);
System.out.println("stringCommonData : " + stringCommonData.getData()); // stringCommonData : abc
System.out.println("integerCommonData : " + integerCommonData.getData()); // integerCommonData : 100
}
}
GenericMethodTest
제네릭 타입 메서드 : 메서드에 타입 매개변수를 사용하여 선언한 것
매개변수로 사용하는 타입 매개변수를 반환값 앞에 선언
package chapter20230831;
class GenMethod {
public <K, V> boolean compare(K fKey, V fValue, K sKey, V sValue) {
if (fKey.equals(sKey) && fValue.equals(sValue)) {
return true;
}
return false;
}
}
public class Generic3 {
public static void main(String[] args) {
GenMethod genMethod = new GenMethod();
// 메서드의 호출시에는 객체.<클래스형들>메서드이름<매개변수들> 형식으로 사용하는데
// <클래스형들>은 생략가능 컴파일러가 매개변수로 필요한 타입을 추론
boolean check = genMethod.<Integer, String>compare(1, "홍길동", 1, "홍길동");
System.out.println("check : " + check); // true
}
}
MultipleGenericTypeTest
제네릭 타입 클래스 : 클래스의 객체를 생성할 때 매개변수를 사용해 특정 타입을 전달하여 이를 기반으로 클래스의 객체가 생성 및 작동하도록 지원하는 것.
어떤 문자를 사용해도 되나 미리 지정된 타입이 있음. 가급적 타입에 맞게 문자를 사용하는 것이 가독성을 높임.
E : Element의 약자. 컬레션 프레임워크를 사용할 때 각 객체를 지칭하는 의미로 사용.
K : Key의 약자. 키와 값이라는 쌍으로 이루어진 형태에서 '키'의 의미로 사용.
V : Value의 약자. 키와 값이라는 쌍으로 이루어진 형태에서 '값'의 의미로 사용.
T : Type의 약자. 자료형이나 클래스의 의미로 사용.
제네릭에서는 기본 자료형(boolean, byte, char, int등)을 타입으로 사용할 수 없어서 여기서는 래퍼 Wrapper 클래스를 의미.
N : Number의 약자. 수치 계열의 의미로 사용. 여러 개를 사용할 때 각 타입 매개변수 뒤에 2, 3, 4등의 숫자를 붙여 사용.
package chapter20230831;
class IntString {
private Integer key;
private String value;
public IntString(Integer key, String value) {
this.key = key;
this.value = value;
}
public void display() {
System.out.println("key: " + key + ", value: " + value);
}
}
class PairClass<K, V> { // 제네릭을 사용하지 않으면 위의 두개의 클래스를 따로 만들어야 하지만 제네릭을 사용하면 하나만 만들면 됨
private K key;
private V value;
public PairClass(K key, V value) {
this.key = key;
this.value = value;
}
public void display() {
System.out.println("key: " + key + ", value: " + value);
}
}
public class MultipleGenericType {
public static void main(String[] args) {
PairClass<Integer, String> pairClass1 = new PairClass<>(1, "홍길동");
PairClass<String, Double> pairClass2 = new PairClass<>("pi", 3.131592);
pairClass1.display(); // key: 1, value: 홍길동
pairClass2.display(); // key: pi, value: 3.131592
}
}