Backend/Java

Java 제네릭

호ㅁl 2022. 11. 14. 23:47

제네릭

  • 임시형으로 지정해놓고있다가 사용시점에서 내가 지정하는 형태로 사용하는 방식
  • 어떤 값이 하나의 참조 자료형이 아닌 여러 참조 자료형을 사용할 수 있도록 프로그래밍 하는 것.
  • 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법.
  • 참조자료형이 변환될 때 컴파일러가 검증을하기 때문에 매우 안정적이다.

 

제네릭 클래스 정의하기

package javastudy2;

//GenericPrinter<T> : 클래스이름
public class GenericPrinter<T> { //<T> : 타입의 약자 , 자료형 매개변수 
	private T material;

	public T getMaterial() {
		return material;
	}

	public void setMaterial(T material) {
		this.material = material;
	}
    
    public String toString() {
		return material.toString();
	}
}
  • 제네릭에서는 여러 참조 자료형을 사용해야하는 부분에 하나의 문자로 표현한다.
  • 여러 자료형으로 바꾸어 사용할 material 변수의 자료형을 T 라고(타입변수) 작성한 것이다.
  • 클래스 이름을 GenericPrinter<T>로 정의하고 나중에 클래스를 사용할 때 T 위치에 실제 사용할 자료형을 지정한다.
  • 클래스의 각 메소드에서 해당 자료형이 필요한 부분에는 모두 T문자를 사용하여 구현한다.
  • 여러개의 타입변수는 콤마( , )로 구분하여 명시할 수 있다.

 

다이아몬드 연산자<>

ArrayList<String> list = new ArrayList<>();

 <> : 다이아몬드 연산자

생략된 <> 부분이 String임을 컴파일러가 유추하기때문에 생성부분에서는 생략이 가능함.

 

 

자료형 매개변수 T와 static

  • static변수나 메소드는 인스턴스를 생성하지 않아도 클래스 이름으로 호출할 수 있다.
  • static 변수는 인스턴스 변수가 생성되기 이전에 생성된다.
  • static 메소드에서는 인스턴스 변수를 사용할 수 없다.
  • T의 자료형이 정해지는 순간은 제네릭 클래스의 인스턴스가 생성되는 순간이다.
  • T의 자료형이 결정되는 시점보다 빠르기 때문에 static변수의 자료형이나 static메소드 내부 변수의 자료형으로 
    T를 사용할 수 없다.

 

제네릭에서 자료형 추론하기

ArrayList<String> list = new ArrayList<String>();

var list = new ArrayList<String>();

지역 변수에 한해서 자료형을 추론할 수 있다.

 

powder 클래스 정의하기

package javastudy2;

public class Powder {
	public void doPrinting() {
		System.out.println("Powder 재료로 출력합니다.");
	}
	
	public String toString() {
		return "재료는 Powder입니다.";
	}
}

 

plastic 클래스 정의하기

package javastudy2;

public class Plastic {
	public void doPrinting() {
		System.out.println("Plastic 재료로 출력합니다.");
	}
	
	public String toString() {
		return "재료는 Plastic입니다.";
	}
}

 

GenericPrinter<T> 클래스 사용하기

package javastudy2;

public class GenericPrinterTest {
	public static void main (String[] args) {
    	//Powder 형으로 GenericPrinter클래스 생성
		GenericPrinter<Powder> powderPrinter = new GenericPrinter<Powder>();
		
		powderPrinter.setMaterial(new Powder()); //powder클래스 생성
		Powder powder = powderPrinter.getMaterial(); //변수에 getMaterial값 대입
		System.out.println(powderPrinter);
		
        //Plastic 형으로 GenericPrinter클래스 생성
		GenericPrinter<Plastic> plasticPrinter = new GenericPrinter<Plastic>();
        
		plasticPrinter.setMaterial(new Plastic());
		Plastic plastic = plasticPrinter.getMaterial();
		System.out.println(plasticPrinter);
	}
}

선언된 제네릭클래스를  생성할때에는 타입변수 자리에 실제사용할 변수를 작성해야한다.

 

 

<T extends 클래스>

public class GenericPrinter<T extends Material>{
	private T material;
}

상위클래스 Material에서 선언한 메소드를 사용할 수 있다. 

 

제네릭 메소드

//public <자료형 매개변수> 반환형 메소드(자료형 배개변수...){...}
public T getX(){
	return x;
}
  • 반환형 앞에 사용하는 <자료형 매개변수>는 여러 개일 수 있다.
  • 제네릭 메소드 내에서만 유효하게 사용할 수 있다.