1.10 < ? >

yeonseong Jo·2023년 5월 1일
0

SEB_BE_45

목록 보기
17/47
post-thumbnail

변수를 선언 할 때
매번 type을 지정해야 하고,
변수의 type을 신경 써 줘야 하는
자바는 정적 타입 언어이다.

하지만 class에서 받을 매게변수에 대한
type을 미리 지정하지 않고 받을 수 있는 방법이 있다.
바로 generic


Generic

generic은 class 설계 시
매개변수의 type을 후에 지정할 수 있게 하는 keyword이다.

특징

class Test<T> {
	T item;
    public Test(T item){
    	this.item = item;
    }
}

위와 같이 class 변수명 뒤에 있는 꺽쇠(< >) 사이에
추후 type을 지정할 매개변수의 type을 임시로 넣어
(위의 경우 T)
선언이 가능하다.
또한, 꺽쇠 사이에는 여러개의 type을 넣을 수 있다.

class Main{
	public static void main(String[] args){
    	Test<Integer> t = new Text<>(10);
    }
}

사용할 때에는 위와 같이 사용한다.
이 사용법을 어디서 많이 봤다 싶었는데,
바로 ArrayList의 변수 선언이었다.

ArrayList<Integer> list = new ArrayList<>()

뭐 여튼
generic을 적용한 class 선언 때 주의점이 하나 있는데
당연하다면 당연한거지만,
static keyword를 사용할 수 없다.


제한된 generic class

일반적으로
generic을 사용하면 객체를 인스턴스화 할 때
제한 없이 아무 타입이나 지정 가능하다.

하지만,
generic class를 선언할 때 extends keyword를 사용하면,
type에 제한을 둘 수 있다.

class Parent{}
class Child extends Parent{}
class Nobody{}

class Test<T extends Parent> {
	T item;
    public Test(T item){
    	this.item = item;
    }
}

class Main{
	public static void main(String[] args){
    	Test<Parent> t1 = new Test<>();
        Test<Child> t2 = new Test<>();
        // Test<Nobody> t3 = new Test<>();  err
    }

물론 interface로도 제한이 가능하다.

interface Inter{}
class Parent{}
class Test<T extends Parent & Inter {
	...
}

&로 확장이 가능하고, class와 interface를 동시에 제한할 때
class는 interface보다 앞에 위치해야 한다.


generic method

일반적으론 의 경우 처럼
class 전체를 generic으로 선언하지만,
어느 class의 특정 method만
generic으로 선언도 가능하다.

class Test<T>{
	T t;
    
    public Test(T t){
    	this.t = t;
    }
    
	static public <T> void test(T t){
    	...
    }
}

위의 경우 class에 T type을,
method에도 T type을 받는데,
method 내에서 class변수와
같은 이름의 변수를 선언해도 상관 없는 것 처럼
(클래스 변수 != 지역 변수)
type 명이 똑같더라도, 별개의 type인 것이다.

또한, method에 static keyword 사용이 가능하다.


wildcard

method에서 generic한 매개변수를 받을 때
변수의 type의 범위를 제한 하는 방법도 있다.

?라는 wildcard keyword를 써서 사용하며
3가지 범위는

class Test {
	void testPrint1(ArrayList<?> arrayList){
    	...
    }
    void testPrint2(ArrayList<? super String> arrayList){
    	...
    }
    void testPrint3(ArrayList<? extends String> arrayList){
    	...
    }
}

위에서 부터 차례대로

?

  • type의 제한 없이 사용 가능

? super String

  • 하한 경계 wildcard
  • String의 상위(String 포함) class만 사용 가능

? extends String

  • 상한 경계 wildcard
  • String의 하위(String 포함) class만 사용 가능

회고

wildcard에 대해 이해하려고
혼자 실험을 했는데,
실험 설계(?)를 잘못해서 엄청난 고뇌에 빠졌었다...
다행히 GPT에 해당 실험이 왜 잘못되었는지 물어보면서
오류를 알게 되었고, 다시 실험을 요청해서
잘 이해하게 되었다.

profile
뒤(back)끝(end)있는 개발자

0개의 댓글