item 3 Jung inchul - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

Effective Java 3e ์•„์ดํ…œ 3๋ฅผ ์š”์•ฝํ•œ ๋‚ด์šฉ ์ž…๋‹ˆ๋‹ค.

์‹ฑ๊ธ€ํ„ด(singleton)์ด๋ž€ ์ธ์Šคํ„ด์Šค๋ฅผ ์˜ค์ง ํ•˜๋‚˜๋งŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งํ•œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ํด๋ž˜์Šค๋ฅผ ์‹ฑ๊ธ€ํ„ด์œผ๋กœ ๋งŒ๋“ค๋ฉด ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ๋‹ค.

Q1. ์‹ฑ๊ธ€ํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์–ด๋–ค๊ฒƒ๋“ค์ด ์žˆ์„๊นŒ?

  • mokito๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ mockBean์„ ์‚ฌ์šฉ

์‹ฑ๊ธ€ํ„ด์„ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹์€ ๋ณดํ†ต ๋‘˜ ์ค‘ ํ•˜๋‚˜๋‹ค. ๋‘ ๋ฐฉ์‹ ๋ชจ๋‘ ์ƒ์„ฑ์ž๋Š” private์œผ๋กœ ๊ฐ์ถฐ๋‘๊ณ , ์œ ์ผํ•œ ์ธ์Šคํ„ด์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋‹จ์œผ๋กœ public static ๋ฉค๋ฒ„๋ฅผ ํ•˜๋‚˜ ๋งˆ๋ จํ•ด๋‘”๋‹ค.

public class Elvis {
	public static final Elvis INSTANCE = new Elvis();
	private Elvis() { ... }

	public void leaveThebuilding() { ... }
}

private ์ƒ์„ฑ์ž๋Š” public static final ํ•„๋“œ์ธ Elvis.INSTANCE๋ฅผ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋œ๋‹ค.

์˜ˆ์™ธ๋Š” ๋‹จ ํ•œ ๊ฐ€์ง€, ๊ถŒํ•œ์ด ์žˆ๋Š” ํด๋ผ์ด์–ธํŠธ๋Š” ๋ฆฌํ”Œ๋ ‰์…˜ API์ธ AccessibleObject.setAccessible์„ ์‚ฌ์šฉํ•ด private์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•˜๋ ค๋ฉด ์ƒ์„ฑ์ž๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ๋‘ ๋ฒˆ์งธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋ ค ํ•  ๋•Œ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๊ฒŒ ํ•˜๋ฉด ๋œ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์–ด๋–ค ์žฅ์ ์ด ์žˆ์„๊นŒ?

  • public static ํ•„๋“œ๊ฐ€ final์ด๋‹ˆ ์ ˆ๋Œ€๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์—†๋‹ค.
  • ๋‘ ๋ฒˆ์งธ ์žฅ์ ์€ ๋ฐ”๋กœ ๊ฐ„๊ฒฐํ•จ์ด๋‹ค.

Q2. ๋ฆฌํ”Œ๋ ‰์…˜ API๋ž€?

  • ๋Ÿฐํƒ€์ž„์— ๋ฉ”๋ชจ๋ฆฌ์— ํ• ๋‹น๋œ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€๋ฅผ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณตํ•˜๋Š” API
  • Field[] fields = bookClass.getDeclaredFields(); // ํ•ด๋‹น ์ธ์Šคํ„ด์Šค์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์กฐํšŒ

์‹ฑ๊ธ€ํ„ด์„ ๋งŒ๋“œ๋Š” ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์—์„œ๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ public static ๋ฉค๋ฒ„๋กœ ์ œ๊ณตํ•œ๋‹ค.

public class Elvis {
	private static final Elvis INSTANCE = new Elvis();
	private Elvis() { ... }
	public static Elvis getInstance() { return INSTANCE; }

	public void leaveThebuilding() { ... }
}

Elvis.getInstance๋Š” ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ์ฒด์˜ ์ฐธ์กฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ์ œ2์˜ Elvis ์ธ์Šคํ„ด์Šค๋ž€ ๊ฒฐ์ฝ” ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š๋Š”๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์–ด๋–ค ์žฅ์ ์ด ์žˆ์„๊นŒ?

  • API๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๊ณ ๋„ ์‹ฑ๊ธ€ํ„ด์ด ์•„๋‹ˆ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. (์Šค๋ ˆ๋“œ๋ณ„๋กœ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๋ฅผ ๋„˜๊ฒจ์ฃผ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค)
  • ์›ํ•œ๋‹ค๋ฉด ์ •์  ํŒฉํ„ฐ๋ฆฌ๋ฅผ ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒฉํ„ฐ๋ฆฌ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • ์ •์  ํŒฉํ„ฐ๋ฆฌ์˜ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ๊ณต๊ธ‰์ž๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์‹ฑ๊ธ€ํ„ด์„ ๋งŒ๋“œ๋Š” ์„ธ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ์›์†Œ๊ฐ€ ํ•˜๋‚˜์ธ ์—ด๊ฑฐ ํƒ€์ž…์„ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

private Object readResolve() {
	return INSTANCE;
}

public enum Elvis {
	INSTANCE;
	public void leaveTheBuilding() { ... }
}

์กฐ๊ธˆ ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์›Œ ๋ณด์ผ ์ˆ˜๋Š” ์žˆ์œผ๋‚˜ ๋Œ€๋ถ€๋ถ„ ์ƒํ™ฉ์—์„œ๋Š” ์›์†Œ๊ฐ€ ํ•˜๋‚˜๋ฟ์ธ ์—ด๊ฑฐ ํƒ€์ž…์ด ์‹ฑ๊ธ€ํ„ด์„ ๋งŒ๋“œ๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋‹ค.

๋‹จ, ๋งŒ๋“ค๋ ค๋Š” ์‹ฑ๊ธ€ํ„ด์ด Enum ์™ธ์˜ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ด ๋ฐฉ๋ฒ•์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

Q3. ์‹ค๋ฌด์—์„œ Enum์œผ๋กœ ์‹ฑ๊ธ€ํ„ด์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„๊นŒ? ์–ธ์ œ๊ฐ€ ์ ํ•ฉํ• ๊นŒ?