제네릭(Generic)2

5BRack·2022년 7월 4일

자바란?

목록 보기
27/42

제네릭 메서드

제네릭이란?

💡 여러가지 타입을 자원으로 사용하기 위해 다양성을 가진 제네릭 타입을 명시해 주어 해당 타입으로 클래스 및 메서드를 프로그래밍 하는 기법
  • 클래스 전체를 제네릭으로 선언하는 대신, 일반 클래스 내부의 특정 메서드만 제네릭으로 선언할 수 있다.
  • 이를 제네릭 메서드라 하며, 리턴 타입 또는 입력매개변수 타입을 제네릭 타입 변수로 선언한다. 제네릭 클래스가 객체를 생성하는 시점에 실제 타입을 지정하는 것과 달리 제네릭 메서드는 호출되는 시점에 실제 제네릭 타입을 지정한다.
//제네릭 타입 변수명이 1개일 때
접근 지정자 <T> T 메서드명(T t){}

//제네릭 타입 변수명이 2개일 때
접근 지정자 <T, V> T 메서드명(T t, V v){}

//매개변수에만 제네릭이 사용됐을 때
접근 지정자 <T> Void 메서드명(T t){}

//리턴타입에만 제네릭이 사용됐을 때
접근 지정자 <T> T 메서드명(int a){}
  • 제네릭 메서드에서 입력매개변수를 제네릭타입으로 사용할 때에는 호출과정에서 제네릭타입을 생략할 수 있다.
class GenericMethods{
    public <T> T method1(T t){
        return t;
    }
    public <T> boolean method2(T t1, T t2){
        return t1.equals(t2);
    }

    public <K,V> void method3(K k, V v){
        System.out.println(k+":"+v);
    }
}

 class GenericMethod {
     public static void main(String[] args) {
         GenericMethods gm = new GenericMethods();

         String str1 = gm.<String>method1("안녕");
         String str2 = gm.method1("안녕");
         System.out.println(str1);
         System.out.println(str2);

     }
}

제네릭 메서드 내에서 사용할 수 있는 메서드

  • 제네릭 메서드는 문법적으로 모든 타입이 올 수 있도록 허용하고 있기 때문에 Object 객체의 메서드만 활용할 수 있다.

제네릭 타입의 범위 제한

  • 제네릭 타입을 올 수 있는 실제 타입의 종류를 제한하는 것

제네릭 클래스의 타입 제한

  • 제네릭 클래스의 정의 과정에서 제네릭 타입을 제한하는 방법은 <제네릭 타입 변수 extends 상위 클래스> 와 같이 제네릭 타입으로 대입될 수 있는 최상위 클래스를 extends 키워드와 함께 정의 하는 방법
접근 지정자 class 클래스명 <T extends 최상위클래스/인터페이스명>{
}
  • 최상위 클래스 및 인터페이스 또는 그 하위 클래스 타입만을 지정할 수 있다.
  • 주의할점은 뒤에 나오는 요소가 클래스이든 인터페이스이든 항상 extends 키워드를 사용한다.

제네릭 메서드의 타입 제한

  • 제네릭 클래스와 마찬가지로 <제네릭 타입 변수 extends 상위 클래스> 와 같이 올 수 있는 최상위 타입을 정의하며, 클래스와 인터페이스 모두 extends 키워드를 사용한다
접근 지정자 <T extends 최상위 클래스/인터페이스명> T 메서드명 (T t){}
  • 타입을 제한하게 되면 최상위 클래스 하위 메서드를 활용할 수 있다.

제네릭 메서드에서의 제네릭 타입 제한 범위 설정

class A{
    public <T extends Number> void method1(T t){
        System.out.println(t.intValue());
    }
}

interface MyInterface{
    public abstract void print();
}

class B{
    public <T extends MyInterface> void method1(T t){
        t.print();
    }
}
public class BoundedTypeOfGenericMethod {
    public static void main(String[] args) {
        A a = new A();
        a.method1(5.8);

        B b = new B();
        b.method1(new MyInterface() {
            @Override
            public void print() {
                System.out.println("print() 구현");
            }
        });
    }
}

제네릭 클래스 객체의 제네릭 타입

리턴 타입 메서드명(제네릭 클래스명<제네릭 타입명> 참조 변수명){}

리턴 타입 메서드명(제네릭 클래스명<?> 참조 변수명){}

리턴 타입 메서드명(제네릭 클래스명<? extends 상위 클래스/인터페이스> 참조 변수명){}

리턴 타입 메서드명(제네릭 클래스명<? super 하위 클래스/인터페이스> 참조 변수명){}
  • 첫번째는 객체의 제네릭 타입을 특정 타입으로 확정하는 방법
  • 두번째는 제네릭 타입 변수에 <?> 사용할 때로 제네릭 타입으로 어떤 것이 대입되든 해당 제네릭 객체이기만 하면 매개변수로 사용할 수 있는 것을 의미
  • 세번째는 <? extends 상위 클래스/인터페이스>와 같이 표기하는 방법으로, 상위 클래스의 자식 클래스타입이 제네릭 타입으로 대입된 객체가 매개변수로 올 수 있다.
  • 네번째 <? super 하위클래스/인터페이스> 는 extends와 반대 개념으로 제네릭 타입을 하위 클래스 또는 하위 클래스의 부모 클래스 타입이 올 수 있다는 것을 의미한다.

제네릭 클래스의 상속

  • 부모 클래스가 제네릭 클래스일 때, 이를 상속한 자식 클래스도 제네릭 클래스가 된다.
  • 즉 제네릭 타입 변수를 자식 클래스가 그대로 물려 받는다.
  • 또한 자식 클래스는 제네릭 타입 변수를 추가해 정의할 수 있다.
//부모 클래스와 제네릭 타입 변수 개수가 동일할 때
class Parent<K,V>{}

class Child<K,V> extends Parent{}

//부모 클래스보다 제네릭 타입 변수의 개수가 많을 때
class Parent<K>{}

class Child<K,V> extends Parent<K>{}

제네릭 메서드의 상속

  • 제네릭 메서드를 포함한 일반 클래스를 상속해 자식 클래스를 생성할 때에도 부모 클래스 내의 제네릭 메서드는 그대로 자식 클래스에 상속된다.
package Resource;

class Parent{
    <T extends Number> void print(T t){
        System.out.println(t);
    }
}

class Child extends Parent{

}
public class InheritanceGenericMethod {
    public static void main(String[] args) {
        Parent p = new Parent();
        p.print(3);
        p.<Integer>print(10);
        
        Child c = new Child();
        c.print(10.1);
        c.<Double>print(10.2);
        
    }
}

0개의 댓글