본문 바로가기

[TIL] 제네릭

인포꿀팁 발행일 : 2020-08-12

제네릭이란?

  • 다양한 타입의 객체를 다루는 클래스나 인터페이스에서 사용할 데이터 타입을 인스턴스를 생성할 때 결정하는 것으로 JDK 5.0부터 지원
  • 데이터 형에 대한 별도의 메소드나 멤버 변수를 구현할 필요 없이 미리 정의된 메소드 또는 멤버 변수에 서로 다른 자료 형으로 처리할 수 있다.
  • 객체의 타입을 컴파일 할 때 체크하므로 객체 타입의 안정성을 높이고 불필요한 형 변환을 막을 수 있다.

장점

  • 성능 저하를 유발하는 강제 캐스팅을 줄일 수 있다.
  • 컴파일 할 때 타입 오류를 체크하므로 객체타입의 안정성을 높인다.
  • 반복적인 코드를 줄일 수 있으며, 재사용성 증가로 유지보수가 편리하다.(오버로딩 줄일 수 있다.)

개요

타입 파라미터를 하나 이상 갖는 제너릭 타입의 클래스

클래스나 인터페이스를 선언할 때 타입을 지정하지 않고 인스턴스를 생성할 때 사용할 타입을 파라미터로 지정

 

제네릭 타입 파라미터

 

 
 
 
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
30
31
32
33
34
35
36
37
38
39
40
package ex0812;
 
public class Generic_Ex2 {
    public static void main(String[] args) {
        User20<String> obj = new User20<String>(); // JDK 5,6은 뒤에도 파라미터 넣어야함
        User20<Integer> obj1 = new User20<>();//JDK 7부터는 생략 가능
        
        obj.set("aaa");
        obj1.set(123);
//        class java.lang.String
//        class java.lang.Integer
        Integer ii = obj1.get();
        //캐스팅 불필요
        
        Test20 tt = new Test20();
        tt.set(30);
//        Integer ii2 = tt.get();// 캐스팅이 필요함
    }
}
class User20<T>{
    private T t;
    
    public void set(T t) {
        System.out.println(t.getClass().getName());
        this.t=t;
    }
    
    public T get() {
        return t;
    }
}
class Test20{
    private Object obj;
    public void set(Object obj) {
        this.obj = obj;
    }
    public Object get() {
        return obj;
    }
}
cs

제한된 타입 파라미터

타입 파라미터로 전달되는 타입의 종류를 제한하기 위한 기능으로 extends 키워드를 사용한다.

 

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 ex0812;
 
public class Generics_Ex5 {
 
    public static void main(String[] args) {
        User24<Integer> obj = new User24<>();
        obj.set(10);
        System.out.println(obj.get());
        
//        User24<String> obj = new User24<>();
        // 컴파일 오류 : 제한된 파라미터이기 때문
        //number 하위 클래스만 가능하다.
    }
 
}
//제한된  타입 파라미터
//extends를 통하여 제한할 클래스를 상속받는다.
class User24<extends Number>{
    private T t;
    public void set (T t) {
        this.t =t;
    }
    public T get() {
        System.out.println(t.getClass().getName());
        return t;
    }
}
cs

 


제네릭 메소드

  • 타입 파라미터를 하나 이상 갖는 메소드를 말한다.
  • 메소드를 선언할 때 타입을 지정하지 않고 메소드를 호출 할 때 명시적으로 타입을 지정하거나 메소드의 매개변수 값의 타입으로 지정한다.
  • 선언 방법은 리턴 타입 앞에 <> 기호를 추가하고 <>안에 타입 파라미터를 기술 한 후 리턴 타입과 매개 변수 타입에서 타입 파라미터를 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package ex0812;
 
public class GenericsMethod_Ex1 {
//제너릭 메소드
    public static void main(String[] args) {
        User23 ob = new User23();
        ob.print("String");
        ob.print(123);
    }
 
}
class User23{
    // 제네릭 메소드
    public <U> void print(U u) {
        System.out.println("U : "+u.getClass().getName());
    }
}
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 ex0812;
 
public class Generics_Ex7 {
    public static void main(String[] args) {
        User26<Integer> obj = new User26<>();
        obj.set(10);
//        User26<Number> obj2 = obj;// 업캐스팅은 안된다
        
        User26<?> obj2 = obj; // 와일드 카드라고 한다.
        // 제네릭의 타입이 결정되지 않은 상태
//        obj2.set(20);// 타입이 결정되지 않앗으니 컴오류이다.
        
        obj2.print();// 해당 print 메소드는 T에 의존적이지 않기때문에 가능하다.
        System.out.println(obj2.get()); // 단순히 값을 가져오는건 가능하다.
    }
}
class User26<T>{
    private T t;
    public void set(T t) {
        this.t =t;
    }
    public T get() {
        return t;
        
    }
    public void print() {
        System.out.println("출력 : "+ t);
    }
}
cs

'Language > JAVA' 카테고리의 다른 글

[TIL] 컬렉션 - java.util.List<E> 인터페이스 & 구현 클래스  (0) 2020.08.24
[TIL] 컬렉션 프레임워크  (0) 2020.08.14
[TIL] 예외처리  (3) 2020.08.12
[TIL] 중첩 클래스  (0) 2020.08.11
[TIL] 인터페이스  (0) 2020.08.11

댓글