자바

13.5  제한된 타입 파라미터 (<T extends 최상위타입>)

타입 파라미터에 지정되는 구체적인 타입을 제한할 필요가 종종 있다. 예를 들어 숫자를 연산하는 제네릭 메소드는 매개값으로 Number 타입 또는 하위 클래스 타입(Byte, Short, Integer, Long, Double) 의 인스턴스만 가져야 한다. 이것이 제한된 타입 파라미터 ( bounded type parameter)  가 필요한 이유이다. 제한된 타입 파라미터를 선언하려면 타입 파라미터 뒤에 extends  키워드를 붙이고 상위 타입을 명시하면 된다. 상위 타입은 클래스뿐만 아니라 인터페이스도 가능하다. 인터페이스라고 해서  implements  를 사용하지 않는다.

 

public <T extends 상위타입> 리턴타입 메소드(매개변수, ...) {...}

 

타입 파라미터에 지정되는 구체적인 타입은 상위 타입이거나 상위 타입의 하위 또는 구현 클래스만 가능하다. 주의할 점은 메소드의 중괄호 {} 안에서 타입 파라미터 변수로 사용 가능한 것은 상위 타입의 멤버(필드, 메소드) 로 제한된다. 하위 타입에만 있는 필드와 메소드는 사용할 수 없다. 다음은 숫자 타입만 구체적인 타입으로 갖는 제네릭 메소드 compare() 이다. 두 개의 숫자 타입을 매개값으로 받아 차이를 리턴한다.

 

public class Util {
    public static <T extends Number> int compare(T t1, T t2){
        double v1 =t1.doubleValue();
        double v2 =t2.doubleValue();
        return Double.compare(v1, v2);
    }
}
 

public class BoundedTypeParameterExample {
    public static void main(String[] args) {
        
        //String str =Util.compare("a", "b"); (x) String 은 Number타입이 아님
        int result1 =Util.compare(10, 20);
        System.out.println(result1);
        
        int result2 =Util.compare(4.5, 3);
        System.out.println(result2);
    }
}
 

13.6 와일드카드 타입 (<?>, <? extends ...>, <? super ...> )

코드에서 ? 를 일반적으로 와일드카드(wildcard) 라고 부른다. 제네릭 타입을 매개값이나 리턴 타입으로 사용할 때 구체적인 타입 대신에 와일드카드를 다음과 같이 세 가지 형태로 사용할 수 있다.

제네릭타입<?> :Unbounded WildCards(제한없음)

타입 파라미터를 대치하는 구체적인 타입으로 모든 클래스난 인터페이스 타입이 올 수 있다.

제네릭타입<? extends 상위타입> : Upper Bounded Wildcards(상위 클래스 제한)

타입 파라미터를 대치하는 구체적인 타입으로 상위 타입이나 하위 타입만 올 수 있다.

제네릭타입<? super 하위타입> Lower Bounded  Wildcards (하위 클래스 제한)

타입 파라미터를 대치하는 구체적인 타입으로 하위 타입이나 상위 타입이 올 수 있다.

 

설명만으로 잘 이해가 되지 않을 것 같다. 다음 코드를 보면서 이해해보자. 제테릭 타입 Course는 과정 클래스로 과정 이름과 수강생을 저장할 수 있는 배열을 가지고 있다. 타입 파라미터 T가 적용된 곳은 수강생 타입 부분이다.

 

public class Course<T> {

    private String name;
    private T[] students;
    
    public Course(String name, int capacity){
        this.name=name;
        students =(T[])(new Object[capacity]);
    }
    
    public String getName(){return name; }
    public T[] getStudents() { return students; }
    public void add(T t){
        for(int i=0; i<students.length; i++){
            if(students[i] ==null){
                students[i] =t;
                break;
            }
        }
    }
}
 

수강생이 될 수 있는 타입은 다음 5가지 클래스라고 가정하자. Person 의 하위 클래스로 Worker 와 Students 가 있고,  Student의 하위 클래스로 HighStudent  가 있다.

Course<?>

- 수강생은 모든 타입 (Person, Worker, Student, HighStudent, Dog) 이 될 수 있다.

 

Course<? extends Student>

- 수강생은 Student 와 Person만 될 수 있다.

 

Course <? super Worker>

- 수강생은 Worker 와 Person만 될 수 있다.

 

다음 예제는 registerCourseXXX() 메소드의 매개값으로 와일드카드 타입을 사용하였다.

registerCourse() 는 모든 수강생이 들을 수 있는 과정을 등록하고, registerCourseStudent() 는 학생만 들을 수 있는 과정을 등록한다. 그리고 registerCourseStudent() 는 학생만 들을 수 있는 과정을 등록한다. 그리고 registerCourseWorker 는 직장인만 들을 수 있는 과정을 등록한다.

 

13. 7 제네릭 타입의 상속과 구현

제네릭 타입도 다른 타입과 마찬가지로 부모 클래스가 될 수 있다. 다음은 Product<T, M>제네릭 타입을 상속해서 ChildProduct<T, M>타입을 정의한다. 

public class ChildProduct<T, M> extends Product<T, M> {....}

자식 제네릭 타입은 추가적으로 타입 파라미터를 가질 수 있다. 다음은 세 가지 타입 파라미터를 가진 자신 제네릭 타입을 선언한 것이다.

 

public class Prodcut<T, M> {
    
    private T kind;
    private M model;
    public T getKind() {
        return kind;
    }
    public void setKind(T kind) {
        this.kind = kind;
    }
    public M getModel() {
        return model;
    }
    public void setModel(M model) {
        this.model = model;
    }
}
 

 

 

about author

PHRASE

Level 60  머나먼나라

목구멍이 포도청 , 먹고 살기 위하여 차마 못할 짓까지 함을 이르는 말.

댓글 ( 4)

댓글 남기기

작성

자바 목록    more