item 62 SeungminLee - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

item 62

λ‹€λ₯Έ νƒ€μž…μ΄ μ μ ˆν•˜λ‹€λ©΄ λ¬Έμžμ—΄ μ‚¬μš©μ„ ν”Όν•˜λΌ

핡심정리

λ°”λ‘œ λ¬Έμžμ—΄μ„ μ“°κΈ° λ³΄λ‹€λŠ” 데이터에 더 μ ν•©ν•œ νƒ€μž…μ„ μ°Ύμ•„μ£Όκ±°λ‚˜ μƒˆλ‘œ μž‘μ„±μ„ ν•˜μž. νŽΈν•˜κΈ° μœ„ν•΄ λ¬Έμžμ—΄μ„ μ‚¬μš©ν•˜λ©΄ κ²°κ΅­ 더 번거럽고, 덜 μœ μ—°ν•˜κ³ , 느리고 였λ₯˜ κ°€λŠ₯성도 컀진닀. λ¬Έμžμ—΄μ„ μ“°κΈ° 전에 더 μ ν•©ν•œ νƒ€μž…μ€ μ—†λŠ”μ§€ κΈ°λ³Ένƒ€μž…, μ—΄κ±° νƒ€μž…, ν˜Όν•© νƒ€μž…μ„ λ‹€μ‹œ ν•œ 번 μƒκ°ν•΄λ³΄μž.

λ¬Έμžμ—΄μ€ λ‹€λ₯Έ κ°’ νƒ€μž…μ„ λŒ€μ‹ ν•˜κΈ°μ— μ ν•©ν•˜μ§€ μ•Šλ‹€.

λ¬Έμžμ—΄μ€ ν…μŠ€νŠΈλ₯Ό ν‘œν˜„ν•˜λ„λ‘ μ„€κ³„λ˜μ—ˆκ³ , κ·Έ 일을 μ•„μ£Ό λ©‹μ§€κ²Œ ν•΄λ‚Έλ‹€. 그런데 λ¬Έμžμ—΄μ΄ μ›Œλ‚™ ν”ν•˜κ³  μžλ°”κ°€ 잘 지원을 ν•΄μ£Όλ‹€λ³΄λ‹ˆ μ›λž˜ μ˜λ„ν•˜μ§€ μ•Šμ€ μš©λ„λ‘œ μ“°μ΄λŠ” κ²½ν–₯이 μžˆλ‹€. λŒ€ν‘œμ μΈ 예둜 λ§Žμ€ μ‚¬λžŒλ“€μ΄ 파일, λ„€νŠΈμ›Œν¬, ν‚€λ³΄λ“œ μž…λ ₯으둜 데이터λ₯Ό μ£Όκ³  받을 λ•Œ 주둜 λ¬Έμžμ—΄μ„ μ‚¬μš©ν•˜λŠ”λ° μ΄λŠ” μ μ ˆν•˜μ§€ μ•Šμ€ 방식이닀.

받은 데이터가 μˆ˜μΉ˜ν˜•μ΄λΌλ©΄ int, float λ“± μ λ‹Ήν•œ 수치 νƒ€μž…μœΌλ‘œ λ³€ν™˜ν•˜λŠ”κ²Œ μ’‹κ³ , 예/μ•„λ‹ˆμ˜€ 질문이라면 μ—΄κ±°νƒ€μž…μ΄λ‚˜ boolean으둜 λ³€ν™˜ν•˜λŠ”κ²Œ μ’‹λ‹€. κΈ°λ³Έ νƒ€μž…μ΄λ“  μ°Έμ‘° νƒ€μž…μ΄λ“  μ μ ˆν•œ κ°’ νƒ€μž…μ΄ μžˆλ‹€λ©΄ 그것을 μ‚¬μš©ν•˜κ³ , μ—†λ‹€λ©΄ μƒˆλ‘œ ν•˜λ‚˜ μž‘μ„±ν•˜λΌ.

λ¬Έμžμ—΄μ€ μ—΄κ±° νƒ€μž…μ„ λŒ€μ‹ ν•˜κΈ°μ— μ ν•©ν•˜μ§€ μ•Šλ‹€.

(μ•„μ΄ν…œ 24) μƒμˆ˜λ₯Ό μ—΄κ±°ν•  λ•ŒλŠ” λ¬Έμžμ—΄λ³΄λ‹€λŠ” μ—΄κ±°νƒ€μž…μ΄ μ›”λ“±νžˆ λ‚«λ‹€.

