본문 바로가기
Java/기본 개념 및 클래스

[Java] 101. 제네릭 Generic

글: Song hyun 2024. 6. 3.
728x90
반응형

[Java] 101. 제네릭 Generic

1. 제네릭이란?

2. T extends 문법

3. 시나리오 코드


1. 제네릭이란?

(1) 제네릭(Generic): 제네릭은 무엇이든 담을 수 있다. (from JAVA ver 5.0~)

(2) 제네릭은 클래스에서 사용하는 변수의 자료형이 여러개이고, 그 기능(메서드)은 동일할 때, 클래스의 자료형을 특정하지 않고 추후 

(2) 우리가 변수를 사용할 때, 항상 자료형을 먼저 선언하게 된다. 이 때, 변수의 이름은 같지만 자료형(데이터 타입)이 다를 때 제네릭을 사용하게 된다.


2. T-extends 문법

(1) 제네릭을 사용해 코드를 작성할 경우, 다양한 자료형을 사용할 수 있다는 장점이 있다. 하지만 상정 외의 자료형이 들어갈 수도 있다는 단점이 존재한다.

(2) 그래서 사용자가 정의한 자료형만 사용할 수 있도록, 제네릭과 함께 상속(Extends) 기법을 사용한다.

 

 

-GenenericPrinter

더보기
package ch03;

// Material을 상속받은 하위 자식 클래스만
// 대체 문자에 들어올 수 있다.
public class GenericPrinter<T extends Material> {
	
	private T material;
	
	public T getMaterial() {
		return material;
	}
	
	public void setMaterial(T material) {
		this.material=material;
	}
	
	@Override
	public String toString() {
		return material.toString();
	}
}

-Material

더보기
package ch03;

// 직접 객체를 사용할 수 없게, 강제성을 부여(추상 클래스)
public abstract class Material {

	public abstract void doPrinting();
	
}

-Plastic/Powder

더보기
package ch03;

/*
 * T extends 클래스 문법을 사용하기 위해 설계
 */

public class Plastic extends Material {

	@Override
	public String toString() {
		return "재료는 플라스틱입니다.";
	}
	
	@Override
	public void doPrinting() {
		System.out.println("플라스틱 재료로 출력합니다.");
		
	} 

}
package ch03;

/*
 * T extends 클래스 문법을 사용하기 위해 설계
 */

public class Powder extends Material {

	@Override
	public String toString() {
		return "재료는 파우더입니다.";
	}
	
	@Override
	public void doPrinting() {
		System.out.println("파우더 재료로 출력합니다.");
		
	} 

}

-MainTest

더보기
package ch03;

public class MainTest3 {
	
	public static void main(String[] args) {
		
		// <T extends 클래스> 사용하기 
		
		// 상위 클래스의 필요성
		// T 자료형은 범위를 제한할 수 없음
		// 위 문법을 사용해, 상위 클래스에 속한 자료형만 대체 문자 안에 들어올 수 있다!
		
		GenericPrinter<Powder> genericPrinter1=new GenericPrinter<>();
		genericPrinter1.setMaterial(new Powder());
		System.out.println(genericPrinter1.toString());
		
		//////////////////////////////////
		// 컴파일 시점에서부터 오류가 생한다.
		// GenericPrinter<Water> genericPrinter2=new GenericPrinter<>();
	}

}

3.시나리오 코드

-ch01

더보기
package ch01;

public class ThreeDPrinter {
	Plastic material;
	
	// get,set
	public Plastic getMaterial() {
		return material;
	}
	
	public void setMaterial(Plastic material) {
		this.material=material;
	}
}
package ch01;

public class Plastic {
	
	@Override
	public String toString() {
		return "재료는 플라스틱 입니다.";
	}

}
package ch01;

public class Powder {

	@Override
	public String toString() {
		return "재료는 파우더 입니다.";
	}
}

 

-ch02

더보기
package ch02;

public class GenericPrinter<T> {

	// T라는 대체 문자를 사용, 
	// E - Elements
	// K - Key
	// V - Value 라는 의미로 대체 문자를 사용하기도 한다.
	// 사실은 어떤 문자든 관계 없다.
	// 자료형 매개변수(type parameter) 
	
	// 이 클래스를 사용하는 시점에서 실제 사용될 자료형이 결정된다.
	
	private T material; // T 대체 문자로형으로 변수를 선언
	public T getMaterial() {
		return material;
	}
	public void setMaterial(T material) {
		this.material=material;
	}
	
	// GenericPrinter<T> -- 참조 변수를 sysout(참조변수)
	// --> 나의 멤버 material에 toString()
	@Override
	public String toString() {
		return material.toString();
	}
	
}
package ch02;

import ch01.Plastic;
import ch01.Powder;

public class MainTest02 {
	
	public static void main(String[] args) {
		
		// 재료 선언
		Plastic plastic01 = new Plastic();
		Powder powder01 = new Powder();
		
		// 사용하는 시점에 T 대신 어떤 자료형을 사용할지 지정하면 된다.
		GenericPrinter<Plastic> genericPrinter1 = new GenericPrinter<>();
		genericPrinter1.setMaterial(plastic01); // 메서드 의존 주입
		
		// 최상위 Object 를 활용할 때와 비교해보면
		// 1. 다운캐스팅을 할 필요가 없다.
		Plastic returnPlastic=genericPrinter1.getMaterial();
		System.out.println(returnPlastic);
		
		// 2. 컴파일 시점에서 오류를 알려주기 때문에, 안정적인 코드 작업이 진행된다.
		// Powder returnPowder=genericPrinter1.getMaterial();
	} // end of main

}

 

728x90
반응형