티스토리 뷰

Java

Java - 제네릭 2

gyeonghyun 2024. 6. 13. 20:08

타입 매개변수 제한

 

제네릭에서 타입 매개변수를 사용하면 어떤 타입이든 들어올 수 있다.

 

이런 상황에서 자바에서는 타입 매개변수를 특정 타입으로 제한 할 수 있다.

 

package generic.ex3;
import generic.animal.Animal;
public class AnimalHospitalV3<T extends Animal> {
    private T animal;
    public void set(T animal) {
        this.animal = animal;
    }
    public void checkup() {
        System.out.println("동물 이름: " + animal.getName());
        System.out.println("동물 크기: " + animal.getSize());
        animal.sound();
    }
    public T getBigger(T target) {
        return animal.getSize() > target.getSize() ? animal : target;
    }
}

 

핵심은 <T extends Animal> 이다.

타입 매개변수 T를 Animal과 그 자식만 받을 수 있도록 제한을 두는 것이다. 즉 T 의 상한이 Animal이 되는 것이다.

 

결론

제네릭에 타입 매개변수 상한을 사용해서 타입 안정성을 지키면서 상위 타입의 원하는 기능까지 사용할 수 있다.

이렇게 코드 재사용과 타입 안정성이라는 두 마리 토끼를 잡을 수 있다.

 

 

제네릭 메서드

제네릭 타입과 지금부터 살펴볼 제네릭 메서드는 둘다 제네릭을 사용하기는 하지만 서로 다른 기능을 제공한다.

 

package generic.ex4;
public class GenericMethod {
 public static Object objMethod(Object obj) {
 System.out.println("object print: " + obj);
 return obj;
 }
 public static <T> T genericMethod(T t) {
 System.out.println("generic print: " + t);
 return t;
 }
 public static <T extends Number> T numberMethod(T t) {
 System.out.println("bound print: " + t);
 return t;
 }
}

 

package generic.ex4;
public class MethodMain1 {
 public static void main(String[] args) {
 Integer i = 10;
 Object object = GenericMethod.objMethod(i);
 // 타입 인자(Type Argument) 명시적 전달
 System.out.println("명시적 타입 인자 전달");
 Integer result = GenericMethod.<Integer>genericMethod(i);
 Integer integerValue = GenericMethod.<Integer>numberMethod(10);
 Double doubleValue = GenericMethod.<Double>numberMethod(20.0);
 }
}

 

 

제네릭 타입

정의 : GenericClass<T>

타입 인자 전달 : 객체를 생성하는 시점  (ex : new GenericClass<String>

 

제네릭 메서드

정의 : <T> T genericMethod(T t)

타입 인자 전달 : 메서드를 호출하는 시점 (ex : GenericMethod.<Integer>genericMethod(i)

 

제네릭 메서드는 클래스 전체가 아니라 특정 메서드 단위로 제네릭을 도입할 때 사용한다.

제네릭 메서드를 정의할 때는 메서드의 반환 타입 왼쪽에 다이아몬드를 사용해서 <T>와 같이 타입 매개변수를 적어준다.

제네릭 메서드는 메서드를 실제 호출하는 시점에 다이아몬드를 사용해서 <Integer>와 같이 타입을 정하고 호출한다.

 

제네릭 메서드의 핵심은 메서드를 호출하는 시점에 타입 인자를 전달해서 타입을 지정하는 것이다. 따라서 타입을 지정하면서 메서드를 호출한다.

 

인스턴스 메서드,static 메서드

제네릭 메서드는 인스턴스 메서드와 static 메서드에 모두 적용할 수 있다.

class Box<T> { //제네릭 타입
 static <V> V staticMethod2(V t) {} //static 메서드에 제네릭 메서드 도입
 <Z> Z instanceMethod2(Z z) {} //인스턴스 메서드에 제네릭 메서드 도입 가능
}

 

참고

제네릭 타입은 static메서드에 타입 매개변수를 사용할 수 없다. 제네릭 타입은 객체를 생성하는 시점에 타입이 정해진다.

그런데 static메서드는 인스턴스 단위가 아니라 클래스 단위로 작동하기 때문에 제네릭 타입과 무관하다.

따라서 static 메서드에 제네릭을 도입하려면 제네릭 메서드를 사용해야 한다.

 

class Box<T> {
 T instanceMethod(T t) {} //가능
 static T staticMethod1(T t) {} //제네릭 타입의 T 사용 불가능
}

 

 

타입 매개변수 제한

제네릭 메서드도 제네릭 타입과 마찬가지로 타입 매개변수를 제한할 수 있다.

public static <T extends Number> T numberMethod(T t) {}
//GenericMethod.numberMethod("Hello"); // 컴파일 오류 Number의 자식만 입력 가능

 

 

 

제네릭 메서드 타입 추론

제네릭 메서드를 호출할 때 <Integer>와 같이 타입 인자를 전달하는 것은 매우 불편하다.

Integer i = 10;
Integer result = GenericMethod.<Integer>genericMethod(i);

 

자바 컴파일러는 genericMethod()에 전달되는 인자 i의 타입이 Integer라는 것을 알 수 있다.

또한 반환 타입이 Integer result라는 것도 알 수 있다. 이런 정보를 통해 자바 컴파일러는 타입 인자를 추론할 수 있다.

 

//타입 추론, 타입 인자 생략
System.out.println("타입 추론");
Integer result2 = GenericMethod.genericMethod(i);
Integer integerValue2 = GenericMethod.numberMethod(10);
Double doubleValue2 = GenericMethod.numberMethod(20.0);

 

 

'Java' 카테고리의 다른 글

Java - 데이터 정렬 1 (Comparable,Comparator)  (0) 2024.06.18
Java - 와일드 카드  (1) 2024.06.13
Java - 제네릭 1  (0) 2024.05.26
Java - 예외 처리  (0) 2024.05.20
Java - 중첩 클래스 내부 클래스 - 3  (0) 2024.05.09
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함