// 문자 μƒμˆ˜ 
public static final String CHEESE_PIZZA = "cheese pizza"
public static final String CHEESE_BURGER = "cheese burger" 
public static final String CHEESE_STICK = "cheese stick" 

// μ—΄κ±°ν˜•μœΌλ‘œ λ³€ν™˜
public enum Cheese { PIZZA, BURGER, STICK }

λ¬Έμžμ—΄μ€ ν˜Όν•© νƒ€μž…μ„ λŒ€μ‹ ν•˜κΈ°μ— μ ν•©ν•˜μ§€ μ•Šλ‹€.

μ—¬λŸ¬ μš”μ†Œκ°€ ν˜Όν•©λœ 데이터λ₯Ό ν•˜λ‚˜μ˜ λ¬Έμžμ—΄λ‘œ ν‘œν˜„ν•˜λŠ” 것은 λŒ€μ²΄λ‘œ 쒋지 μ•Šμ€ 생각이닀.

String compoundKey = className + "#" + i.next();
  • κ΅¬λΆ„μžμΈ '#' λ¬Έμžκ°€ classNameμ΄λ‚˜ i.next ν˜Όλž€μŠ€λŸ¬μš΄ κ²°κ³Όλ₯Ό μ΄ˆλž˜ν•œλ‹€.
  • 각 μš”μ†Œλ₯Ό κ°œλ³„λ‘œ μ ‘κ·Όν•˜λ €λ©΄ λ¬Έμžμ—΄μ„ νŒŒμ‹±ν•΄μ•Ό ν•΄μ„œ 느리고, 였λ₯˜ κ°€λŠ₯μ„±κΉŒμ§€ 컀진닀.
  • μ μ ν•œ equals, toString, compareTo λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•  수 μ—†μœΌλ©°, String이 μ œκ³΅ν•˜λŠ” κΈ°λŠ₯μ—λ§Œ μ˜μ‘΄ν•΄μ•Ό ν•œλ‹€.
  • 이런 경우 차라리 μ „μš© 클래슀λ₯Ό μƒˆλ‘œ λ§Œλ“œλŠ” 게 μ’‹μœΌλ©° private 정적 맴버 클래슀 ν˜•νƒœλ‘œ λ§Œλ“ λ‹€.
public class TestClass {
	private String dummy; 

	private static class testInnerClass {
		public void printMethod() {}
	}

}

λ¬Έμžμ—΄μ€ κΆŒν•œμ„ ν‘œν˜„ν•˜κΈ°μ— μ ν•©ν•˜μ§€ μ•Šλ‹€.

public class ThreadLocal {
	private ThreadLocal() {}
	
	// ν˜„μž¬ μŠ€λ ˆλ“œμ˜ 값을 ν‚€λ‘œ κ΅¬λΆ„ν•΄μ„œ μ €μž₯ν•œλ‹€.
	public static void set(String key, Object value);

	// ν‚€κ°€ κ°€λ¦¬ν‚€λŠ” ν˜„μž¬ μŠ€λ ˆλ“œμ˜ 값을 λ°˜ν™˜ν•œλ‹€.
	public static Object get(String key);
}

