제네릭(Generic)
데이터 타입을 일반화 시키는 방법
클래스, 인터페이스, 메소드 등에서 사용될 수 있는 타입 매개변수 (parameter)
< > 를 사용하여 정의한다.
제네릭을 사용하는 이유
- 컬렉션의 안정성을 보장하기 위해 사용한다.
- < >안에 데이터 타입을 명시하여 타입을 제한함으로써 안정성을 보장할 수 있다. (타입 안정성 보장)
- 클래스, 인터페이스, 메소드에 < > 지정 가능.
- 예를 들어 <String>으로 지정하면 String 타입만 들어올 수 있어 다른 데이터 타입 유입을 막는다.
- < >안에 데이터 타입을 명시하여 타입을 제한함으로써 안정성을 보장할 수 있다. (타입 안정성 보장)
- 재사용성이 높아진다.
- 제네릭 타입을 선언할 때, 어떤 데이터 타입이 들어올지 결정하지 않으므로, 다양한 데이터 타입에 대해 일반적으로 적용할 수 있는 메서드나 클래스를 작성할 수 있다.
- <T> : 가변 타입(T)를 사용하여 임의로 설정해두고 실행될 때 실행되는 데이터 타입으로 대입한다. (유연성 증대)
제네릭 배열 생성 방법
1. 배열을 먼저 생성 후,
2. 사용하고자 하는 데이터 타입으로 형변환 진행.
public ObjectArr(int size){
array = (T[])new Object[size];
}
제네릭 멀티 타입 파라미터
제네릭 타입에는 여러 개의 파라미터를 넣을 수 있다. 멀티 타입 파라미터는 Key, Value 형태로 사용하게 된다. 대표적인 예로 컬렉션의 Map 구조가 제네릭의 멀티 타입 파라미터를 사용한다.
Map <K, V> => K : key, V : value
- K는 key의 타입
- V는 value의 타입
public class Pair<K, V> {
private K key; //임의의 타입 지정
private V value; //임의의 타입 지정
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public void setKey(K key) {
this.key = key;
}
public void setValue(V value) {
this.value = value;
}
}
=========================================================================
public class PairGenericTest {
public static void main(String[] args) {
Pair<String, Integer> pair = new Pair<>("hello", 1); //키 타입 : String, 값 타입 : Integer
System.out.println(pair.getKey()); //hello
System.out.println(pair.getValue()); //1
//검색을 빠르게 할 수 있는 자료구조 -> (hash계열의 자료구조 : hashMap, hashtable)
Map<String, Integer> maps = new HashMap<>();
maps.put("kor", 60);
maps.put("eng", 70);
maps.put("mat", 80);
System.out.println(maps.get("kor")); //60
System.out.println(maps.get("eng")); //70
System.out.println(maps.get("mat")); //80
}
}
제네릭 제한된 타입 파라미터
제네릭은 타입 파라미터를 제한할 수 있다. < > 안에 타입을 지정 시, extends 키워드를 활용하여 부모로부터 상속 받는 타입만으로 제한하도록 설정할 수 있다.
Example <T extends Number>{ }
- T 타입은 Number 클래스의 하위 클래스들만 지정할 수 있음.
- 그 이외의 타입이 들어오면 컴파일 오류가 발생한다.
public class AverageCalculator<T extends Number> { //Number 클래스 하위 클래스만 타입으로 지정 가능. (제네릭 타입 제한)
private T[] numbers;
public AverageCalculator(T[] numbers) {
this.numbers = numbers;
}
public double calculatorAverage(){
double sum = 0.0;
for(T number : numbers){
sum += number.doubleValue();
}
return sum / numbers.length;
}
}
==============================================================================================
public class GenericLimitTest {
public static void main(String[] args) {
Integer[] integers = {1,2,3,4,5};
Double[] doubles = {1.0,2.0,3.0,4.0,5.0};
AverageCalculator<Integer> integerCalculator = new AverageCalculator<>(integers);
double integerAvg = integerCalculator.calculatorAverage();
System.out.println(integerAvg); //3.0
AverageCalculator<Double> doubleCalculator = new AverageCalculator<>(doubles);
double doubleAvg = doubleCalculator.calculatorAverage();
System.out.println(doubleAvg); //3.0
//String 타입은 Number 클래스의 하위 클래스가 아니기 때문에 지정불가 (제네릭 제한)
//AverageCalculator<String> stringCalculator = new AverageCalculator<>();
}
}
'JAVA' 카테고리의 다른 글
클래스란? (0) | 2024.03.19 |
---|---|
Java 개발 환경의 이해 (0) | 2024.03.15 |