λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Java

[Java-기초] μ œλ„€λ¦­

by μ½”λ”©ν•˜λŠ” λΆ•μ–΄ 2021. 2. 21.
λ°˜μ‘ν˜•

β–Ά μ œλ„€λ¦­

μ–΄λ–€ 값이 ν•˜λ‚˜μ˜ μ°Έμ‘° μžλ£Œν˜•μ΄ μ•„λ‹Œ μ—¬λŸ¬ μ°Έμ‘° μžλ£Œν˜•μ„ μ‚¬μš©ν•  수 μžˆλ„λ‘ ν”„λ‘œκ·Έλž˜λ°ν•˜λŠ” 것을 'μ œλ„€λ¦­ ν”„λ‘œκ·Έλž˜λ°'이라고 ν•œλ‹€.

​

 

ThreeDPrinter3.java

package genericsTest;

public class ThreeDPrinter3 {
	private Object material;

	public Object getMaterial() {
		return material;
	}

	public void setMaterial(Object material) {
		this.material = material;
	}
}

μ–΄λ–€ μž¬λ£Œλ“  μ“Έ 수 μžˆλ„λ‘ material λ³€μˆ˜μ˜ μžλ£Œν˜•μ„ Object둜 μ‚¬μš©ν•  수 μžˆλ‹€.

(ObjectλŠ” λͺ¨λ“  클래슀의 μ΅œμƒμœ„ ν΄λž˜μŠ€μ΄λ―€λ‘œ λͺ¨λ“  ν΄λž˜μŠ€λŠ” Object둜 λ³€ν™˜ν•  수 있음)

ν•˜μ§€λ§Œ 단점이 μžˆλ‹€. β–Όβ–Ό

setMaterial( ) λ©”μ„œλ“œλ₯Ό ν™œμš©ν•˜μ—¬ Powderλ₯Ό 재료둜 선택할 λ•ŒλŠ” λ§€κ°œλ³€μˆ˜ μžλ£Œν˜•μ΄ Objectμ΄λ―€λ‘œ μžλ™ ν˜•λ³€ν™˜μ΄ λœλ‹€. ν•˜μ§€λ§Œ λ°˜ν™˜ν˜•μ΄ Object 클래슀인 getMaterial( ) λ©”μ„œλ“œλ‘œ Powder μžλ£Œν˜• λ³€μˆ˜λ₯Ό λ°˜ν™˜λ°›μ„ λ•ŒλŠ” λ°˜λ“œμ‹œ ν˜• λ³€ν™˜μ„ ν•΄μ€˜μ•Ό ν•œλ‹€.

즉, μ–΄λ–€ λ³€μˆ˜κ°€ μ—¬λŸ¬ μ°Έμ‘° μžλ£Œν˜•μ„ μ‚¬μš©ν•  수 μžˆλ„λ‘ Object 클래슀λ₯Ό μ‚¬μš©ν•˜λ©΄ λ‹€μ‹œ μ›λž˜ μžλ£Œν˜•μœΌλ‘œ λ°˜ν™˜ν•΄ μ£ΌκΈ° μœ„ν•΄ 맀번 ν˜• λ³€ν™˜μ„ ν•΄μ•Ό ν•˜λŠ” λ²ˆκ±°λ‘œμ›€μ΄ μžˆλ‹€.

​

​

​

*μ œλ„€λ¦­ 클래슀 μ •μ˜ν•˜κΈ°

μ œλ„€λ¦­μ—μ„œλŠ” μ—¬λŸ¬ μ°Έμ‘° μžλ£Œν˜•μ„ μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” 뢀뢄에 Objectκ°€ μ•„λ‹Œ ν•˜λ‚˜μ˜ 문자둜 ν‘œν˜„ν•œλ‹€.

​

μ½”λ“œλ₯Ό 보면 μ—¬λŸ¬ μžλ£Œν˜•μœΌλ‘œ λ°”κΎΈμ–΄ μ‚¬μš©ν•  material λ³€μˆ˜μ˜ μžλ£Œν˜•μ„ T라고 썼닀. 이 λ•Œ Tλ₯Ό μžλ£Œν˜• λ§€κ°œλ³€μˆ˜λΌκ³  λΆ€λ₯Έλ‹€. (T 말고 λ‹€λ₯Έκ±° 써도 됨)

