제네릭

zee-chive·2024년 7월 23일

Java

목록 보기
8/12

제네릭

  • 다양한 종류의 객체, 데이터를 처리할 수 있도록 클래스, 인터페이스, 메서드를 작성하는 방법
  • 타입 매개변수를 사용
    1. 코드의 재사용성을 높임,
    2. 타입의 안정성 보장





제네릭 클래스

  • 클래스 정의 시 타입 매개변수를 사용하여 다양한 타입을 처리할 수 있는 클래스
  • 타입 매개변수는 < > 안에 적는다

  • 사용하는 시점에 해당 타입을 정의할 수 있다.

기본 Objcet 사용 시

package test05;

class Box{
	private Object obj;

	public Object getObj() {
		return obj;
	}

	public void setObj(Object obj) {
		this.obj = obj;
	}
}

public class normalBox {
	public static void main(String[] args) {
		Box box = new Box();
		
		// Object 를 사용하므로, 모두 넣을 수 있다.
		box.setObj(11); // 정수형
		box.setObj("Hello"); // 문자형
		box.setObj(42.11); // 실수형 
		
		Object obj = box.getObj(); 
		// 값을 사용하는 순간에는 object로만 꺼낼 수 있고, 
		// 이를 사용하기 위해서는 전부 형변환을 해줘야 한다. 
		
		if (obj instanceof Double) {
			System.out.println("실수형의 값입니다.");
		} else if (obj instanceof Integer) {
			System.out.println("정수형의 값입니다.");
		} else if (obj instanceof String) {
			System.out.println("문자형의 값입니다.");
		} 
	}
}


Generic

package test05;

// <  > 안에 타입 파라미터를 정해준다.
class Box<T>{
	private T t;
	
	public T getT() {
		return t;
	}
	
	public void setT(T t) {
		this.t = t;
	}
}

public class GenericBox {
	public static void main(String[] args) {
		// 제네릭 클래스 사용 시점에 매개변수 타입을 정한다 .
		// 제네릭에서 타입을 쓸 때, class 명으로 작성해야 한다.
		Box<Integer> intbox = new Box<Integer>();
		Box<String> strbox = new Box<>(); // 동일한 타입이라면 생략 가능 
		Box<Double> doublebox = new Box<Double>();
		
		intbox.setT(43); // 타입 안정성을 높여준다.
		strbox.setT("Hello");
		String value = strbox.getT();

		
	}
}


  • 변수와 생성 쪽 타입은 반드시 일치해야 한다. (상속 관계에 있는 것 또한 불가능)
    • Box<Student> box = new Box<Student>(); 가능
    • Box<Person> box = new Box<Student>(); 불가능
  • 추정이 가능한 경우 타입 생략 가능하다.
  • 제네릭 타입을 지정하지 않고 생성은 가능하지만, Object와 같이 상위 타입을 지정하고 생략하는 것이 낫다.


  • 클래스의 타입 파라미터와는 별개로 메서드 레벨에서 제네릭 타입을 정의하고 사용할 수 있다.
  • 메서드의 매개변수나 반환 타입을 타입 파라미터로 지정하여 처리
  • 정의하려면 매서드의 반환 타입 앞에 파라미터를 선언
	public <U> void printClassName(U item) {
		System.out.println("Item type : " + item.getClass().getName());
	}


한정된 타입의 매개변수

  • 제네릭 클래스를 정의할 때, 모든 종류 타입이 아니라 특정 종류 타입에 대해 작성하고 싶은 경우
  • 구체적인 타입의 제한이 필요할 때 extends 키워드 사용할 수 있다.
    • super의 사용은 불가능하며 extends만 사용 가능하다.

class nBox<T extends Integer>{
	private T t;
	
	public T getT() {
		return t;
	}
	
	public void setT(T t) {
		this.t = t;
	}
}

public class GenericBox {
	public static void main(String[] args) {

		nBox<Integer> intbox = new nBox<Integer>();
		nBox<String> strbox = new nBox<String>();		
	}
}


위와 같이 integer 확장된 숫자만 가능하다고 나온다.





와일드 카드

  • 제네릭 클래스의 인스턴스 변수의 참조 타입을 작성할 때, 와일드카드로서 문자 ? 사용
  • 불특정 타입을 나타내기 위해 사용하는 특수 타입
  • 타입이 구체적으로 정해진 제네릭 클래스들의 부모 타입으로서 사용 가능
    • 제네릭 클래스 Box 에 대해서 Box<?>Box<A>, Box<B> 의 부모가 된다.
    • GenericType<?> : 타입에 제한이 없음
    • GenericType<? extends T> : T와 T를 상속 받은 타입들만 사용 가능
    • GenericType<? super T> : T와 T의 조상 타입들만 사용 가능

    - 버전이 다르면, 오류가 발생되기도 한다.
profile
누가 봐도 읽기 쉬운 글이 최고의 글이다.

0개의 댓글