가끔 κΆŒν•œμ„ λ¬Έμžμ—΄λ‘œ ν‘œν˜„ν•˜λŠ” κ²½μš°κ°€ μ’…μ’… μžˆλ‹€. μœ„μ˜ μ½”λ“œλŠ” μŠ€λ ˆλ“œ μ§€μ—­λ³€μˆ˜ κΈ°λŠ₯을 섀계할 λ•Œ 각 μŠ€λ ˆλ“œκ°€ μžμ‹ λ§Œμ˜ λ³€μˆ˜λ₯Ό κ°–κ²Œ ν•΄μ£ΌλŠ” 일을 ν•œλ‹€. 이 μ½”λ“œλŠ” keyλΌλŠ” κΆŒν•œμ„ λ¬Έμžμ—΄λ‘œ κ΄€λ¦¬ν•˜κ³  μžˆλŠ”λ° 무슨 λ¬Έμ œκ°€ μžˆμ„κΉŒ?

  • μŠ€λ ˆλ“œ κ΅¬λΆ„μš© λ¬Έμžμ—΄ ν‚€κ°€ μ „μ—­ μ΄λ¦„κ³΅κ°„μ—μ„œ 곡유되고 μžˆλ‹€.
  • 처음의 μ˜λ„λŒ€λ‘œ λ™μž‘ν•˜λ €λ©΄ 각 ν΄λΌμ΄μ–ΈνŠΈκ°€ κ³ μœ ν•œ ν‚€λ₯Ό μ œκ³΅ν•΄μ•Ό ν•œλ‹€.
  • ν‚€κ°€ μ „μ—­κ³΅κ°„μ—μ„œ 곡유되고 있기 λ•Œλ¬Έμ— μ˜λ„μ§€ μ•Šκ²Œ 같은 ν‚€λ₯Ό μ“°λ©΄ 같은 λ³€μˆ˜λ₯Ό κ³΅μœ ν•˜κ²Œ λœλ‹€.
  • κ²°κ΅­ ν‚€λ₯Ό 가지고 μžˆλŠ” ν΄λΌμ΄μ–ΈνŠΈλ“€μ΄ λͺ¨λ‘ 제 κΈ°λŠ₯을 ν•˜μ§€ λͺ»ν•  것이고, μ•…μ˜μ μΈ ν΄λΌμ΄μ–ΈνŠΈλŠ” 심지어 μ˜λ„μ μœΌλ‘œ 같은 ν‚€λ₯Ό μ‚¬μš©ν•΄ λ‹€λ₯Έ ν΄λΌμ΄μ–ΈνŠΈμ˜ 값을 κ°ˆμ·¨ν•  수 μžˆλ‹€.
  • λ¬Έμžμ—΄ λŒ€μ‹  μœ„μ‘°ν•  수 μ—†λŠ” Key classλ₯Ό μ‚¬μš©ν•΄μ„œ ν•΄κ²°ν•  수 μžˆλ‹€.

ThreadLocal class κ°œμ„ 1

public class ThreadLocal {
	private ThreadLocal() {}
	
	public static class Key {
		Key() {}
	}
	
	// μœ„μ‘°κ°€ λΆˆκ°€λŠ₯ν•œ 고유 ν‚€ 생성
	public static Key getKey() {
		return new Key();
	}

	public static void set(Key key, Object value);
	public static Object get(Key key);
}

ThreadLocal class κ°œμ„  2

public final class ThreadLocal {
	public ThreadLocal();
	
	public void set(Object value);
	public Object get();
}
  • 1μ—μ„œ κ³΅μœ ν•˜μ§€ μ•Šμ€ 고유 keyλ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— κ°œμ„ 2μ—μ„œ getκ³Ό set을 key의 클래슀 μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œλ‘œ λ°”κΏ¨λ‹€.
  • μ΄λ ‡κ²Œ ν•¨μœΌλ‘œ KeyλŠ” 더 이상 μŠ€λ ˆλ“œ μ§€μ—­λ³€μˆ˜λ₯Ό κ΅¬λΆ„ν•˜κΈ° μœ„ν•œ ν‚€κ°€ μ•„λ‹ˆλΌ Key μžμ²΄κ°€ μŠ€λ ˆλ“œ μ§€μ—­λ³€μˆ˜κ°€ λœλ‹€.
  • κ·Έλž˜μ„œ ν†±ν΄λž˜μŠ€μ˜ ThreadLocal을 날렀버리고 Keyλ₯Ό ThreadLocal둜 바꿔버렸닀.
  • 문제점: Objectλ₯Ό μ‹€μ œνƒ€μž…μœΌλ‘œ casting ν•΄μ•Ό ν•΄μ„œ νƒ€μž… μ•ˆμ „ν•˜μ§€ μ•Šλ‹€.
  • νƒ€μž… μ„Έμ΄ν”„ν•˜κ²Œ λ§Œλ“€κΈ° μœ„ν•΄ ThreadLocal을 λ§€κ°œλ³€μˆ˜ν™” νƒ€μž…(μ œλ„€λ¦­)으둜 λ§Œλ“€μ–΄λ³΄μž.

ThreadLocal class μ΅œμ’…λ³Έ

public final class ThreadLocal<T> {
	public ThreadLocal();
	
	public void set(T value);
	public T get();
}

β†’ ν˜Όν•© νƒ€μž…μ„ String으둜 ν‰μΉ˜λŠ” 문제λ₯Ό ν•΄κ²°ν•˜κ³ , ν‚€(String ν‚€, public static class Key) 보닀 λΉ λ₯΄κ³  μš°μ•„ν•œ μ½”λ“œκ°€ μ™„μ„±λ˜μ—ˆλ‹€!