본문 바로가기
Study/Java_study

Java_study_14 (제네릭)

by hjshims 2021. 9. 20.

♨학습내용

더보기

 제네릭 사용법

제네릭 주요 개념 (바운디드 타입, 와일드 카드)

제네릭 메소드 만들기

Erasure

 

  • 제네릭 사용법
  • 제네릭 이란?

- 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법이다.

- 제네릭은 중복 코드의 제거를 위해 자바 5부터 나왔다. 

- 객체의 타입을 컴파일 시에 체크해 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어든다.

 

- 제네릭 장점

1. 타입 안정성을 제공한다.

2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해진다.

 

  • 제네릭 사용법

- 제네릭 타입(class<T>, interface<T>)

- 타입을 파라미터로 가지는 클래스와 인터페이스이다.

- 클래스 or 인터페이스 뒤에 '<>' 부호가 붙고, 사이에 타입 파라미터가 위치한다.

- 일반적으로 타입 파라미터는 대문자 알파벳 한 글자로 표현한다.

- 타입의 매개변수의 이름은 아무거나 들어가도 상관없지만, 공식문서의 Name Convention을 따르는 게 좋습니다.

 

public class 클래스명<T> {

}

public interface 인터페이스명<T> {

}

 

  • E : 주로 자바 Collection framework에 사용되는 Element
  • K : map에서 매개변수로 사용되는 Key
  • V : map에서 매개변수로 사용되는 Value
  • N : 숫자를 나타내는 Number
  • T : 일반적으로 사용하는 제네릭 Type
  • S : 두번째로 사용하는 일반 제네릭 Type
  • U : 세번째로 사용하는 일반 제네릭 Type
  • V : 네번째로 사용하는 일반 제네릭 Type

 

 

  • 멀티 타입 파라미터(class<K, V, ...>, interface<K, V, ...>)

- 제네릭 타입은 두 개 이상의 멀티 타입 파라미터를 가질 수 있다.

 

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

 


 

 

  • 제네릭 주요 개념 (바운디드 타입, 와일드 카드)
  • 바운디드 타입

- 바운디드 타입 매개변수는 특정 타입의 서브타입으로 제한하는 것을 말한다.

- 클래스, 인터페이스, 메소드를 제네릭으로 작성할 때, 타입 변수를 제한하기 위해서는 Bounded Type으로 선언해야한다.
- <T extends 상위타입> 으로 타입변수를 지정하여 상위타입의 하위클래스로만 제한할 수 있다.

 

public class Example {
    public static void main(String[] args) {

        // bounded 내의 타입이 아니여서 컴파일 오류 발생
        // BoundedGeneric<String> boundedGeneric = new BoundedGeneric<String>();

        BoundedGeneric<Integer> boundedGeneric = new BoundedGeneric<>();
        boundedGeneric.setT(Integer.valueOf(10));
        boundedGeneric.print();

    }
}

class BoundedGeneric<T extends Number>{
    T t;

    public void print(){
        System.out.println(t);
    }

    public void setT(T t){
        this.t = t;
    }
}

 

 

  • 와일드 카드

- 제네릭에서 와일드 카드는 <?>로 나타내며 알 수 없는 유형을 나타낸다.

- 와일드 카드는 파라미터 변수, 필드, 지역변수의 타입 그리고 리턴 타입에도 사용될 수 있다.

- 그러나 와일드 카드는 제네릭 메소드 호출, 제네릭 클래스 인스턴스 생성 또는 수퍼 타입의 타입 인자로는 사용될 수 없다.

 

import java.util.Arrays;
import java.util.List;

public class Example {

    public static double sum(List<? extends Number> numberlist){
        double sum = 0.0;

        for(Number n : numberlist){
            sum+=n.doubleValue();
        }
        return sum;
    }
    public static void main(String[] args) {
        List<Integer> integerList = Arrays.asList(3, 6, 9);
        System.out.println("sum : "+sum(integerList));      // 18.0

        List<Double> doubleList = Arrays.asList(3.3, 6.6, 9.9);
        System.out.println("sum : "+sum(doubleList));       // 19.8

    }
}

 

  • 제네릭타입<?> : Unbounded Wildcards(제한없음) 
    • 타입 파라미터를 대치하는 구체적인 타입으로 모든 클래스나 인터페이스 타입이 올 수 있다.
  • 제네릭타입<? extends 상위타입> : Upper Bounded Wildcards(상위클래스 제한)
    • 타입 파라미터를 대치하는 구체적인 타입으로 상위 타입이나 하위 타입만 올 수 있다.
  • 제네릭타입 <? super 하위타입> : Lower Bounded Wildcards (하위클래스 제한)
    • 타입 파라미터를 대치하는 구체적인 타입으로 하위 타입이나 상위 타입이 올 수 있다.

 

 

 


 

 

  • 제네릭 메소드 만들기

- 클래스가 전부가 아닌 메서드 하나에 대해 제네릭으로 정의할 수 있다.

class BoxFactory {
	public <T> Box<T> makeBox(T o) {
		Box<T> box = new Box<T>();
		box.set(o);
		return box;
	}
}

 

- 제네릭 클래스는 인스턴스 생성 시 타입 인자를 결정하지만
- 제네릭 메서드는 메서드 호출 시점에 결정한다.

 

Box<String> sBox = BoxFactory.<String>makeBox("Hello");
Box<Double> dBox = BoxFactory.<Double>makeBox(3.69);

 

- 다음과 같이 타입 인자 생략이 가능하다.

 

Box<String> sBox =  BoxFactory.makeBox("Hello");
Box<Double> dBox = BoxFactory.makeBox(3.69);

 

- double의 경우 wrapper클래스 Double형으로 오토박싱이 진행된다.

- 제네릭 메서드는 메서드 호출 시 전달되는 인자의 자료형을 근거로 판단한다.

 

 


 

 

  • Erasure

- 자바는 하위 호환성을 지키기 위해 타입 소거를 만들었다.

- 제네릭의 타입 소거는 원소 타입을 컴파일 시기에만 검사하고 런타임에는 해당 타입의 정보를 알 수 없다는 개념이다.

- 이러한 개념이 나온 이유는, 제네릭 개념을 도입한 이후로 이전 버전의 자바와의 하위 호환성때문이다.

 

- Non-Reifiable Type 런타임에 타입 정보의 유무에 따라 타입을 나누는 개념이다.

  • Refiable type : 런타임에 타입에 대한 정보를 가지고 있다.
    primitive, non - generic, unbounded wildcards (<?>) 등 이 있다.
  • Non - Reifiable type : 런타임에 타입에 대한 정보가 없다.
    type erasure 가 진행되는 대부분의 generic parameterized type 이 있다.

 

 

'Study > Java_study' 카테고리의 다른 글

Java_study_15 (람다식)  (0) 2021.09.27
Java_study_13 (I/O)  (0) 2021.09.20
Java_study_12 (애노테이션)  (0) 2021.09.14
Java_study_11 (Enum)  (0) 2021.09.07
Java_study_10 (멀티쓰레드 프로그래밍)  (0) 2021.08.30