Cute Running Puppy

Language/[Java] 자바 완전 정복

6주차_16. 제네릭

R.silver 2022. 3. 1. 15:41
반응형

제네릭 클래스와 제네릭 인터페이스 

제네릭

오버로딩의 비효율성을 해결하는 문법

제네릭의 문법

제네릭 클래스와 제네릭 인터페이스 정의하기 

1. 제네릭 타입 변수명이 1개일 때

접근_지정자 class 클래스명<T> {
    ...
}

접근_지정자 interface 클래스명<T> {
    ...
}

2. 제네릭 타입 변수명이 2개일 때

접근_지정자 class 클래스명<K, V> {
    ...
}

접근_지정자 interface 클래스명<K, V> {
    ...
}

제네릭 클래스는 객체를 생성하는 시점에 타입을 지정함 (클래스를 정의하는 시점에 타입을 지정하는 것 X)

 

public class Myclass<T> {
	private T t;
    public T get(); {
    	return t;
    }
    public void set(T t) {
     this.t = t;
     }
 }
 
 public interface MyInterface<K, V> {
 	public abstract void setKey(K k);
    public abstract void setValue(V v);
    public abstract getKey();
    public abstract getValue();
}

 

class MyClass<T> {
	private T t;
    public T get() {
    	return t;
    }
    
    public void set(T t) {
    	this.t = t;
    }
}

...
// main class
{
	MyClass<String> mc1 = new My Class<String>();
    mc1.set("안녕");
    System.out.println(mc1.get());
   
   	MyClass<Integer> mc2 = new My Class<Integer>();
    mc2.set(123);
    System.out.println(mc2.get());
}

// 출력 결과
안녕
123

 

최상위 클래스인 object class 를 사용하는 것도 가능하지만 항상 다운 캐스팅을 해주어야 한다는 문제가 발생한다. 

제네릭 메서드 

제네릭 메서드의 정의와 호출 

클래스 전체를 제네릭으로 선언하는 대신 클래스 내부의 특정 메서드만 제너릭으로 선언하는 방법

제너릭 클래스 제네릭 메서드
객체를 생성하는 시점에 실제 타입을 지정 호출되는 시점에 실제 제네릭 타입을 지정 
1. 제네릭 타입 변수명이 1개일 때 

접근_지정자 <T> T 메서드명 (T t) {
    ...
}

2. 제네릭 타입 변수명이 2개일 때 

접근_지정자 <T, V> T 메서드명 (T t, V v) {
    ...
}

3. 매개변수에만 제네릭이 사용됐을 때

접근_지정자 <T> void 메서드명 (T t) {
    ...
}

4. 리턴 타입에만 제네릭이 사용됐을 때

접근_지정자 <T> void 메서드명 (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);
	}
}

public 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);
		
		boolean bool1 = gm.<Double>method2(2.5, 2.5);
		boolean bool2 = gm.method2(2.5, 2.5);
		System.out.println(bool1);
		System.out.println(bool2);
		
		gm.<String, Integer>method3("국어", 80);
		gm.method3("국어", 80); 		
	}
}

 

제네릭 타입 범위 제한 

제네릭 타입 범위 제한의 종류와 타입 범위 제한 방법

제네릭 클래스의 타입 제한

접근_지정자 class 클래스명 <T extends 최상위_클래스/인터페이스명> {
    ...
}

인터페이스도 extends 사용 

제네릭 메서드의 타입 제한 

접근_지정자 <T extends 최상위_클래스/인터페이스명> T 메서드명(T t) {
    ...
}

메서드 매개변수일 때 제네릭 클래스의 타입 제한 

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

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

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

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

제네릭의 상속

부모 클래스가 제네릭 클래스이면 이를 상속한 자식 클래스도 제네릭 클래스가 된다 

 

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) {
		
		//#1. 부모클래스 제네릭메서드 이용
		Parent p = new Parent();
		p.<Integer>print(10);
		p.print(10);
		
		//#2. 자식클래스 제네릭메서드 이용
		Child c = new Child();
		c.<Double>print(5.8);
		c.print(5.8);
	}
}
반응형