본문 바로가기
Java/Java

[Java] 제네릭(Generics)

by 기록하는_사람 2022. 10. 18.

제네릭(Generics)

📌 제네릭(Generics)

: 일반화.

  자바에서는 '자료형'이 그 대상임.

class Box<T> {
	...
}

 

📌 제네릭(Generics) 사용 이유

: 저장된 인스턴스를 사용할 때 형 변환을 하는데, 이때 실수로 오류가 발생할 수 있으며, 그 실수가 드러나지 않을 수 있음. → 위 상황의 불편함을 줄이기 위해 제네릭(Generics)이 등장함.

자료형에 의존적이지 않은 클래스 정의 가능해짐. 

 

📌 자료형에 의존하지 않기 위해 Object 대신 T 사용.

     T는  인스턴스 생성 시, 결정됨.

     T의 역할을 알려주기 위해 클래스 이름 뒤에 <T> 붙임.

 

📌 용어

① 타입 매개변수(Type Parameter) 

: Box<T>에서 T.

② 타입 인자(Type Argument)

: Box<Apple> boxA = new Box<Apple>( ); 에서 Apple.

③ 매개변수화 타입(Parameterized Type) = 제네릭 타입(Generic Type)

: Box<Apple>.

class Apple {
	...
}

class Box<T> {
	...
}

public class GenericsTest {

	public static void main(String[] args) {
		Box<Apple> boxA = new Box<Apple>();
		...
	}

}

 

📌 타입 매개변수 이름 규칙

한 문자.

② 대문자.

E Element
K Key
N Number
T Type
V Value

 

제네릭(Generics) - 에시

📌 제네릭(Generics) 예시

📄 GenericsTest.java

package generics;

class Apple {
	public String toString() {
		return "apple";
	}
}

class Banana {
	public String toString() {
		return "banana";
	}
}

class Box<T> {  // 제네릭 기반의 클래스. 
	private T ob;
	
	public void set(T o) {
		ob = o;
	}
	
	public T get() {
		return ob;
	}
}

public class GenericsTest {

	public static void main(String[] args) {
		Box<Apple> boxA = new Box<Apple>();
		Box<Banana> boxB = new Box<Banana>();
		
		boxA.set(new Apple());
		boxB.set(new Banana());
		
		Apple a = boxA.get();
		Banana b = boxB.get();
		
		System.out.println(a.toString());  // apple
		System.out.println(b.toString());  // banana
	}

}

 

제네릭(Generics) - 매개변수화 타입

📌 매개변수화 타입을 구성할 때 기본 자료형을 타입 인자로 쓸 수 없음. 

단, 기본 자료형에 대한 래퍼 클래스가 존재하고, 박싱과 언박싱이 자동으로 이루어지기 때문에 

아래와 같은 코드 작성 가능. 

 

📄 WrapperTest.java

package generics;

class Box<T> {  // 제네릭 기반의 클래스. 
	private T ob;
	
	public void set(T o) {
		ob = o;
	}
	
	public T get() {
		return ob;
	}
}

public class WrapperTest {
	public static void main(String[] args) {
    	// Box<int> box = new Box<int>();  // 타입 인자로 기본 자료형 사용 불가. 
        Box<Integer> box = new Box<Integer>();
        
        box.set(10);  // 오토 박싱.
        int num = box.get();  // 오토 언박싱.
        
        System.out.println(num);  // 10
	}
}

 

제네릭(Generics) - 타입 인자

📌 다이아몬드(Diamond) 기호

: 타입 인자 생략. 

class Box<> {
	...
}

 

📌 매개변수화 타입을 타입 인자로 사용 가능. 

📄 BoxInBox.java

package generics;

class Box<T> {  // 제네릭 기반의 클래스. 
	private T ob;
	
	public void set(T o) {
		ob = o;
	}
	
	public T get() {
		return ob;
	}
}

public class BoxInBox {

	public static void main(String[] args) {
		Box<String> b1 = new Box<>();
		b1.set("Hello");
		
		Box<Box<String>> b2 = new Box<>();
		b2.set(b1);
		
		Box<Box<Box<String>>> b3 = new Box<>();
		b3.set(b2);
		
		System.out.println(b3.get().get().get());  // Hello
	}

}

 

📌 타입 인자 제한

: extends

 

① 클래스.

: 인스턴스 생성 시 설정한 클래스 또는 그 클래스를 상속하는 클래스만 타입 인자로 사용 가능. 

class Box<T extends Number> {
	...
}

 

② 인터페이스.

interface Sumable {
	...
}

class Box<T extends Sumable> {
	...
}

 

③ 클래스와 인터페이스 동시에 제한 가능.

interface Sumable {
	...
}

class Box<T extends Number & Sumable> {
	...
}

 

제네릭(Generics) 메소드

📌 제네릭(Generics) 메소드

: 제네릭(Generics)으로 정의된 메소드.

  static 선언의 유무에 상관없이 정의 가능. 

 

📌 static과 반환형 사이에 T가 타입 매개변수임을 알려야 함. 

public static <T> Box<T> makeBox(T o) {
	...
}

 

📌 메소드 호출 시 자료형이 결정됨. 

 

📌 타입 매개변수 제한

: extends로 타입 매개변수 제한 가능. 

 

제네릭(Generics) 인터페이스

📌 제네릭(Generics) 인터페이스

: 제네릭(Generics)으로 정의된 인터페이스. 

 

제네릭(Generics) 상속

📌 제네릭(Generics) 클래스는 상속이 가능함.

 

'Java > Java' 카테고리의 다른 글

[Java] 컬렉션 프레임워크 - List<E> 인터페이스  (0) 2022.10.18
[Java] 와일드카드(Wildcard)  (0) 2022.10.18
[Java] Array 클래스  (0) 2022.10.17
[Java] StringTokenizer 클래스  (0) 2022.10.17
[Java] Math 클래스와 난수 생성  (0) 2022.10.17

댓글