19.04.17 제네릭,와일드카드

Back-End/Java 2019. 4. 17. 17:47
728x90
반응형


-제네릭의 사용-


제네릭은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법.
class Person <T>{
  public T info;
}
Person<String> p1 = new Person<String>();


//<>안에 있는 String이 T자리에 들어간다고 생각하면 된다.
즉 데이터 타입을 외부에서 지정하는 기법을 의미한다.

복수의 제네릭을 사용할 때는 <T,S>처럼 가운데 콤마를 찍고 사용한다.
(ex. class Person <T,S>)
그리고 참조 형식은 < >안에 들어갈 수 있고, {기본데이터 타입 = 값 형식}(int,char,float 등)은 java내에서 객체를 가지고 있지 않기 때문에
올 수 없고, 기본 데이터 타입을 포장한 포장(wrapper) 클래스 데이터 타입(integer 등)이 올 수 있다.



-예제 및 출력 결과-


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
package com.hs.chap13;
 
public class Box<T, R> {
    private T t;
    private R r;
 
    public T get0() {
        return this.t;
    }
 
    public void set0(T t) {
        this.t = t;
    }
 
    public R get1() {
        return this.r;
    }
 
    public void set1(R r) {
        this.r = r;
    }
 
    public static <U> void set2(U u) {
        System.out.println("제네릭 메소드가 실행되었습니다.");
    }
 
}
 
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.hs.chap13;
 
public class BoxExample {
 
    public static void main(String[] args) {
        Box<String,Integer> box1 = new Box<String,Integer>(); //멀티 제네릭 타입 사용 T와 R을 각각 String 타입과,Integer 타입으로 지정
        box1.set0("안녕하세요."); 
        box1.set1(3);
        System.out.println("제네릭 타입변환 문자 출력 : "+box1.get0());
        System.out.println("제네릭 타입변환 숫자 출력 : "+box1.get1());
        
        
        Box<Integer,String> box2 = new Box<Integer,String>(); //위에와 반대로 멀티 제네릭 타입 사용 T와 R을 각각 Integer 타입과,String 타입으로 지정
        box2.set0(78);
        box2.set1("반갑습니다.");
        System.out.println("제네릭 타입변환 문자 출력 : "+box2.get1());
        System.out.println("제네릭 타입변환 숫자 출력 : "+box2.get0());
        
        
    }
}
 
cs




-제네릭 메소드-


제네릭 메소드는 매개 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드를 말한다.
제네릭 메소드를 선언하는 방법은 리턴 타입 앞에 <> 기호를 추가하고 타입 파라미터를 기술한 다음,
리턴 타입과 매개 타입으로 타입 파라미터를 사용하면 된다.


-예제 및 출력결과-


1
2
3
4
5
6
7
8
9
10
package com.hs.chap13;
 
public class Util {
    public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
        boolean keyCompare = p1.getKey().equals(p2.getKey());
        boolean valueCompare = p1.getValue().equals(p2.getValue());
        return keyCompare && valueCompare;
    }
}
 
cs

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
package com.hs.chap13;
 
public class Pair<K, V> {
    private K key;
    private V value;
 
    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }
 
    public void setKey(K key) {
        this.key = key;
    }
 
    public void setValue(V value) {
        this.value = value;
    }
 
    public K getKey() {
        return key;
    }
 
    public V getValue() {
        return value;
    }
 
}
 
cs

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
package com.hs.chap13;
 
public class CompareMethodExample {
 
    public static void main(String[] args) {
        Pair<Integer, String> p1 = new Pair<Integer, String>(1"사과");
        Pair<Integer, String> p2 = new Pair<Integer, String>(1"사과");
        boolean result1 = Util.<Integer, String>compare(p1, p2);
        System.out.println(result1);
        if (result1) {
            System.out.println("p1과 p2는 논리적으로 동등한 객체 입니다.");
        } else {
            System.out.println("p1과 p2는 논리적으로 동등하지 않는 객체입니다.");
        }
 
        Pair<StringString> p3 = new Pair<StringString>("user1""홍길동");
        Pair<StringString> p4 = new Pair<StringString>("user2""홍길동");
        boolean result2 = Util.compare(p3, p4);
        System.out.println(result2);
        if (result2) {
            System.out.println("p3과 p4는 논리적으로 동등한 객체 입니다.");
        } else {
            System.out.println("p3과 p4는 논리적으로 동등하지 않은 객체 입니다.");
        }
    }
}
 
cs




-제네릭 제한-


extends 키워드를 사용하면 제한할 수 있다.
< >안에서 extends가 사용되면 상속한다는 뜻이 아니라 부모가 누구인지 표시한다.

EX) class Person <T extends Info>는 T에 데이터 타입을 판단할때 Info클래스에 있는 것들만
쓸 수 있도록 하는 것이다.
(제한을 하는 이유 : 아무 값이나 들어오면 오류가 발생될 수 있기 때문에)




-제네릭 메소드-


제네릭 메소드는 매개 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드를 말한다.
제네릭 메소드를 선언하는 방법은 리턴 타입 앞에 <> 기호를 추가하고 타입 파라미터를 기술한 다음,
리턴 타입과 매개 타입으로 타입 파라미터를 사용하면 된다.

abstract class Info{  //Info라는 이름의 추상클래스 생성
 public abstract int getLevel(); //getLevel()이라는 메소드 구현


 

- 와일드 카드 타입 -


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


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


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


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




-제네릭 타입의 상속과 구현-


제네릭 타입도 부모 클래스가 될수 있고, 자식 제네릭 타입은 추가적으로 타입 파라미터를 가질 수 있다.


728x90
반응형
: