eajni IT μ΄ˆλ³΄μ‚¬μ „ πŸ’¦πŸ’¦

[JAVA] Generic

2022-11-20

μ œλ„€λ¦­μ΄λž€?

클래슀 λ‚΄λΆ€μ—μ„œ μ§€μ •ν•˜λŠ” 것이 μ•„λ‹Œ μ™ΈλΆ€μ—μ„œ μ‚¬μš©μžμ— μ˜ν•΄ μ§€μ •λ˜λŠ” 것을 μ˜λ―Έν•¨.

μ œλ„€λ¦­ μ‚¬μš©μ˜ μž₯점

  1. νƒ€μž… μ•ˆμ •μ„± 보μž₯
    • 컴파일 μ‹œμ μ—μ„œ νƒ€μž… μ—λŸ¬λ₯Ό μž‘μ•„λ‚΄ λŸ°νƒ€μž„ μ‹œμ— λ°œμƒν•  수 μžˆλŠ” μ—λŸ¬λ₯Ό λ°©μ§€
  2. μ½”λ“œ μž¬μ‚¬μš©μ„± 증가
    • μ½”λ“œ μž‘μ„±ν•  λ•Œ νƒ€μž…μ„ μ§€μ •ν•  ν•„μš”κ°€ μ—†μœΌλ―€λ‘œ λ‹€μ–‘ν•œ νƒ€μž…μ— λŒ€ν•΄ μž¬μ‚¬μš©μ„±μ΄ 높아짐.
  3. μ½”λ“œ 가독성 ν–₯상
    • μ½”λ“œλ₯Ό 더 μ§κ΄€μ μœΌλ‘œ μž‘μ„±ν•  수 있음.
  4. ν˜• λ³€ν™˜ 제거
    • ν˜•λ³€ν™˜μ„ μ œκ±°ν•  수 μžˆμ–΄μ„œ μ½”λ“œκ°€ 더 깔끔해지고 간결해짐.
  5. μ»¬λ ‰μ…˜μ—μ„œ μœ μš©ν•¨
    • μ»¬λ ‰μ…˜μ€ λ‹€μ–‘ν•œ νƒ€μž…μ„ 담을 수 μžˆμ–΄μ•Όν•˜λ―€λ‘œ μ œλ„€λ¦­μ˜ νƒ€μž…μ•ˆμ •μ„±κ³Ό ν˜•λ³€ν™˜ 제거둜 μ½”λ“œκ°€ 더 깔끔해짐
  6. μžλ£Œκ΅¬μ‘°μ—μ„œμ˜ ν™œμš©
    • μžλ£Œκ΅¬μ‘°μ—μ„œλ„ λ‹€μ–‘ν•œ νƒ€μž…μ— λŒ€ν•΄ μœ μ—°ν•˜κ²Œ λŒ€μ²˜κ°€λŠ₯. Stack클래슀λ₯Ό κ΅¬ν˜„ν•  λ•Œ μ‚¬μš©ν•˜λ©΄ λ‹€μ–‘ν•œ νƒ€μž…μ˜ μš”μ†Œλ₯Ό 담을 수 μžˆλŠ” μŠ€νƒμ„ κ΅¬ν˜„ν•  수 있음.

μ œλ„€λ¦­ μ‚¬μš© 방법

μ œλ„€λ¦­ νƒ€μž…

νƒ€μž… μ„€λͺ…
<\T> Type
<\E> Element
<\K> Key
<\V> Value
<\N> Number

클래슀 및 μΈν„°νŽ˜μ΄μŠ€ μ„ μ–Έ

기본적인 μ œλ„€λ¦­ νƒ€μž…μ˜ 클래슀 , μΈν„°νŽ˜μ΄μŠ€ μ„ μ–Έ

public class ClassName <T> {...}
public Interface InterfaceName <T> {...}

Tνƒ€μž…μ€ ν•΄λ‹Ή λΈ”λŸ­ {…}μ•ˆμ—μ„œ μœ νš¨ν•¨.

μ œλ„€λ¦­ νƒ€μž…μΈμž 두 개 μ„ μ–Έ

public class ClassName <T,K> {...}
public Interface InterfaceName <T,K> {...}

//λŒ€ν‘œμ μœΌλ‘œ νƒ€μž…μΈμž 두 개 λ°›λŠ” μ»¬λ ‰μ…˜ : HashMap
public class HashMap<K,V> {...}

데이터 νƒ€μž…μ„ μ™ΈλΆ€λ‘œλΆ€ν„° μ§€μ •ν•  수 있음.

μœ„μ²˜λŸΌ μƒμ„±λœ μ œλ„€λ¦­ 클래슀λ₯Ό μ‚¬μš©ν•˜κ³  μ‹Άλ‹€? β†’ 객체 생성을 ν•  λ•Œ ꡬ체적인 νƒ€μž…μ„ λͺ…μ‹œν•΄μ£Όμ–΄μ•Ό 함.

public class ClassName <T,K> {...}

public class Main {
	public static void main(String[] args){
		ClassName<String, Integer> a = new ClassName<String, Integer>();
	}
}

주의! νƒ€μž… νŒŒλΌλ―Έν„°λ‘œ λͺ…μ‹œν•  수 μžˆλŠ” 것은 μ°Έμ‘° νƒ€μž…(Reference Type)밖에 올 수 μ—†μŒ

즉, int, double, char 같은 primitive type은 λΆˆκ°€. κ·Έλž˜μ„œ intν˜• doubleν˜• λ“± primitive Type의 경우 Integer, Double 같은 Wrapper Type으둜 μ“°λŠ” μ΄μœ κ°€ λ°”λ‘œ μœ„μ™€κ°™μ€ μ΄μœ λ‹€.

λ˜ν•œ λ°”κΏ” λ§ν•˜λ©΄ μ°Έμ‘° νƒ€μž…μ΄ 올 수 μžˆλ‹€λŠ” 것은 μ‚¬μš©μžκ°€ μ •μ˜ν•œ ν΄λž˜μŠ€λ„ νƒ€μž…μœΌλ‘œ 올 수 μžˆλ‹€λŠ” 것이닀.

public class ClassName <T> {...}

public class Student {...}

public class Main {
	public static void main(String[] args){
		ClassName<Student> a = new ClassName<Student>();
	}
}

μ œλ„€λ¦­ λ©”μ†Œλ“œ

λ©”μ†Œλ“œμ˜ 선언뢀에 νƒ€μž… λ³€μˆ˜λ₯Ό μ‚¬μš©ν•œ λ©”μ†Œλ“œ μ΄λ•Œ νƒ€μž… λ³€μˆ˜μ˜ 선언은 λ©”μ†Œλ“œ μ„ μ–ΈλΆ€μ—μ„œ λ°˜ν™˜ νƒ€μž… λ°”λ‘œ μ•žμ— μœ„μΉ˜

public static <T> void sort( ... ) { ... }
public <T> T genericMethod(T o){
	...
}
[μ ‘κ·Ό μ œμ–΄μž] <μ œλ„€λ¦­νƒ€μž…> [λ¦¬ν„΄νƒ€μž…] [λ©”μ†Œλ“œλͺ…]([νŒŒλΌλ―Έν„°νƒ€μž…] [νŒŒλΌλ―Έν„°]){
		//ν…μŠ€νŠΈ
}

<?> : μ™€μΌλ“œ μΉ΄λ“œ(Wild card)

νƒ€μž… νŒŒλΌλ―Έν„°λ₯Ό ꡬ체적으둜 μ œν•œ

public static <T extends Number> int compare(T t1, T t2) {
			// extendsλ₯Ό μ΄μš©ν•΄ νƒ€μž… μ œν•œ
	double v1 = t1.doubleValue(); 
	double v2 = t2.doubleValue();
	return Double.compare(v1, v2);
}

μ™€μΌλ“œμΉ΄λ“œ(wild card)λž€ 이름에 μ œν•œμ„ 두지 μ•ŠμŒμ„ ν‘œν˜„ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” 기호λ₯Ό μ˜λ―Έν•¨.

extends 와 super

? extends T : μƒν•œ 경계 ? super T : ν•˜ν•œ 경계 단, 경계λ₯Ό μ§€μ •ν•˜κ³  KλŠ” νŠΉμ • νƒ€μž…μœΌλ‘œ 지정이 λ˜μ§€λ§Œ, ?λŠ” νƒ€μž…μ΄ μ§€μ •λ˜μ§€ μ•ŠλŠ”λ‹€.

<?>Β 

νƒ€μž… λ³€μˆ˜μ— λͺ¨λ“  νƒ€μž…μ„ μ‚¬μš©ν•  수 있음. (<? extends Object>와 같은 의미 )

<?Β extendsΒ T>Β 

T νƒ€μž…κ³Ό T νƒ€μž…μ„Β μƒμ†λ°›λŠ”Β μžμ† 클래슀 νƒ€μž…λ§Œμ„ μ‚¬μš©ν•  수 있음.

<?Β superΒ T>Β 

T νƒ€μž…κ³Ό T νƒ€μž…μ΄Β μƒμ†λ°›μ€ μ‘°μƒΒ ν΄λž˜μŠ€ νƒ€μž…λ§Œμ„ μ‚¬μš©ν•  수 있음.

<K extends T>

T와 T의 μžμ† νƒ€μž…λ§Œ κ°€λŠ₯ (KλŠ” λ“€μ–΄μ˜€λŠ” νƒ€μž…μœΌλ‘œ 지정됨.)

<K super T>

T와 T의 λΆ€λͺ¨(쑰상) νƒ€μž…λ§Œ κ°€λŠ₯ (KλŠ” λ“€μ–΄μ˜€λŠ” νƒ€μž…μœΌλ‘œ 지정됨.)

/*
 * Number와 이λ₯Ό μƒμ†ν•˜λŠ” Integer, Short, Double, Long λ“±μ˜
 * νƒ€μž…μ΄ 지정될 수 있으며, 객체 ν˜Ήμ€ λ©”μ†Œλ“œλ₯Ό 호좜 ν•  경우 KλŠ”
 * μ§€μ •λœ νƒ€μž…μœΌλ‘œ λ³€ν™˜μ΄ λœλ‹€.
 */
<K extends Number>
 
 
/*
 * Number와 이λ₯Ό μƒμ†ν•˜λŠ” Integer, Short, Double, Long λ“±μ˜
 * νƒ€μž…μ΄ 지정될 수 있으며, 객체 ν˜Ήμ€ λ©”μ†Œλ“œλ₯Ό 호좜 ν•  경우 μ§€μ • λ˜λŠ” νƒ€μž…μ΄ μ—†μ–΄
 * νƒ€μž… μ°Έμ‘°λ₯Ό ν•  μˆ˜λŠ” μ—†λ‹€.
 */
<? extends T>	// T와 T의 μžμ† νƒ€μž…λ§Œ κ°€λŠ₯

?(λ¬ΌμŒν‘œ)

μ™€μΌλ“œ μΉ΄λ“œ <?> 은 <? extends Object> 와 κ°™λ‹€.

[ObjectλŠ” μžλ°”μ—μ„œμ˜ λͺ¨λ“  API 및 μ‚¬μš©μž 클래슀의 μ΅œμƒμœ„ νƒ€μž…μ΄λ‹€. ]

public class ClassName { ... }public class ClassName extends Object { ... }

기본적으둜 public class ClassName extends Object {} λ₯Ό λ¬΅μ‹œμ μœΌλ‘œ μƒμ†λ°›λŠ” κ²ƒμ΄λ‚˜ 닀름이 μ—†μŒ!

ν•œλ§ˆλ””λ‘œ <?>은 μ–΄λ–€ νƒ€μž…μ΄λ“  상관 μ—†λ‹€λŠ” 의미.

=> 데이터가 μ•„λ‹Œ 'κΈ°λŠ₯'의 μ‚¬μš©μ—λ§Œ 관심이 μžˆλŠ” κ²½μš°μ— <?>둜 μ‚¬μš©ν•  수 있음

μ œλ„€λ¦­ μ‚¬μš© μ˜ˆμ‹œ

μ œλ„€λ¦­ 클래슀 μ˜ˆμ‹œ

  1. νƒ€μž…μΈμž 1개
class ClassName<E>{
	private E element;  //μ œλ„€λ¦­ νƒ€μž… λ³€μˆ˜ μ„ μ–Έ

	void set(E element) {   // μ œλ„€λ¦­ λ§€κ°œλ³€μˆ˜ λ©”μ†Œλ“œ
		this.element = element;
	}

	E get(){  // μ œλ„€λ¦­ νƒ€μž… λ°˜ν™˜ λ©”μ†Œλ“œ
	return element;
	}

}
public class Main {
	public static void main(String[] args){
		ClassName<String> a = new ClassName<String>();
		ClassName<String> b = new ClassName<String>();

		a.set("10");
		b.set(10);

		System.out.println("a data : " + a.get());
		//λ°˜ν™˜λœ λ³€μˆ˜μ˜ νƒ€μž… 좜λ ₯
		System.out.println("a E Type : " + a.get().getClass().getName());

		System.out.println("b data : " + b.get());
		//λ°˜ν™˜λœ λ³€μˆ˜μ˜ νƒ€μž… 좜λ ₯
		System.out.println("b E Type : " + b.get().getClass().getName());

		}
	}

ClassNameμ΄λž€ 객체λ₯Ό 생성할 λ•Œ <> μ•ˆμ— νƒ€μž… νŒŒλΌλ―Έν„°(Type parameter) E λ₯Ό μ§€μ •.

a객체의 ClassName의 E μ œλ„€λ¦­ νƒ€μž…μ€ String으둜 λͺ¨λ‘ λ³€ν™˜λœλ‹€.

b객체의 ClassName의 E μ œλ„€λ¦­ νƒ€μž…μ€ Integer으둜 λͺ¨λ‘ λ³€ν™˜λœλ‹€.

μ‹€μ œλ‘œ μœ„ μ½”λ“œλ₯Ό μ‹€ν–‰μ‹œν‚€λ©΄ λ‹€μŒκ³Ό 같이 좜λ ₯λœλ‹€.

https://blog.kakaocdn.net/dn/bwZf3n/btqLeqtwL2Z/juSEIt48ifvKRIPZ6PALL1/img.png

  1. νƒ€μž…μΈμž 2개
class ClassName<K,V>{
	private K first;  //K μ œλ„€λ¦­ νƒ€μž…
	private V second; //V μ œλ„€λ¦­ νƒ€μž…

	void set(K first,V second) {   // μ œλ„€λ¦­ λ§€κ°œλ³€μˆ˜ λ©”μ†Œλ“œ
		this.first = first;
		this.second = second;
	}

	K getfirst(){  // μ œλ„€λ¦­ νƒ€μž… λ°˜ν™˜ λ©”μ†Œλ“œ
	return first;
	}

	V getsecond(){
	return second;
	}
}

public class Main {
	public static void main(String[] args){
		ClassName<String,Integer> a = new ClassName<String,Integer>();

		a.set("10",10);

		System.out.println("first data : " + a.getfirst());
		//λ°˜ν™˜λœ λ³€μˆ˜μ˜ νƒ€μž… 좜λ ₯
		System.out.println("K Type : " + a.getfirst().getClass().getName());

		System.out.println("second data : " + second.getsecond());
		//λ°˜ν™˜λœ λ³€μˆ˜μ˜ νƒ€μž… 좜λ ₯
		System.out.println("V Type : " + b.getseconde().getClass().getName());

		}
	}

κ²°κ³Ό


μ œλ„€λ¦­ λ©”μ†Œλ“œ μ˜ˆμ‹œ

λ©”μ†Œλ“œ ν•œμ • μ œλ„€λ¦­ μ‚¬μš©ν•˜λŠ” 방법

// 맀개 λ³€μˆ˜ νƒ€μž…: T
// 리턴 νƒ€μž…: Box<T>
public <T> Box<T> boxing(T t) {
    Box<T> box = new Box<T>();
    box.set(t);
    return box;
}
//호
public class BoxingMethodExample {
	public static void main(String[] args) {
		Box<Integer> box1 = <Integer>boxing(100);
		int intValue = box1.get();
		
		Box<String> box2 = boxing("홍길동");
		String strValue = box2.get();
	}
}


prev [JAVA] OOP

Comments

Content