제네릭

kwang·2022년 7월 7일
0

Java-Live-Study

목록 보기
15/15

목표

자바의 제네릭에 대해 학습하세요.

학습할 것 (필수)

  • 제네릭 사용법
  • 제네릭 주요 개념 (바운디드 타입, 와일드 카드)
  • 제네릭 메소드 만들기
  • Erasure

제네릭 사용법

제네릭

클래스나 메서드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하여 일반화 하는 것을 의미한다.

장점

  • 컴파일 시 강한 타입 체크를 할 수 있다.
  • 타입 변환을 제거한다.

작성

   static class Champion  {
        Object passive;

        public Object getPassive() {
            return passive;
        }

        public void setPassive(Object passive) {
            this.passive = passive;
        }
    }

위의 코드는 Object 타입을 가지는 클래스이다. 이러한 클래스를 제네릭을 이용해서 바꿔보겠다.

   static class Champion <T> {
        T passive;

        public T getPassive() {
            return passive;
        }

        public void setPassive(T passive) {
            this.passive = passive;
        }
    }
    

보는거와 같이 Object가 T로 모두 치환되었다. T는 임의 참조형 변수로써 타입 변수라고 하며 실질적인 자료형을 나타내기보다 임의의 참조형 타입이라는 뜻이다.

//Object일 경우
	public static void main(String[] args) {
        Champion champion = new Champion();
        champion.setPassive("패시브");
        String str = (String) champion.getPassive();
        System.out.println(str);
    }
//제네릭 T일 경우
    public static void main(String[] args) {
        Champion<String> champion = new Champion<>();
        champion.setPassive("패시브");
        String str = champion.getPassive();
        System.out.println(str);
    }

위의 클래스를 둘다 실행해보면 getPassive()를 하는 과정에서 타입변환에 차이를 볼 수 있다. 이처럼 제네릭은 자동 타입변환이 된다는걸 확인할 수 있다.

제네릭 임의 참조형 변수

T : 타입
E : 요소(element,컬렉션에서 주로 사용된다)
K : 키
V : 값
N : 숫자
S, U, V : 두번째,세번째,네번째 선언된 타입

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

바운디드 타입(제한된 제네릭 클래스)

제네릭 타입에 extends 키워드를 사용하면 특정 타입의 자손들만으로 타입을 제한 할 수 있다.

class FruitBox<T extends Fruit> extends Box{
      
}

과일만 담을 수 있는 박스가 있을때 만약 과일이 아닌 다른 장난감과 같은 클래스를 담으려할때 타입제한을 할 수 있다.

와일드 카드

제네릭으로 구현된 메서드의 경우 선언된 타입으로만 매개변수를 입력해야 한다.

이와 상속관계에 있는 타입을 사용하려해도 불가능하다. 이러한 문제를 해결하는 것이 와일드 카드이다.

Unbounded WildCard
List<?> 와 같은 형태로 물음표를 이용해 정의하는 방법이다.
물음표는 내부적으로 Object로 정의되어 사용되어 모든 타입의 파라미터를 받을 수 있다.

Upper Bounded WildCard
List<? extends Parents>와 같은 형식으로 작성되며 보기와 같이 특정타입의 자식 클래스만 인자로 받을 수 있다.

Lower Bounded WildCard
List<? super Child>로 작성되며 특정 타입의 부모타입만 인자로 받겠다는 뜻이다.

제네릭 메소드 만들기

제네릭 메서드는 매개 타입과 리턴 타입으로 타입 파라미터를 갖는 메서드를 말한다.

제네릭 메서드를 선언하는 방법은 리턴 타입앞에 <>를 이용하여 타입 파라미터를 기술한 다음 리턴 타입과 매개 타입으로 사용하면 된다.

// 정의
public <타입파라미터> 리턴타입 메서드명(매개변수){

}

//사용하는 방법
리턴타입 변수 = <구체적인 타입>메서드명(매개값);
리턴타입 변수 = 메서드명(매개값);

아래는 boxing이라는 메서드를 만들었다. 코드를 보면 T타입을 전달받아 Box 객체의 Type에 대입하는 메서드이다.

메서드를 실행하는 부분을 보면 형변환없이 대입되는걸 확인할 수 있다.

public class Box<T> {
    T type;
    
    public T getType() {return type;}

    public void setType(T type) {this.type = type;}
}

// 제네릭메서드 정의하는 코드
public class Util {
    public static <T> Box<T> boxing(T t){
        Box<T> box = new Box<>();
        box.setType(t);
        return box;
    }
}
//실행하는 코드
public class Main {
    public static void main(String[] args) {
        Box<Integer> numBox = Util.boxing(10);
        int result = numBox.getType();

        Box<String> strBox = Util.<String>boxing("str");
        String str = strBox.getType();
    }
}

Erasure

Type Erasure

Type Erasure은 제네릭에 사용된 타입 파라미터들이 컴파일이 되는 과정에서 검증을 마치고 나면 필요가 없어지기에 런타임시 타입 파라미터를 지우는 것을 말한다.

// 런타임 전
public class Box<T> {
    T type;

    public T getType() {return type;
    }

    public void setType(T type) {
        this.type = type;
    }
}

// 런타임 시


public class Box {
    Object type;

    public Object getType() {return type;
    }

    public void setType(Object type) {
        this.type = type;
    }
}

타입파라미터 T가 Object로 변환되는 것을 볼 수있다. 이처럼 타입파라미터가 변환되는 것을 말한다.

0개의 댓글