Generic Type(제네릭 타입)이란?

  • 타입을 파라미터(parameter)로 가지는 클래스와 인터페이스
  • 선언 시 클래스 또는 인터페이스 이름 뒤에 "<매개변수 타입>"부호를 붙임
  • 클래스를 정의하면서 사용할 변수의 데이터타입을 명시하지결정하지 않은 상태로 냅두다 데이터타입을 실행(컴파일)할 때 매개변수로 받아서 데이터 타입을 결정한다 (데이터타입에 유연하면서도 안정성까지 제공)
  • 제네릭은 어떠한 데이터타입을 기반으로도 인스턴스 생성이 가능하도록 자료형에 일반적인 클래스를 정의하는 문법이다(재사용이 가능)
  • 제네릭은 클래스, 인터페이스, 메서드를 정의할 때 타입을 매개변수로 사용할 수 있도록 한다

✔ Generic(제네릭)의 장점은?

  • 불필요한 타입 변경을 없애준다 (타입 변환 제거)
  • 엄격한 타입 검사를 통해 안정성을 높여준다 (컴파일 시에 미리 타입을 체크해서 에러 방지)

 Generic(제네릭) 선언

public class 클래스명<T>{...}    //<T>는 매개변수의 타입(parameter type)이라 한다. 
public class Product<T, M>{...}
public interface 인터페이스명<T>{...}

 

  • 제네릭 클래스(generic class)에서는 타입을 변수로 표시한다. 이것은 매개변수의 타입라 한다.
  • 매개변수의 타입은 객체 생성 시에 프로그래머에 의하여 결정된다

 

매개변수타입 표기

타입 설명
<T> Type
<E> Element
<K> Key
<V> Value
<N> Number

- 일반적으로 대문자 알파벳 한 문자로 표현한다

실행 클래스에서 객체를 생성할 때 구체적인 타입을 지정해 주어야 한다

 

Product<String> product1=new Product<String>();    //문자열을 저장

Product<Interger> product2=new Product<Integer>();     //정수를 저장

 

Product<클래스명, String> product=new Product<클래스명, String>();     //클래스도 넣기 가능함

 

(클래스명<타입인자>참조변수=new 클래스명<타입인자>();)

 


Generic Type 예시

더보기

1) class Product

public class Product<T,M> {	//제네릭 타입 선언
	private T kind;
	private M model;

	public Product() {}
	public Product(T kind, M model) {
		this.kind=kind;
		this.model=model;
	}
	public T getKind() {
		return this.kind;
	}
	public M getModel() {
		return this.model;
	}
	public void setKind(T kind) {
		this.kind = kind;
	}
	public void setModel(M model) {
		this.model = model;
	}

	@Override
	public String toString() {
		return "kind : " + kind.getClass().getSimpleName().toUpperCase() + ", model :" + model;
	}
}

2) class Product

public class Car {
	private String color;

	public Car() {
	}

	public Car(String color) {
		this.color = color;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}
}

3) class Tv

public class Tv {
	
	private int size;

	public Tv(){ }
	
	public Tv(int size){
		this.size=size;
	}
	
	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}
	
	@Override
	public String toString(){
		return "[size : "+size +"인치]";
	}
}

3) class SmartPhone

public class SmartPhone {
	private String company;
	private String os;
	
	public SmartPhone() {
		
	}
	public SmartPhone(String company, String os) {
		this.company = company;
		this.os = os;
	}
	
	@Override
	public String toString() {
		return " [" + company + ", " + os +"]";
	}
}

4) 실행 class : ProductRun

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

		/* class Car */
		Product<Car, String> product1 = new Product<Car, String>();	//제네릭타입
		product1.setKind(new Car());
		product1.getKind().setColor("RED");
		product1.setModel("베뉴");
		System.out.println(product1.toString() + " [color : " + product1.getKind().getColor() + "]");

		/* class Tv */
		/*Product<Tv, String> product2 = new Product<Tv, String>();
		product2.setKind(new Tv(48));
		product2.setModel("스마트 TV");*/
		
		Product<Tv, String> product2 = new Product<Tv, String>(new Tv(48), "스마트 TV");
		
		System.out.print(product2.toString() + " ");
		System.out.println(product2.getKind().toString());

		/* class SmartPhone */
		/*Product<SmartPhone, String> product3 = new Product<SmartPhone, String>();
		product3.setKind(new SmartPhone("삼성", "안드로이드"));
		product3.setModel("갤럭시 Z 플립3");*/
		
		Product<SmartPhone, String> product3 = new Product<SmartPhone, String>(new SmartPhone("삼성", "안드로이드"), "갤럭시 Z 플립3");
		
		System.out.print(product3.toString());
		System.out.println(product3.getKind().toString());
		// product3.getKind() -> SmartPhone의 주솟값. toString() -> SmartPhone이 가진 toString()
	}
}

 

✔ 한정된 타입매개변수 (bounded type parameter)

- 타입매개변수로 전달되는 타입의 종류를 제한하고 싶은 경우가 있다

  이런경우 한정된 타입매개변수를 쓴다

 

✔ 사용법 : 매개변수타입뒤에 extends나 super 을 쓴다

class MyMath<T extends Number>{ ... }	//Declaring Class (클래스선언)
.
.
MyMath<Integer or Double> m = MyMath<Integer or Double>();	//Declaring	Object (객체선언)
<매개변수타입 extends 부모 클래스명>

> 부모클래스를 상속받은 자식 객체들만 가능한다  

 

<매개변수타입 extends 인터페이스명>
// implements 키워드를 사용해서는 안됨

> 인터페이스로부터 구현 클래스 객체들만 가능하다

 

✔ 와일드카드

제네릭 타입을 매개변수타입이나 리턴타입으로 사용할 때

구체적인 타입 대신에 와일드카드로 명시할 수도 있다.

 

와일드카드 사용법

와일드카드는 ? 기호로 표현한다 ( ? 기호는 어떤 타입 매개변수도 지정할 수 있다는 의미

현재 객체의 매개변수타입과 같지않은 타입의 인자도 받을 수 있다

 

<? extends 부모 클래스>

: 매개변수타입을 대치하는구체적인 타입으로

부모 클래스이거나 부모클래스로부터 상속받은 하위 객체만 타입으로 지정 > ?

 

<? super 자식 클래스>

: 매개변수타입을 대치하는 구체적인 타입으로

자식 클래스이거 나 자식 클래스가 상속하는 부모 객체만 타입으로 지정 > ?

 


 

✔ 제네릭 메소드

매개변수 타입과 리턴 타입으로 매개변수타입을 갖는 메소드를 제네릭 메소드라고 한다 (정적메소드에 많이 씀

 

✔ 제네릭 메소드 선언

- 리턴 타입 앞에 <> 기호를 추가하고 매개변수타입 기술

- 매개변수타입을 리턴 타입과 매개변수로 사용

public < 매개변수타입, ... > 리턴타입 메서드명( 매개변수, ... ) { ... }
public class GenericMethod{
	//배열의 마지막 원고를 반환하는 메소드
	public static <T> T getLast(T[] array){	 
		return array[array.length -1];
	}
}

 

 

 

 

 

 

 

 

 

 

 

 

 

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

JAVA 기본 API  (0) 2022.02.28
컬렉션 (Collection)  (0) 2022.02.23
예외 (Exception Event)  (0) 2022.02.22
내부 클래스 (중첩 클래스)  (0) 2022.02.21
다형성 (Polymorphism)  (0) 2022.02.21