클래슀 이름을 GenericPrinter<T>라고 μ •μ˜ν•˜κ³  λ‚˜μ€‘μ— 클래슀λ₯Ό μ‚¬μš©ν•  λ•Œ T μœ„μΉ˜μ— μ‹€μ œ μ‚¬μš©ν•  μžλ£Œν˜•μ„ μ§€μ •ν•œλ‹€. 클래슀의 각 λ©”μ„œλ“œμ—μ„œ ν•΄λ‹Ή μžλ£Œν˜•μ΄ ν•„μš”ν•œ λΆ€λΆ„μ—λŠ” λͺ¨λ‘ T 문자λ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•œλ‹€.

​

​

​

*μžλ£Œν˜• λ§€κ°œλ³€μˆ˜ T와 static

static λ³€μˆ˜λ‚˜ λ©”μ„œλ“œλŠ” μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ§€ μ•Šμ•„λ„ 클래슀 μ΄λ¦„μœΌλ‘œ ν˜ΈμΆœν•  수 μžˆλ‹€.

static λ³€μˆ˜λŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜κ°€ μƒμ„±λ˜κΈ° 이전에 μƒμ„±λœλ‹€. λ˜ν•œ static λ©”μ„œλ“œμ—μ„œλŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€. 그런데 T의 μžλ£Œν˜•μ΄ μ •ν•΄μ§€λŠ” μˆœκ°„μ€ μ œλ„€λ¦­ 클래슀의 μΈμŠ€ν„΄μŠ€κ°€ μƒμ„±λ˜λŠ” μˆœκ°„μ΄λ‹€. λ”°λΌμ„œ T의 μžλ£Œν˜•μ΄ κ²°μ •λ˜λŠ” μ‹œμ λ³΄λ‹€ λΉ λ₯΄κΈ° λ•Œλ¬Έμ— static λ³€μˆ˜μ˜ μžλ£Œν˜•μ΄λ‚˜ static λ©”μ„œλ“œ λ‚΄λΆ€ λ³€μˆ˜μ˜ μžλ£Œν˜•μœΌλ‘œ Tλ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.

​

​

​

*μ œλ„€λ¦­ 클래슀 μ‚¬μš©ν•˜κΈ°

Powderκ°€ 재료인 PrinterλŠ” λ‹€μŒκ³Ό 같이 μ„ μ–Έν•˜μ—¬ μƒμ„±ν•œλ‹€.

GenericPrinter<Powder> powderPrinter = new GenericPrinter<Powder>();

powderPrinter.setMaterial(new Powder());
Powder powder = powderPrinter.getMaterial();  // λͺ…μ‹œμ  ν˜• λ³€ν™˜μ„ ν•˜μ§€ μ•ŠμŒ

T둜 μ •μ˜ν•œ 클래슀 뢀뢄에 Powderν˜•μ„ λ„£μ–΄ μ£Όκ³ , Tν˜• λ§€κ°œλ³€μˆ˜κ°€ ν•„μš”ν•œ λ©”μ„œλ“œμ— Powder 클래슀λ₯Ό μƒμ„±ν•˜μ—¬ λŒ€μž…ν•΄μ€€λ‹€. GenericPrinter<Powder>μ—μ„œ μ–΄λ–€ μžλ£Œν˜•μ„ μ‚¬μš©ν• μ§€ λͺ…μ‹œν–ˆμœΌλ―€λ‘œ getMaterial( ) λ©”μ„œλ“œμ—μ„œ λ°˜ν™˜ν•  λ•Œ ν˜• λ³€ν™˜μ„ ν•˜μ§€ μ•ŠλŠ”λ‹€. μ΄λ ‡κ²Œ μ‹€μ œ μ œλ„€λ¦­ 클래슀λ₯Ό μ‚¬μš©ν•  λ•Œ T μœ„μΉ˜μ— μ‚¬μš©ν•œ Powderν˜•μ„ 'λŒ€μž…λœ μžλ£Œν˜•'이라 ν•˜κ³ , Powderλ₯Ό λŒ€μž…ν•΄ λ§Œλ“  GenericPrinter<Powder>λ₯Ό 'μ œλ„€λ¦­ μžλ£Œν˜•'이라고 ν•˜κ² λ‹€.

μš©μ–΄

μ„€λͺ…

GenericPrinter<Powder>

μ œλ„€λ¦­ μžλ£Œν˜•(Generic type), λ§€κ°œλ³€μˆ˜ν™”λœ μžλ£Œν˜•(parameterized type)

Powder

λŒ€μž…λœ μžλ£Œν˜•

μ œλ„€λ¦­μœΌλ‘œ κ΅¬ν˜„ν•˜λ©΄ μ™œ ν˜• λ³€ν™˜μ„ ν•˜μ§€ μ•Šμ•„λ„ 될까? μ œλ„€λ¦­ 클래슀λ₯Ό μ‚¬μš©ν•˜λ©΄ μ»΄νŒŒμΌλŸ¬λŠ” 일단 λŒ€μž…λœ μžλ£Œν˜•μ΄ 잘 μ“°μ˜€λŠ”μ§€ ν™•μΈν•œλ‹€. 그리고 class νŒŒμΌμ„ 생성할 λ•Œ Tλ₯Ό μ‚¬μš©ν•œ 곳에 μ§€μ •λœ μžλ£Œν˜•μ— 따라 μ»΄νŒŒμΌν•˜λ―€λ‘œ ν˜• λ³€ν™˜μ„ ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€. λ”°λΌμ„œ μ œλ„€λ¦­μ„ μ‚¬μš©ν•˜λ©΄ μ»΄νŒŒμΌλŸ¬κ°€ μžλ£Œν˜•μ„ 확인해 μ£ΌκΈ° λ•Œλ¬Έμ— μ•ˆμ •μ μ΄λ©΄μ„œ ν˜• λ³€ν™˜ μ½”λ“œκ°€ 쀄어든닀.

​

​

​

*μ œλ„€λ¦­ 클래슀 μ‚¬μš© 예제

 

Powder.java

package generics;

public class Powder {
	public void doPrinting() {
		System.out.println("Powder 재료둜 좜λ ₯ν•©λ‹ˆλ‹€.");
	}

	public String toString() {
		return "μž¬λ£ŒλŠ” Powder μž…λ‹ˆλ‹€.";
	}
}

 

 

Plastic.java

package generics;

public class Plastic {
	public void doPrinting() {
		System.out.println("Plastic 재료둜 좜λ ₯ν•©λ‹ˆλ‹€.");
	}

	public String toString() {
		return "μž¬λ£ŒλŠ” Plastic μž…λ‹ˆλ‹€.";
	}
}

 

 

GenericPrinter.java

package generics;

public class GenericPrinter<T> {
	private T material;  // T μžλ£Œν˜•μœΌλ‘œ μ„ μ–Έν•œ λ³€μˆ˜

	public T getMaterial() {  // T μžλ£Œν˜• λ³€μˆ˜ material을 λ°˜ν™˜ν•˜λŠ” μ œλ„€λ¦­ λ©”μ„œλ“œ
		return material;
	}

	public void setMaterial(T material) {
		this.material = material;
	}

	public String toString() {
		return material.toString();
	}
}

 

 

GenericPrinterTest.java

package generics;

public class GenericPrinterTest {
	public static void main(String[] args) {
		GenericPrinter<Powder> powderPrinter = new GenericPrinter<Powder>();  // Powderν˜•μœΌλ‘œ GenericPrinter 클래슀 생성

		powderPrinter.setMaterial(new Powder());
		Powder powder = powderPrinter.getMaterial(); // λͺ…μ‹œμ  ν˜• λ³€ν™˜μ„ ν•˜μ§€ μ•ŠμŒ
		System.out.println(powderPrinter);

		GenericPrinter<Plastic> plasticPrinter = new GenericPrinter<Plastic>();  // Plasticν˜•μœΌλ‘œ GenericPrinter 클래슀 생성

		plasticPrinter.setMaterial(new Plastic());
		Plastic plastic = plasticPrinter.getMaterial();
		System.out.println(plasticPrinter);
	}
}

<μ‹€ν–‰ κ²°κ³Ό>

 

 

 

β–Ά T μžλ£Œν˜•μ— μ‚¬μš©ν•  μžλ£Œν˜•μ„ μ œν•œν•˜λŠ” <T extends 클래슀>

μ œλ„€λ¦­ ν΄λž˜μŠ€μ—μ„œ T μžλ£Œν˜•μ— μ‚¬μš©ν•  μžλ£Œν˜•μ— μ œν•œμ„ λ‘˜ 수 μžˆλ‹€.

μ‚¬μš©ν•  ν΄λž˜μŠ€μ— μžλ£Œν˜• μ œν•œμ„ λ‘λŠ” λ°©μ‹μœΌλ‘œ extends μ˜ˆμ•½μ–΄λ₯Ό μ‚¬μš©ν•œλ‹€.

​

Material.java

package generics;

public abstract class Material {
	public abstract void doPrinting();
}

 

 

Powder.java

package generics;

public class Powder extends Material {
	public void doPrinting() {
		System.out.println("Powder 재료둜 좜λ ₯ν•©λ‹ˆλ‹€.");
	}

	public String toString() {
		return "μž¬λ£ŒλŠ” Powder μž…λ‹ˆλ‹€.";
	}
}

 

 

Plastic.java

package generics;

public class Plastic extends Material {
	public void doPrinting() {
		System.out.println("Plastic 재료둜 좜λ ₯ν•©λ‹ˆλ‹€.");
	}

	public String toString() {
		return "μž¬λ£ŒλŠ” Plastic μž…λ‹ˆλ‹€.";
	}
}

 

 

 

β–Ά <T extends 클래슀>둜 μƒμœ„ 클래슀 λ©”μ„œλ“œ μ‚¬μš©ν•˜κΈ°

​

GenericPrinter.java

package generics;

public class GenericPrinter<T extends Material> {  // extends μ˜ˆμ•½μ–΄λ‘œ μ‚¬μš©ν•  수 μžˆλŠ” μžλ£Œν˜•μ— μ œν•œμ„ λ‘ 
	private T material;

	public T getMaterial() {
		return material;
	}

	public void setMaterial(T material) {
		this.material = material;
	}

	public String toString() {
		return material.toString();
	}

	public void printing() {
		material.doPrinting();  // μƒμœ„ 클래슀 Material λ©”μ„œλ“œ 호좜
	}
    
}

클래슀 이름에 <T extends Material>이라고 λͺ…μ‹œν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλŠ” μžλ£Œν˜•μ— μ œν•œμ„ λ‘”λ‹€.

<T extends Material>둜 μ„ μ–Έν•˜λ©΄ μ œλ„€λ¦­ 클래슀λ₯Ό μ‚¬μš©ν•  λ•Œ μƒμœ„ 클래슀 Materialμ—μ„œ μ„ μ–Έν•œ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€(ex. doPrinting( ) λ©”μ„œλ“œ). λ§Œμ•½ Material 클래슀λ₯Ό 상속받지 μ•Šμ€ λ‹€λ₯Έ 클래슀λ₯Ό μ‚¬μš©ν•˜λ©΄ 였λ₯˜κ°€ λ‚œλ‹€.

​

<T extends Material>을 μ‚¬μš©ν•˜λ©΄ T μžλ£Œν˜•μ΄ Objectκ°€ μ•„λ‹Œ Material둜 λ³€ν™˜λ˜κ³  μ‚¬μš©ν•˜μ§€ μ•ŠμœΌλ©΄ Tλ₯Ό μ»΄νŒŒμΌν• λ•Œ Object 클래슀둜 λ³€ν™˜λœλ‹€. λ”°λΌμ„œ <T extends Material>λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ€ κ²½μš°μ—λŠ” Object ν΄λž˜μŠ€κ°€ 기본으둜 μ œκ³΅ν•˜λŠ” λ©”μ„œλ“œλ§Œ μ‚¬μš©ν•  수 μžˆλ‹€. μ™œλƒν•˜λ©΄ μžλ£Œν˜•μ„ μ•Œ 수 μ—†κΈ° λ•Œλ¬Έμ΄λ‹€.

​

​

GenericPrinterTest2.java

package generics;

public class GenericPrinterTest2 {
	public static void main(String[] args) {
		GenericPrinter<Powder> powderPrinter = new GenericPrinter<Powder>();
		powderPrinter.setMaterial(new Powder());
		powderPrinter.printing();

		GenericPrinter<Plastic> plasticPrinter = new GenericPrinter<Plastic>();
		plasticPrinter.setMaterial(new Plastic());
		plasticPrinter.printing();
	}
}

<μ‹€ν–‰ κ²°κ³Ό>

​

λ°˜μ‘ν˜•

λŒ“κΈ€