1 ~ 9

์•„์ดํ…œ 1. ์ƒ์„ฑ์ž ๋Œ€์‹  ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ๊ณ ๋ คํ•˜๋ผ


ยท ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ(static factory method)๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

- ์ „ํ†ต์ ์ธ ์ˆ˜๋‹จ: public ์ƒ์„ฑ์ž

- ๋””์ž์ธ ํŒจํ„ด(Gamma95)์˜ ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ์™€๋Š” ๋‹ค๋ฅด๋‹ค. ์ด์™€ ์ผ์น˜ํ•˜๋Š” ํŒจํ„ด์€ ์—†๋‹ค.

์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ์žฅ์ 

1. ์ด๋ฆ„์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

- ์ƒ์„ฑ์ž์— ๋„˜๊ธฐ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ƒ์„ฑ์ž ์ž์ฒด ๋งŒ์œผ๋กœ๋Š” ๋ฐ˜ํ™˜๋  ๊ฐ์ฒด์˜ ํŠน์„ฑ์„ ์ œ๋Œ€๋กœ ์„ค๋ช…ํ•˜์ง€ ๋ชปํ•œ๋‹ค. ๋ฐ˜๋ฉด ์ •์  ํŒฉํ„ฐ๋ฆฌ๋Š” ๋ฐ˜ํ™˜๋  ๊ฐ์ฒด์˜ ํŠน์„ฑ์„ ์‰ฝ๊ฒŒ ๋ฌ˜์‚ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ex) ๊ฐ’์ด ์†Œ์ˆ˜์ธ Integer๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” BigInteger.probablePrime

- ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ƒ์„ฑ์ž๊ฐ€ ์žˆ์„ ๋•Œ, ์—‰๋šฑํ•œ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์‹ค์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํด๋ž˜์Šค ์„ค๋ช… ๋ฌธ์„œ๋ฅผ ์ฐพ์•„๋ณด์ง€ ์•Š๊ณ ๋„ ์˜๋ฏธ๋ฅผ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๋‹ค.

2. ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

- ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ถˆ๋ณ€ ํด๋ž˜์Šค(immutable class ์•„์ดํ…œ 17)๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด ๋†“๊ฑฐ๋‚˜, ์ƒˆ๋กœ ์ƒ์„ฑํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์บ์‹ฑํ•˜์—ฌ ์žฌํ™œ์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.

- ์ƒ์„ฑ๋น„์šฉ์ด ํฌ๊ณ , ์ž์ฃผ ์š”์ฒญ๋˜๋Š” ๊ฐ์ฒด๋ผ๋ฉด ์„ฑ๋Šฅ์„ ์ƒ๋‹นํžˆ ๋Œ์–ด์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋‹ค. ํ”Œ๋ผ์ด์›จ์ดํŠธ ํŒจํ„ด[Gamma97]๋„ ์ด์™€ ๋น„์Šทํ•œ ๊ธฐ๋ฒ•์ด๋‹ค.

- ๋ฐ˜๋ณต๋˜๋Š” ์š”์ฒญ์— ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์‹์œผ๋กœ ์–ด๋Š ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ด์•„ ์žˆ๊ฒŒ ํ• ์ง€ ์ฒ ์ €ํžˆ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋‹ค. ์ธ์Šคํ„ด์Šค ํ†ต์ œ๋Š” ํ”Œ๋ผ์ด์›จ์ดํŠธ ํŒจํ„ด์˜ ๊ทผ๊ฐ„์ด ๋˜๋ฉฐ, ์—ด๊ฑฐ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•˜๋‚˜๋งŒ ๋งŒ๋“ค์–ด์ง์„ ๋ณด์žฅํ•œ๋‹ค.

์ธ์Šคํ„ด์Šค ํ†ต์ œ ์ด์œ  โ†“

๋”๋ณด๊ธฐ

TODO: ํ”Œ๋ผ์ด์›จ์ดํŠธํŒจํ„ด

3. ๋ฐ˜ํ™˜ ํƒ€์ž…์˜ ํ•˜์œ„ ํƒ€์ž… ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

- ๋ฐ˜ํ™˜ํ•  ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.

- ์œ ์—ฐ์„ฑ์„ ์‘์šฉํ•˜์—ฌ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ๊ณต๊ฐœํ•˜์ง€ ์•Š๊ณ ๋„ ๊ทธ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์–ด API๋ฅผ ์ž‘๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

- ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ ํ”„๋ ˆ์ž„์›Œํฌ(์•„์ดํ…œ20)๋ฅผ ๋งŒ๋“œ๋Š” ํ•ต์‹ฌ ๊ธฐ์ˆ ์ด๊ธฐ๋„ ํ•˜๋‹ค.

๋”๋ณด๊ธฐ

4. ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋”ฐ๋ผ ๋งค๋ฒˆ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ์ฒด๋“ค์˜ ์กด์žฌ๋ฅผ ๋ชจ๋ฅธ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ ๋ฒ„์ „์—์„œ ์›ํ•˜๋Š”๋Œ€๋กœ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํŽธ๋ฆฌํ•˜๋‹ค.

ex) EnumSet ํด๋ž˜์Šค๋Š” Public ์ƒ์„ฑ์ž ์—†์ด ์ •์  ํŒฉํ„ฐ๋ฆฌ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ, ์›์†Œ๊ฐ€ 64๊ฐœ ์ดํ•˜๋ฉด long ๋ณ€์ˆ˜ ํ•˜๋‚˜๋กœ ๊ด€๋ฆฌํ•˜๋Š” RegularEnumSet์˜ ์ธ์Šคํ„ด์Šค๋ฅผ, 65๊ฐœ ์ด์ƒ์ด๋ฉด long ๋ฐฐ์—ด๋กœ ๊ด€๋ฆฌํ•˜๋Š” JumboEnumSet์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. (OpenJDK๊ธฐ์ค€)

5. ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์‹œ์ ์— ๋ฐ˜ํ™˜ํ•  ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

- ์ด๋Ÿฐ ์œ ์—ฐํ•จ์€ ์„œ๋น„์Šค ์ œ๊ณต์ž ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋“œ๋Š” ๊ทผ๊ฐ„์ด ๋œ๋‹ค. ex)JDBC

- ์ œ๊ณต์ž(provider): ์„œ๋น„์Šค์˜ ๊ตฌํ˜„์ฒด๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” ์—ญํ• ์„ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํ†ต์ œํ•˜์—ฌ, ํด๋ผ์ด์–ธํŠธ์˜ ๊ตฌํ˜„์ฒด๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌํ•ด์ค€๋‹ค.

์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ๋‹จ์ 

1. ์ƒ์†์„ ํ•˜๋ ค๋ฉด public์ด๋‚˜ protected ์ƒ์„ฑ์ž๊ฐ€ ํ•„์š”ํ•˜๋‹ˆ ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋งŒ ์ œ๊ณตํ•˜๋ฉด ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค.

- ์ƒ์†๋ณด๋‹ค ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉ(์•„์ดํ…œ 18)ํ•˜๋„๋ก ์œ ๋„ํ•˜๊ณ , ๋ถˆ๋ณ€ ํƒ€์ž…์œผ๋กœ ๋งŒ๋“ค๋ ค๋ฉด ์ด ์ œ์•ฝ์„ ์ง€์ผœ์•ผ ํ•œ๋‹ค๋Š” ์ ์—์„œ ์˜คํžˆ๋ ค ์žฅ์ ์œผ๋กœ ๋ฐ›์•„๋“ค์ผ ์ˆ˜๋„ ์žˆ๋‹ค.

2. ์ €์ • ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ฐพ๊ธฐ ์–ด๋ ต๋‹ค.

- ์ƒ์„ฑ์ž์ฒ˜๋Ÿผ API ์„ค๋ช…์— ๋ช…ํ™•ํžˆ ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์‚ฌ์šฉ์ž๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ ๋ฐฉ์‹ ํด๋ž˜์Šค๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•  ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ด์•ผ ํ•œ๋‹ค.

- API ๋ฌธ์„œ๋ฅผ ์ž˜ ์จ๋†“๊ณ , ๋ฉ”์„œ๋“œ ์ด๋ฆ„๋„ ๋„๋ฆฌ ์•Œ๋ ค์ง„ ๊ทœ์•ฝ์„ ๋”ฐ๋ผ ์ง“๋Š” ์‹์œผ๋กœ ๋ฌธ์ œ๋ฅผ ์™„ํ™”ํ•˜์ž.

์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ ๋ช…๋ช… ๋ฐฉ์‹

ยท from - ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ•˜๋‚˜๋งŒ ๋ฐ›์•„์„œ ํ•ด๋‹น ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ

์˜ˆ์‹œ) Date date = Date.from(dateStr);

ยท of - ์—ฌ๋Ÿฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„ ์ ํ•ฉํ•œ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ง‘๊ณ„ ๋ฉ”์„œ๋“œ

์˜ˆ์‹œ) Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);

ยท valueOf - from๊ณผ of์˜ ๋” ์ž์„ธํ•œ ๋ฒ„์ „

์˜ˆ์‹œ) BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);

ยท instance(getInstance) - ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๋Š”๋‹ค๋ฉด, ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ช…์‹œํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ, ๊ฐ™์€ ์ธ์Šคํ„ด์Šค์ž„์„ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค. ์‹ฑ๊ธ€ํ„ด์ผ ์ˆ˜๋„ ์žˆ๋‹ค.

์˜ˆ์‹œ) StackWalker luke = StackWalker.getInstance(options);

ยท create(newInstance) - instance/getInstance์™€ ๊ฐ™์ง€๋งŒ, ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•จ์„ ๋ณด์žฅํ•œ๋‹ค.

ยท getType - getInstance์™€ ๋งฅ๋ฝ์€ ๊ฐ™์œผ๋‚˜ ํŠน์ • Type์„ ๋ฐ˜ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉ

์˜ˆ์‹œ) Steak steak = Food.getSteak(Meet.BEEF);

ยท newType - newInstance์™€ ๊ฐ™์œผ๋‚˜, ์ƒ์„ฑํ•  ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ ํ•  ๋•Œ ์‚ฌ์šฉ

์˜ˆ์‹œ) Steak steak = Food.newSteak(Meet.BEEF);

ยท Type - getType, newType์˜ ๊ฐ™๊ฒฐํ•œ ๋ฒ„์ „

์˜ˆ์‹œ) Steak steak = Food.steak(Meet.BEEF);

์•„์ดํ…œ 2. ์ƒ์„ฑ์ž์— ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ๋‹ค๋ฉด ๋นŒ๋”๋ฅผ ๊ณ ๋ คํ•˜๋ผ


ยท ์ •์  ํŒฉํ„ฐ๋ฆฌ์™€ ์ƒ์„ฑ์ž๋Š” ์„ ํƒ์  ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ์„ ๋•Œ ์ ์ ˆํžˆ ๋Œ€์‘ํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋Š” ์ œ์•ฝ์ด ์žˆ๋‹ค.

ยท ์ด๋Ÿฌํ•œ ๋ฌธ์ œ์˜ ๋Œ€์•ˆ์œผ๋กœ ์ ์ธต์  ์ƒ์„ฑ์ž ํŒจํ„ด(telescoping constructor pattern)๊ณผ ์ž๋ฐ”๋นˆ์ฆˆ ํŒจํ„ด์ด ๋“ฑ์žฅํ–ˆ์ง€๋งŒ, ํ•œ๊ณ„๊ฐ€ ์กด์žฌํ•œ๋‹ค.

๋”๋ณด๊ธฐ

ยท ์ ์ธต์  ์ƒ์„ฑ์ž ํŒจํ„ด์˜ ์•ˆ์ „์„ฑ๊ณผ ์ž๋ฐ”๋นˆ์ฆˆ ํŒจํ„ด์˜ ๊ฐ€๋…์„ฑ์„ ๊ฒธ๋น„ํ•œ ๋นŒ๋” ํŒจํ„ด์œผ๋กœ ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํด๋ผ์ด์–ธํŠธ๋Š” ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ๋งŒ๋“œ๋Š” ๋Œ€์‹ , ํ•„์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋งŒ์œผ๋กœ ์ƒ์„ฑ์ž๋‚˜ ์ •์  ํŒฉํ„ฐ๋ฆฌ๋ฅผ ํ˜ธ์ถœํ•ด ๋นŒ๋” ๊ฐ์ฒด๋ฅผ ์–ป๊ณ , ๋นŒ๋” ๊ฐ์ฒด๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์„ธํ„ฐ ๋ฉ”์„œ๋“œ๋“ค๋กœ ์›ํ•˜๋Š” ์„ ํƒ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜๊ณ , ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” build ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ๊ฐ์ฒด๋ฅผ ์–ป๋Š”๋‹ค.

๋นŒ๋” ํŒจํ„ด ์˜ˆ์‹œ

class NutritionFacts{
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;
    
    public static class Builder{
        // ํ•„์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜
        private final int servingSize;
        private final int servings;
        
        // ์„ ํƒ ๋งค๊ฐœ๋ณ€์ˆ˜
        private int calories     = 0;
        private int fat          = 0;
        private int sodium       = 0;
        private int carbohydrate = 0;
        
        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings = servings;
        }
        
        public Builder calories(int calories){
            this.calories = calories;
            return this;
        }
        
        public Builder fat(int fat){
            this.fat = fat;
            return this;
        }
        
        public Builder sodium(int sodium){
            this.sodium = sodium;
            return this;
        }
        
        public Builder carbohydrate(int carbohydrate){
            this.carbohydrate = carbohydrate;
            return this;
        }
        
        public NutritionFacts build(){
            return new NutritionFacts(this);
        }
    }
    
    private NutritionFacts(Builder builder){
        servingSize  = builder.servingSize;
        servings     = builder.servings;
        calories     = builder.calories;
        fat          = builder.fat;
        sodium       = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }
}

๋นŒ๋” ํŒจํ„ด ์‚ฌ์šฉ๋ฒ•

ยท ์ด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋Š” ์“ฐ๊ธฐ ์‰ฝ๊ณ  ์ฝ๊ธฐ ์‰ฝ๋‹ค.

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
    .calories(100)
    .sodium(35)
    .carbohydrate(27).build();

ยท ๋นŒ๋” ํŒจํ„ด์€ ํŒŒ์ด์ฌ๊ณผ ์Šค์นผ๋ผ์— ์žˆ๋Š” ๋ช…๋ช…๋œ ์„ ํƒ์  ๋งค๊ฐœ๋ณ€์ˆ˜(named optional parameters)๋ฅผ ํ‰๋‚ด ๋‚ธ ๊ฒƒ์ด๋‹ค.

ยท ๋นŒ๋”์˜ ์„ธํ„ฐ ๋ฉ”์„œ๋“œ๋“ค์„ ๋นŒ๋” ์ž์‹ ์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋–„๋ฌธ์— ์—ฐ์‡„์ ์œผ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์„ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด ํ๋ฅด๋“ฏ ์—ฐ๊ฒฐ๋œ๋‹ค๋Š” ๋œป์œผ๋กœ ํ”Œ๋ฃจ์–ธํŠธ API ํ˜น์€ ๋ฉ”์„œ๋“œ ์—ฐ์‡„๋ผ ํ•œ๋‹ค.

ยท ์ž˜๋ชป๋œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ผ์ฐ ๋ฐœ๊ฒฌํ•˜๊ธฐ์œ„ํ•ด ๋นŒ๋”์˜ ์ƒ์„ฑ์ž์™€ ๋ฉ”์„œ๋“œ์—์„œ ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฒ€์‚ฌํ•˜๊ณ , build ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœํ•˜๋Š” ์ƒ์„ฑ์ž์—์„œ ์—ฌ๋Ÿฌ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๊ฑธ์นœ ๋ถˆ๋ณ€์‹์„ ๊ฒ€์‚ฌํ•˜์ž.

- ๋ถˆ๋ณ€(immutable ํ˜น์€ immutability): ์–ด๋– ํ•œ ๋ณ€๊ฒฝ๋„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋œป์œผ๋กœ ๋ณ€๊ฒฝ์„ ํ—ˆ์šฉํ•˜๋Š” ๊ฐ€๋ณ€(mutable) ๊ฐ์ฒด์™€ ๊ตฌ๋ถ„ํ•˜๋Š” ์šฉ๋„๋กœ ์“ฐ์ธ๋‹ค.

ยท ๋นŒ๋” ํŒจํ„ด์€ ๊ณ„์ธต์ ์œผ๋กœ ์„ค๊ณ„๋œ ํด๋ž˜์Šค์™€ ํ•จ๊ป˜ ์“ฐ๊ธฐ์— ์ข‹๋‹ค.

public abstract class Pizza{
    public enum Topping { HAM, MUSHROOM, ONION, PEPPER, SAUSAGE }
    final Set<Topping> toppings;
        
        abstract static class Builder<T extends Builder<T>>{
            EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
                public T addTopping(Topping topping){
                    toppings.add(Objects.requireNonNull(topping));
                    return self();
                }
                abstract Pizza build();
                
                protected abstract T self();
                }
                
                Pizza(Builder<?> builder){
                    toppings = builder.toppings.clone();
                }
                
                }
public class NyPizza extends Pizza{
    public enum Size { SMALL, MEDIUM, LARGE }
    private final Size size;
    
    public static class Builder extends Pizza.Builder<Builder>{
        private final Size size;
        
        public Builder(Size size){
            this.size = Objects.requireNonNull(size);
        }
        
        @Override public NyPizza build(){
            return new NyPizza(this);
        }
        
        @Override protected Builder self(){
            return this;
        }
    }
    
    private NyPizza(Builder builder){
        super(builder);
        size = builder.size();
    }
    
    }
public class Calzone extends Pizza{
    private final boolean sauceInside;
    
    public static class Builder extends Pizza.Builder<Builder>{
        private boolean sauceInside = false;
        
        public Builder sauceInside(){
            sauceInside = true;
            return this;
        }
        
        @Override public Calzone builde(){
            return new Calzone(this);
        }
        
        @Override protected Builder self(){ return this; }
    }
    private Calzone(Builder builder){
        super(builder);
        sauceInside = builder.sauceInside;
    }
    }
// ๊ฐ์ฒด ์ƒ์„ฑ
NyPizza pizza = new NyPizza.Builder(SMALL)
    .addTopping(SAUSAGE).addTopping(ONION).build();
Calzone calzone = new Calzone.Builder()
    .addTopping(HAM).sauceInside().build();

ยท Pizza.Builder ํด๋ž˜์Šค๋Š” ์žฌ๊ท€์  ํƒ€์ž… ํ•œ์ •์„ ์ด์šฉํ•˜๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด๋‹ค. ์—ฌ๊ธฐ์— ์ถ”์ƒ ๋ฉ”์„œ๋“œ์ธ self๋ฅผ ๋”ํ•ด ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ํ˜•๋ณ€ํ™˜ํ•˜์ง€ ์•Š๊ณ ๋„ ๋ฉ”์„œ๋“œ ์—ฐ์‡„๋ฅผ ์ง€์›ํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ๊ฐ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๋นŒ๋”๊ฐ€ ์ •์˜ํ•œ build ๋ฉ”์„œ๋“œ๋Š” ํ•ด๋‹นํ•˜๋Š” ๊ตฌ์ฒด ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์˜ํ•œ ๋ฐ˜ํ•œ ํƒ€์ž…์ด ์•„๋‹Œ, ๊ทธ ํ•˜์œ„ ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ณต๋ณ€๋ฐ˜ํ™˜ ํƒ€์ดํ•‘(covariant return typing)์ด๋ผ ํ•œ๋‹ค. ์ด ๊ธฐ๋Šฅ์„ ์ด์šฉํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ˜•๋ณ€ํ™˜์— ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š๊ณ  ๋นŒ๋”๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ๋นŒ๋” ํŒจํ„ด์€ ์œ ์—ฐํ•˜๋‹ค. ๋นŒ๋” ํ•˜๋‚˜๋กœ ์—ฌ๋Ÿฌ ๊ฐ์ฒด๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ณ , ๋นŒ๋”์— ๋„˜๊ธฐ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ๊ณ , ๊ฐ์ฒด๋งˆ๋‹ค ๋ถ€์—ฌ๋˜๋Š” ์ผ๋ จ๋ฒˆํ˜ธ์™€ ๊ฐ™์€ ํŠน์ • ํ•„๋“œ๋Š” ๋นŒ๋”๊ฐ€ ์•Œ์•„์„œ ์ฑ„์šฐ๋„๋ก ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋‹จ์ 

ยท ๋นŒ๋” ์ƒ์„ฑ ๋น„์šฉ์ด ํฌ์ง€๋Š” ์•Š์ง€๋งŒ ์„ฑ๋Šฅ์— ๋ฏผ๊ฐํ•œ ์ƒํ™ฉ์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.

ยท ์ฝ”๋“œ๊ฐ€ ์žฅํ™ฉํ•˜๋‹ค.

+ ์ถ”๊ฐ€์ ์ธ ๋ฐฉ๋ฒ•

1. ํ•„๋“œ ๊ฐ’๋งŒ ๋“ค์–ด์žˆ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด DIํ•œ๋‹ค.

2. Map ๊ฐ’์„ ํด๋ž˜์Šค ํ•„๋“œ๋กœ๋กœ ์˜ฎ๊ธด๋‹ค.

์•„์ดํ…œ 3. private ์ƒ์„ฑ์ž๋‚˜ ์—ด๊ฑฐ ํƒ€์ž…์œผ๋กœ ์‹ฑ๊ธ€ํ„ด์„ ๋ณด์ฆํ•˜๋ผ


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

ex) ํ•จ์ˆ˜์™€ ๊ฐ™์€ ๋ฌด์ƒํƒœ ๊ฐ์ฒด, ์„ค๊ณ„์ƒ ์œ ์ผํ•ด์•ผ ํ•˜๋Š” ์‹œ์Šคํ…œ ์ปดํฌ๋„ŒํŠธ

์‹ฑ๊ธ€ํ„ด์˜ ๋ฌธ์ œ์ 

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

- ํƒ€์ž…์„ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ •์˜ํ•œ ํ›„ ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ๋งŒ๋“  ์‹ฑ๊ธ€ํ„ด์ด ์•„๋‹ˆ๋ผ๋ฉด ์‹ฑ๊ธ€ํ„ด ์ธ์Šคํ„ด์Šค๋ฅผ mock ๊ตฌํ˜„์œผ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์‹ฑ๊ธ€ํ„ด์„ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹

1. public static ๋ฉค๋ฒ„๊ฐ€ final ํ•„๋“œ์ธ ๋ฐฉ์‹

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

ยท ์žฅ์ : ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์‹ฑ๊ธ€ํ„ด์ž„์ด API์— ๋ช…๋ฐฑํžˆ ๋“œ๋Ÿฌ๋‚œ๋‹ค. public static ํ•„๋“œ๊ฐ€ final์ด๋‹ˆ ์ ˆ๋Œ€๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์—†๋‹ค.

ยท ๋ฌธ์ œ์ :

1. ๊ถŒํ•œ์ด ์žˆ๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ฆฌํ”Œ๋ ‰์…˜ API์ธ AccessibleObject.setAccessible์„ ์‚ฌ์šฉํ•ด private ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœ ํ•  ์ˆ˜ ์žˆ๋‹ค.

2. ์ƒ์„ฑ๋˜๋Š” ์‹œ์ ์„ ์กฐ์ ˆํ•  ์ˆ˜ ์—†๋‹ค. (ํด๋ž˜์Šค๊ฐ€ ๋‹ค๋ฅธ ์ž์›(DB์ปค๋„ฅ์…˜ ๋“ฑ)์— ์˜์กดํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ด์šฉ ๋ถˆ๊ฐ€๋Šฅ)

- ๋ฐฉ์–ด ๋ฐฉ๋ฒ•: ์ƒ์„ฑ์ž๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ๋‘ ๋ฒˆ์งธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋ ค ํ•  ๋•Œ ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค.

2. ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ public static ๋ฉค๋ฒ„๋กœ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ์‹

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

ยท ์žฅ์ :

1. API๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๊ณ ๋„ ์‹ฑ๊ธ€ํ„ด์ด ์•„๋‹ˆ๊ฒŒ ๋ณ€๊ผ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

ex) ์œ ์ผํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋˜ ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœํ•˜๋Š” ์Šค๋ ˆ๋“œ๋ณ„๋กœ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค.

2. ์ •์  ํŒฉํ„ฐ๋ฆฌ๋ฅผ ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒฉํ„ฐ๋ฆฌ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. (์•„์ดํ…œ30)

3.์ •์  ํŒฉํ„ฐ๋ฆฌ์˜ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ๊ณต๊ธ‰์ž(supplier)๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ex) Elvis::getInstance๋ฅผ Supplier<Elvis>๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. (์•„์ดํ…œ 43, 44)

ยท ๋ฌธ์ œ์ : ๋ฆฌํ”Œ๋ ‰์…˜์„ ํ†ตํ•œ ์˜ˆ์™ธ๋Š” ๋˜‘๊ฐ™์ด ์ ์šฉ๋œ๋‹ค.

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

ยท ๋‘˜ ์ค‘ ํ•˜๋‚˜์˜ ๋ฐฉ์‹์œผ๋กœ ๋งŒ๋“  ์‹ฑ๊ธ€ํ„ด ํด๋ž˜์Šค๋ฅผ ์ง๋ ฌํ™”ํ•˜๋ ค๋ฉด, Serializable์„ ๊ตฌํ˜„ํ•œ๋‹ค๊ณ  ์„ ์–ธํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋Š” ๋ถ€์กฑ ํ•˜๋‹ค.

- ๋ชจ๋“  ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋ฅผ transient๋กœ ์„ ์–ธํ•˜๊ณ , readResolve ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค. (์•„์ดํ…œ 89)

- ์ด๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š์œผ๋ฉด, ์ง๋ ฌํ™”๋œ ์ธ์Šคํ„ด์Šค๋ฅผ ์—ญ์ง๋ ฌํ™”ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๊ฐ€ ๋งŒ๋“ค์–ด ์ง„๋‹ค.

// ์‹ฑ๊ธ€ํ„ด์ž„์„ ๋ณด์žฅํ•ด์ฃผ๋Š” readResolve ๋ฉ”์„œ๋“œ
private Object readResolve() {
    // '์ง„์งœ' Elvis๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฐ€์งœ Elvis๋Š” ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์— ๋งก๋‹ค.
    return INSTANCE;
}

3. ์›์†Œ๊ฐ€ ํ•˜๋‚˜์ธ ์—ด๊ฑฐ ํƒ€์ž…์„ ์„ ์–ธํ•œ๋‹ค.

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

ยท ์žฅ์ :

1. ๊ฐ„๊ฒฐํ•˜๋‹ค.

2. ์ถ”๊ฐ€ ๋…ธ๋ ฅ ์—†์ด ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

3. ์•„์ฃผ ๋ณต์žกํ•œ ์ง๋ ฌํ™” ์ƒํ™ฉ์ด๋‚˜ ๋ฆฌํ”Œ๋ ‰์…˜ ๊ณต๊ฒฉ์—๋„ ์ œ2์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ๊ธฐ๋Š” ์ผ์„ ์™„๋ฒฝํžˆ ๋ง‰์•„์ค€๋‹ค.

ยท ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ์‹ฑ๊ธ€ํ„ด์„ ๋งŒ๋“œ๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋‹ค.

ยท ๋ฌธ์ œ์ : ์‹ฑ๊ธ€ํ„ด์ด Enum ์™ธ์˜ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ์ด ๋ฐฉ๋ฒ•์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

- ์—ด๊ฑฐ ํƒ€์ž…์ด ๋‹ค๋ฅธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ์„ ์–ธํ•  ์ˆ˜ ์—†๋‹ค.

์•„์ดํ…œ 4. ์ธ์Šคํ„ด์Šค๋ฅผ ๋ง‰์œผ๋ ค๊ฑฐ๋“  private ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ผ


ยท ์ •์  ๋ฉ”์„œ๋“œ์™€ ์ •์  ํ•„๋“œ๋งŒ ๋‹ด์€ ํด๋ž˜์Šค๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ์ ์œผ๋กœ ์‚ฌ๊ณ ํ•˜์ง€ ์•Š๋Š” ์‚ฌ๋žŒ๋“ค์ด ์ข…์ข… ๋‚จ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด์ง€๋งŒ, ๋‚˜๋ฆ„์˜ ์“ฐ์ž„์ƒˆ๊ฐ€ ์žˆ๋‹ค.

1. java.lang.Math, java.util.Arrays์ฒ˜๋Ÿผ ๊ธฐ๋ณธ ํƒ€์ž… ๊ฐ’์ด๋‚˜ ๋ฐฐ์—ด ๊ด€๋ จ ๋ฉ”์„œ๋“œ๋“ค์„ ๋ชจ์•„๋†“์„ ์ˆ˜ ์žˆ๋‹ค.

2. java.util.Collections์ฒ˜๋Ÿผ ํŠน์ • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” ์ •์  ๋ฉ”์„œ๋“œ(ํ˜น์€ ํŒฉํ„ฐ๋ฆฌ)๋ฅผ ๋ชจ์•„๋†“์„ ์ˆ˜ ์žˆ๋‹ค.

(์ž๋ฐ” 8 ๋ถ€ํ„ฐ๋Š” ์ด๋Ÿฐ ๋ฉ”์„œ๋“œ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค)

3. final ํด๋ž˜์Šค์™€ ๊ด€๋ จ๋œ ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ์•„ ๋†“์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. final ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ด์„œ ํ•˜์œ„ ํด๋ž˜์Šค์— ๋ฉ”์„œ๋“œ๋ฅผ ๋„ฃ๋Š” ๊ฑด ๋ถˆ๊ฐ€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ยท ์ •์  ๋ฉค๋ฒ„๋งŒ ๋‹ด์€ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค๋Š” ์ธ์Šคํ„ด์Šค๋กœ ๋งŒ๋“ค์–ด ์“ฐ๋ ค๊ณ  ์„ค๊ณ„ํ•œ ๊ฒŒ ์•„๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ private ์ƒ์„ฑ์ž๋ฅผ ์ถ”๊ฐ€ํ•ด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šคํ™”๋ฅผ ๋ง‰์•„์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. (์ƒ์„ฑ์ž๋ฅผ ๋ช…์‹œํ•˜์ง€ ์•Š์œผ๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ž๋™์œผ๋กœ ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ ๋‹ค)

// ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค
public class UtilityClass {
    // ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฒƒ์„ ๋ง‰๋Š”๋‹ค(์ธ์Šคํ„ด์Šคํ™” ๋ฐฉ์ง€์šฉ).
    // ์•…์˜์  ๋ฆฌํ”Œ๋ ‰์…˜์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.
    private UtilityClass() {
        throw new AssertionError();
    }
}

ยท ์ƒ์„ฑ์ž๊ฐ€ ๋ถ„๋ช… ์กด์žฌํ•˜๋Š”๋ฐ ํ˜ธ์ถœํ•  ์ˆ˜๋Š” ์—†๋‹ค๋‹ˆ, ๊ทธ๋‹ค์ง€ ์ง๊ด€์ ์ด์ง€ ์•Š์œผ๋ฏ€๋กœ ์•ž์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ ์ ˆํ•œ ์ฃผ์„์„ ๋‹ฌ์•„์ค€๋‹ค.

ยท ์ด ๋ฐฉ์‹์€ ์ƒ์†์„ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ํšจ๊ณผ๋„ ์žˆ๋‹ค. ๋ชจ๋“  ์ƒ์„ฑ์ž๋Š” ๋ช…์‹œ์ ์ด๋“  ๋ฌต์‹œ์ ์ด๋“  ์ƒ์œ„ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•ด์•ผํ•˜๋Š”๋ฐ, ์ด๋ฅผ private ์„ ์–ธ์œผ๋กœ ๋ง‰์•„๋ฒ„๋ ธ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์•„์ดํ…œ 5. ์ž์›์„ ์ง์ ‘ ๋ช…์‹œํ•˜์ง€ ๋ง๊ณ  ์˜์กด ๊ฐ์ฒด ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋ผ


ยท ๋งŽ์€ ํด๋ž˜์Šค๊ฐ€ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ž์›์— ์˜์กดํ•œ๋‹ค. ์‚ฌ์šฉํ•˜๋Š” ์ž์›์— ๋”ฐ๋ผ ๋™์ž‘์ด ๋‹ฌ๋ผ์ง€๋Š” ํด๋ž˜์Šค์— ๊ฒฝ์šฐ ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ ์ž์› ์ธ์Šคํ„ด์Šค๋ฅผ ์ง€์›ํ•ด์•ผ ํ•˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” ์ž์›์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

ยท ์ด ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ฐ„๋‹จํ•œ ํŒจํ„ด์œผ๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์ƒ์„ฑ์ž์— ํ•„์š”ํ•œ ์ž์›์„ ๋„˜๊ฒจ์ฃผ๋Š” ๋ฐฉ์‹์ด์žˆ๋‹ค. ์ด๋Š” ์˜์กด ๊ฐ์ฒด ์ฃผ์ž…์˜ ํ•œ ํ˜•ํƒœ๋‹ค. ์•„๋ž˜๋Š” ์‚ฌ์ „(dictionary)์— ์˜์กดํ•˜๋Š” ๋งž์ถค๋ฒ• ๊ฒ€์‚ฌ๊ธฐ ํด๋ž˜์Šค๋‹ค.

public class SpellChecker {
    private final Lexicon dictionary;
    
    // ์—ฌ๊ธฐ์„œ ์˜์กด์„ฑ ์ฃผ์ž…์„!
    public SpellChecker(Lexicon dictionary){
        this.dictionary = Objects.requireNotNull(dictionary);
    }
    
    public static boolean isVaild(String word) {...}
    public static List<String> suggestions(String typo) {...}
        }

ยท ์˜์กด ๊ฐ์ฒด ์ฃผ์ž… ํŒจํ„ด์˜ ์žฅ์ :

1. ์ž์›์ด ๋ช‡ ๊ฐœ๋“  ์˜์กด ๊ด€๊ณ„๊ฐ€ ์–ด๋–ป๊ทผ ์ƒ๊ด€์—†์ด ์ž˜ ๋™์ž‘ํ•œ๋‹ค.

2. ๋ถˆ๋ณ€(์•„์ดํ…œ17)์„ ๋ณด์žฅํ•˜์—ฌ ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์˜์กด ๊ฐ์ฒด๋ฅผ ์•ˆ์‹ฌํ•˜๊ณ  ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

ยท ์˜์กด ๊ฐ์ฒด ์ฃผ์ž…์€ ์ƒ์„ฑ์ž, ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ชจ๋‘์— ๋˜‘๊ฐ™์ด ์‘์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ์ด ํŒจํ„ด์˜ ์“ธ๋งŒํ•œ ๋ณ€ํ˜•์œผ๋กœ, ์ƒ์„ฑ์ž์— ์ž์› ํŒฉํ„ฐ๋ฆฌ๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š” ๋ฐฉ์‹์ด ์žˆ๋‹ค. ์ฆ‰, ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด(Gamma95)์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

- ํŒฉํ„ฐ๋ฆฌ: ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ํŠน์ • ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ฐ์ฒด

ยท ์ž๋ฐ” 8์—์„œ ์†Œ๊ฐœํ•œ Supplier<T> ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํŒฉํ„ฐ๋ฆฌ๋ฅผ ํ‘œํ˜„ํ•œ ์™„๋ฒฝํ•œ ์˜ˆ๋‹ค.

ยท Supplier<T>๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…(bounded wildcard type, ์•„์ดํ…œ 31)์„ ์‚ฌ์šฉํ•ด ํŒฉํ„ฐ๋ฆฌ์˜ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ œํ•œํ•ด์•ผํ•œ๋‹ค. ์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ด ํด๋ผ์ด์–ธํŠธ๋Š” ์ž์‹ ์ด ๋ช…์‹œํ•œ ํƒ€์ž…์˜ ํ•˜์œ„ ํƒ€์ž…์ด๋ผ๋ฉด ๋ฌด์—‡์ด๋“  ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ํŒฉํ„ฐ๋ฆฌ๋ฅผ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค.

- ์˜ˆ์‹œ) ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ œ๊ณตํ•œ ํŒฉํ„ฐ๋ฆฌ๊ฐ€ ์ƒ์„ฑํ•œ ํƒ€์ผ๋“ค๋กœ ์ฟ ์„ฑ๋œ ๋ชจ์ž์ดํฌ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฉ”์„œ๋“œ

Mosaic create(Supplier<? extends Tile> tileFactory) { ... }

ยท ์˜์กด ๊ฐ์ฒด ์ฃผ์ž…์€ ์œ ์—ฐ์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ๊ฐœ์„ ํ•ด์ค€๋‹ค.

ยท ํ•˜์ง€๋งŒ ์˜์กด์„ฑ์ด ๋งŽ์€ ํฐ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ฝ”๋“œ๋ฅผ ์–ด์ง€๋Ÿฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ๋„ ํ•œ๋‹ค. ์ด๋Ÿด๋–„ ๋Œ€๊ฑฐ, ์ฃผ์Šค, ์Šคํ”„๋ง ๊ฐ™์€ ์˜์กด ๊ฐ์ฒด ์ฃผ์ž… ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ํด๋ž˜์Šค๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ž์›์— ์˜์กดํ•˜๊ณ , ๊ทธ ์ž์›์ด ํด๋ž˜์Šค ๋™์ž‘์— ์˜ํ–ฅ์„ ์ค€๋‹ค๋ฉด ์‹ฑ๊ธ€ํ„ด๊ณผ ์ •์  ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์ด ์ž์›๋“ค์„ ํด๋ž˜์Šค๊ฐ€ ์ง์ ‘ ๋งŒ๋“ค๊ฒŒ ํ•ด์„œ๋„ ์•ˆ๋œ๋‹ค.

- ์ •์  ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์ž˜๋ชป ์‚ฌ์šฉํ•œ ์˜ˆ: ์œ ์—ฐํ•˜์ง€ ์•Š๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

public class SpellChecker {
    private static final Lexicon dictionary = ...;
    
    private SpellChecker() {} // ์ธ์Šคํ„ด์Šคํ™” ๋ฐฉ์ง€ (์•„์ดํ…œ 4 ์ฐธ๊ณ )
    
    public static boolean isVaild(String word) {...}
    public static List<String> suggestions(String typo) {...}
        }

- ์‹ฑ๊ธ€ํ„ด์„ ์ž˜๋ชป ์‚ฌ์šฉํ•œ ์˜ˆ: ์œ ์—ฐํ•˜์ง€ ์•Š๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

public class SpellChecker {
    private final Lexicon dictionary = ...;
    
    private SpellChecker() {} // ์ธ์Šคํ„ด์Šคํ™” ๋ฐฉ์ง€ (์•„์ดํ…œ 4 ์ฐธ๊ณ )
    public static SpellChecker INSTANCE = new SpellChecker(...);
    
    public static boolean isVaild(String word) {...}
    public static List<String> suggestions(String typo) {...}
        }

์•„์ดํ…œ 6. ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ์„ ํ”ผํ•˜๋ผ


ยท ๋˜‘๊ฐ™์€ ๊ธฐ๋Šฅ์˜ ๊ฐ์ฒด๋ฅผ ๋งค๋ฒˆ ์ƒ์„ฑํ•˜๊ธฐ๋ณด๋‹ค ๊ฐ์ฒด ํ•˜๋‚˜๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ๋‚˜์„ ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ์žฌ์‚ฌ์šฉ์€ ๋น ๋ฅด๊ณ  ์„ธ๋ จ๋˜๋‹ค. ํŠนํžˆ ๋ถˆ๋ณ€ ๊ฐ์ฒด(์•„์ดํ…œ 17)๋Š” ์–ธ์ œ๋“  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ์ƒ์„ฑ์ž ๋Œ€์‹  ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋งค์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ถˆ๋ณ€ ํด๋ž˜์Šค์—์„œ๋Š” ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.

ex) Boolean(String) ์ƒ์„ฑ์ž ๋Œ€์‹  Boolean.valueOf(String) ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

ยท ๊ฐ€๋ณ€ ๊ฐ์ฒด๋ผ ํ•ด๋„ ์ˆ˜์šฉ ์ค‘์— ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์„ ๊ฒƒ์ž„์„ ์•ˆ๋‹ค๋ฉด ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ์ƒ์„ฑ ๋น„์šฉ์ด ์•„์ฃผ ๋น„์‹ผ ๊ฐ์ฒด๊ฐ€ ๋ฐ˜๋ณตํ•ด์„œ ํ•„์š”ํ•˜๋‹ค๋ฉด, ์บ์‹ฑํ•˜์—ฌ ์žฌ์‚ฌ์šฉํ•˜๊ธธ ๊ถŒํ•œ๋‹ค.

ex) ์•„๋ž˜๋Š” ์ฃผ์–ด์ง„ ๋ฌธ์ž์—ด์ด ์œ ํšจํ•œ ๋กœ๋งˆ ์ˆซ์ž์ธ์ง€ ํ™•์ธํ•˜๋Š” ๋ฉ”์„œ๋“œ๋‹ค. ํ•˜์ง€๋งŒ String.matches ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

public class RomanNumerals {
    static boolean isRomanNumeral(String s) {
        return s.matches("^(?=.)M*(C[MD]|D?C{0,3})" +
            "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})");
    }
}

- String.matches๋Š” ์„ฑ๋Šฅ์ด ์ค‘์š”ํ•œ ์ƒํ™ฉ์—์„œ ๋ฐ˜๋ณตํ•ด ์‚ฌ์šฉํ•˜๊ธฐ์— ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค.

1. ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ๋งŒ๋“œ๋Š” ์ •๊ทœํ‘œํ˜„์‹์šฉ Pattern ์ธ์Šคํ„ด์Šค๋Š” ํ•œ ๋ฒˆ ์“ฐ๊ณ  ๋ฒ„๋ ค์ ธ์„œ ๊ณง๋ฐ”๋กœ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ๋Œ€์ƒ์ด ๋œ๋‹ค.

2. Pattern์€ ์ž…๋ ฅ๋ฐ›์€ ์ •๊ทœํ‘œํ˜„์‹์— ํ•ด๋‹นํ•˜๋Š” ์œ ํ•œ ์ƒํƒœ ๋จธ์‹ (finite state machine)์„ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ๋น„์šฉ์ด ๋†’๋‹ค.

TODO: ์œ ํ•œ ์ƒํƒœ ๋จธ์‹ ์ด๋ž€?

- ๋ถˆ๋ณ€์ธ Pattern ์ธ์Šคํ„ด์Šค๋ฅผ ํด๋ž˜์Šค ์ดˆ๊ธฐํ™”(์ •์  ์ดˆ๊ธฐํ™”) ๊ณผ์ •์—์„œ ์ง์ ‘ ์ƒ์„ฑํ•ด ์บ์‹ฑํ•ด๋‘๊ณ , ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ๋Š” ์„ฑ๋Šฅ๋งŒ ์ข‹์•„์ง„ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ฝ”๋“œ๋„ ๋” ๋ช…ํ™•ํ•ด์กŒ๋‹ค.

public class RomanNumerals {
    private static final Pattern ROMAN = Pattern.compile("^(?=.)M*(C[MD]|D?C{0,3})" +
        "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})");
    
    static boolean isRomanNumeral(String s) {
        return ROMAN.matcher(s).matches();
    }
}

- isRomanNumeral ๋ฉ”์„œ๋“œ๊ฐ€ ์ฒ˜์Œ ํ˜ธ์ถœ๋  ๋•Œ ํ•„๋“œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋„๋ก ์ง€์—ฐ ์ดˆ๊ธฐํ™”๋กœ ๋ถˆํ•„์š”ํ•œ ์ดˆ๊ธฐํ™”๋ฅผ ์—†์•จ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๊ถŒํ•˜์ง€ ์•Š๋Š”๋‹ค.

- ์ง€์—ฐ ์ดˆ๊ธฐํ™”๋Š” ์ฝ”๋“œ๋ฅผ ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“œ๋Š”๋ฐ, ์„ฑ๋Šฅ์€ ํฌ๊ฒŒ ๊ฐœ์„ ๋˜์ง€ ์•Š์„ ๋•Œ๊ฐ€ ๋งŽ๋‹ค(์•„์ดํ…œ 67).

ยท ๊ฐ์ฒด๊ฐ€ ๋ถˆ๋ณ€์ด๋ผ๋ฉด ์žฌ์‚ฌ์šฉํ•ด๋„ ์•ˆ์ ํ•จ์ด ๋ช…๋ฐฑํ•˜์ง€๋งŒ, ํ›จ์”ฌ ๋œ ๋ช…ํ™•ํ•˜๊ฑฐ๋‚˜, ์ง๊ด€์— ๋ฐ˜๋Œ€๋˜๋Š” ์ƒํ™ฉ๋„ ์žˆ๋‹ค.

ex) ์–ด๋Œ‘ํ„ฐ[Gamma95]๋ฅผ ์˜ˆ๋กœ ๋“ค๋ฉด, ์–ด๋Œ‘ํ„ฐ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋’ค์— ์žˆ๋Š” ๊ฐ์ฒด๋กœ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” view๋ผ ์—ฌ๋Ÿฌ ๊ฐœ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†๋‹ค.

- ์–ด๋Œ‘ํ„ฐ: ์‹ค์ œ ์ž‘์—…์€ ๋’ท๋‹จ ๊ฐ์ฒด์— ์œ„์ž„ํ•˜๊ณ , ์ž์‹ ์€ ์ œ2์˜ ์ธํ„ฐํŽ˜์ด์Šค ์—ญํ• ์„ ํ•ด์ฃผ๋Š” ๊ฐ์ฒด

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๋ฅผ ๋Œ€๋ณ€ํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ง์ž.

Map<String, Object> map = new HashMap<>();
    map.put("Hello", "World");
    
    Set<String> set1 = map.keySet();
        Set<String> set2 = map.keySet();
            
            assertThat(set1).isSameAs(set2); // TRUE
            
            set1.remove("Hello");
            System.out.println(set1.size()); // 1
            System.out.println(set1.size()); // 1

ยท ์˜คํ† ๋ฐ•์‹ฑ์€ ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์„ฑ๋Šฅ์— ํ•ด๋กœ์šธ ์ˆ˜ ์žˆ๋‹ค.

- ์˜คํ† ๋ฐ•์‹ฑ: ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๊ธฐ๋ณธ ํƒ€์ž…๊ณผ ๋ฐ•์‹ฑ๋œ ๊ธฐ๋ณธ ํƒ€์ž…์„ ์„ž์–ด ์“ธ ๋•Œ ์ž๋™์œผ๋กœ ์ƒํ˜ธ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ๊ธฐ์ˆ 

ex) ๋‹ค์Œ์€ sum ๋ณ€์ˆ˜๋ฅผ long์ด ์•„๋‹Œ Long์œผ๋กœ ์„ ์–ธํ•ด์„œ ๋ถˆํ•„์š”ํ•œ Long ์ธ์Šคํ„ด์Šค๊ฐ€ ์•ฝ 231๊ฐœ๋‚˜ ๋งŒ๋“ค์–ด ์ง„๋‹ค.

public class Sum {
    private static long sum() {
        Long sum = 0L;
        for (long i = 0; i <= Integer.MAX_VALUE; i++) {
            sum += i;
        }
        return sum;
    }
}

ยท ๊ฐ์ฒด ์ƒ์„ฑ์€ ๋ฌด์กฐ๊ฑด ๋น„์‹ธ๋‹ˆ ํ”ผํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋žจ์˜ ๋ช…ํ™•์„ฑ, ๊ฐ„๊ฒฐ์„ฑ, ๊ธฐ๋Šฅ์„ ์œ„ํ•ด ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€๋กœ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ข‹๋‹ค.

ยท ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๊ฐ™์€ ์ƒ์„ฑ ๋น„์šฉ์ด ๋งค์šฐ ๋น„์‹ผ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๊ฐ์ฒด ํ’€์„ ๋งŒ๋“ค์ง€ ๋ง์ž. ์ผ๋ฐ˜์ ์œผ๋กœ ์ž์ฒด ๊ฐ์ฒด ํ’€์€ ์ฝ”๋“œ๋ฅผ ํ—ท๊ฐˆ๋ฆฌ๊ฒŒ ๋งŒ๋“ค๊ณ , ์‚ฌ์šฉ๋Ÿ‰์„ ๋Š˜๋ฆฌ๊ณ , ์„ฑ๋Šฅ์„ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค.

ยท ์ด๋ฒˆ ์•„์ดํ…œ์€ ๋ฐฉ์–ด์  ๋ณต์‚ฌ(defensive copy)๋ฅผ ๋‹ค๋ฃจ๋Š” ์•„์ดํ…œ 50๊ณผ ๋Œ€์กฐ์ ์ด๋‹ค.

- ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ๋งˆ๋ผ vs ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋ฉด ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์ง€ ๋งˆ๋ผ

- ๋ฐฉ์–ด์  ๋ณต์‚ฌ๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์—์„œ ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ํ”ผํ•ด๊ฐ€ ํ•„์š” ์—†๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ˜๋ณต ์ƒ์„ฑํ–ˆ์„ ๋•Œ ํ”ผํ•ด๋ณด๋‹ค ํ›จ์”ฌ ํฌ๋‹ค.

- ๋ฐฉ์–ด์  ๋ณต์‚ฌ์— ์‹คํŒจํ•˜๋ฉด ๋ฒ„๊ทธ์™€ ๋ณด์•ˆ ๊ตฌ๋ฉ์œผ๋กœ ์ด์–ด์ง€์ง€๋งŒ, ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ์€ ๊ทธ์ € ์ฝ”๋“œ ํ˜•ํƒœ์™€ ์„ฑ๋Šฅ์—๋งŒ ์˜ํ–ฅ์„ ์ค€๋‹ค.



์•„์ดํ…œ 7. ๋‹ค ์“ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•˜๋ผ


ยท ์•„๋ž˜ ์Šคํƒ ํด๋ž˜์Šค๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

- ์ด ์Šคํƒ์„ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์˜ค๋ž˜ ์‹คํ–‰ํ•˜๋‹ค ๋ณด๋ฉด ์ ์ฐจ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ํ™œ๋™๊ณผ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ๋Š˜์–ด๋‚˜ ๊ฒฐ๊ตญ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋œ๋‹ค.

- ๋“œ๋ฌผ๊ธด ํ•˜์ง€๋งŒ ์‹ฌํ•  ๋•Œ๋Š” ๋””์Šคํฌ ํŽ˜์ด์ง•์ด๋‚˜ OutOfMemoryError๋ฅผ ์ผ์œผ์ผœ ํ”„๋กœ๊ทธ๋žจ์ด ์˜ˆ๊ธฐ์น˜ ์•Š๊ฒŒ ์ข…๋ฃŒ๋œ๋‹ค.

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    
    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }
    
    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }
    
    public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        return elements[--size];
    }
    
    private void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}

ยท pop ๋ฉ”์„œ๋“œ์—์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

- ์Šคํƒ์ด ์ปค์กŒ๋‹ค๊ฐ€ ์ค„์–ด๋“ค ๋•Œ, ์Šคํƒ์—์„œ ๊บผ๋‚ด์ง„ ๊ฐ์ฒด๋“ค์€ ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ํšŒ์ˆ˜ํ•˜์ง€ ์•Š๋Š”๋‹ค.

- ๊บผ๋‚ด์ง„ ๊ฐ์ฒด๋“ค์ด ๋‹ค ์“ด ์ฐธ์กฐ(obsolete reference)๋ฅผ ์—ฌ์ „ํžˆ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

- elements ๋ฐฐ์—ด์˜ 'ํ™œ์„ฑ ์˜์—ญ'๋ฐ–์˜ ์ฐธ์กฐ๋“ค์ด ๋ชจ๋‘ ์—ฌ๊ธฐ์— ํ•ด๋‹นํ•œ๋‹ค. ํ™œ์„ฑ ์˜์—ญ์€ ์ธ๋ฑ์Šค๊ฐ€ size๋ณด๋‹ค ์ž‘์€ ์›์†Œ๋“ค๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

- ๋‹ค์“ด ์ฐธ์กฐ: ์•ž์œผ๋กœ ๋‹ค์‹œ ์“ฐ์ง€ ์•Š์„ ์ฐธ์กฐ

ยท ๊ฐ์ฒด ์ฐธ์กฐ ํ•˜๋‚˜๋ฅผ ์‚ด๋ ค๋‘๋ฉด ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๋Š” ๊ทธ ๊ฐ์ฒด๋ฟ ์•„๋‹ˆ๋ผ ๊ทธ ๊ฐ์ฒด๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๋ชจ๋“  ๊ฐ์ฒด(๋˜ ๊ทธ ๊ฐ์ฒด๋“ค์ด ์ฐธ์กฐํ•˜๋Š” ๋ชจ๋“  ๊ฐ์ฒด)๋ฅผ ํšŒ์ˆ˜ํ•ด๊ฐ€์ง€ ๋ชปํ•œ๋‹ค.

- ๋‹จ ๋ช‡ ๊ฐœ์˜ ๊ฐ์ฒด๊ฐ€ ๋งค์šฐ ๋งŽ์€ ๊ฐ์ฒด๋ฅผ ํšŒ์ˆ˜๋˜์ง€ ๋ชปํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๊ณ , ์ž ์žฌ์ ์œผ๋กœ ์„ฑ๋Šฅ์— ์•…์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

ยท ์ฐธ์กฐ๋ฅผ ๋‹ค ์ผ์„ ๋•Œ null(์ฐธ์กฐ ํ•ด์ œ)ํ•œ๋‹ค.

public Object pop() {
    if (size == 0)
        throw new EmptyStackException();
    Object result = elements[--size];
    elements[size] = null; // ๋‹ค ์“ด ์ฐธ์กฐ ํ•ด์ œ
    return result;
}

ยท ๋‹ค์“ด ์ฐธ์กฐ๋ฅผ null ํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ฅ˜๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

- null ์ฒ˜๋ฆฌํ•œ ์ฐธ์กฐ๋ฅผ ์‹ค์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋ ค ํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์€ ์ฆ‰์‹œ NullPointerException์„ ๋˜์ง€๋ฉฐ ์ข…๋ฃŒ๋œ๋‹ค.

- null ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์•„๋ฌด ๋‚ด์ƒ‰ ์—†์ด ๋ฌด์–ธ๊ฐ€ ์ž˜๋ชป๋œ ์ผ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ null ์ฒ˜๋ฆฌํ•˜๋Š” ์ผ์€ ์˜ˆ์™ธ์ ์ธ ๊ฒฝ์šฐ์—ฌ์•ผ ํ•œ๋‹ค. ๋‹ค ์“ด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ๊ทธ ์ฐธ์กฐ๋ฅผ ๋‹ด์€ ๋ณ€์ˆ˜๋ฅผ ์œ ํšจ ๋ฒ”์œ„(scope) ๋ฐ–์œผ๋กœ ๋ฐ€์–ด๋‚ด๋Š” ๊ฒƒ์ด๋‹ค.

- ๋ณ€์ˆ˜์˜ ๋ฒ”์œ„๋ฅผ ์ตœ์†Œ๋กœ ๋˜๊ฒŒ ์ •์˜ํ–ˆ๋‹ค๋ฉด(์•„์ดํ…œ 57) ์ด ์ผ์€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด๋ค„์ง„๋‹ค.

- null ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์•ž์„  ์ฝ”๋“œ์˜ ์Šคํƒ ์ฒ˜๋Ÿผ ์ž๊ธฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค์ด๋‹ค. ๋น„ํ™œ์„ฑ ์˜์—ญ์—์„œ ์ฐธ์กฐํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ๋” ์ด์ƒ ์“ธ๋ชจ์—†๋‹ค๋Š” ๊ฒƒ์„ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋งŒ ์•Œ์ง€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๋Š” ์•Œ์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด๋Ÿด ๋•Œ๋Š” null ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์—ฌ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์— ์ง์ ‘ ์•Œ๋ ค์•ผํ•œ๋‹ค.

ยท ์บ์‹œ ์—ญ์‹œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์ผ์œผํ‚ค๋Š” ์ฃผ๋ฒ”์ด๋‹ค.

- ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ๋‹ค ์“ด ๋’ค ํ•จ์ฐธ์„ ๊ทธ๋ƒฅ ๋†”๋‘๋Š” ์ผ์„ ์ž์ฃผ ์ ‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•1: ์™ธ๋ถ€์—์„œ ํ‚ค๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋™์•ˆ๋งŒ ์—”ํŠธ๋ฆฌ๊ฐ€ ์‚ด์•„ ์žˆ๋Š” ์บ์‹œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, WeakHashMap์„ ์‚ฌ์šฉํ•ด ์บ์‹œ๋ฅผ ๋งŒ๋“ ๋‹ค.

๋‹ค ์“ด ์—”ํŠธ๋ฆฌ๋Š” ์ฆ‰์‹œ ์ž๋™์œผ๋กœ ์ œ๊ฑฐ๋œ๋‹ค.

- ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•2: ์บ์‹œ๋ฅผ ๋งŒ๋“ค ๋•Œ ๋ณดํ†ต ์บ์‹œ ์—”ํŠธ๋ฆฌ์˜ ์œ ํšจ ๊ธฐ๊ฐ„์„ ์ •ํ™•ํžˆ ์ •์˜ํ•˜๊ธฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐ„์ด ์ง€๋‚ ์ˆ˜๋ก ์—”ํŠธ๋ฆฌ์˜ ๊ฐ€์น˜๋ฅผ ๋–จ์–ด๋œจ๋ฆฌ๋Š” ๋ฐฉ์‹์ด ํ”ํžˆ ์‚ฌ์šฉ๋œ๋‹ค. ์ด๋Ÿฐ ๋ฐฉ์‹์—์„œ๋Š” ์“ฐ์ง€ ์•Š๋Š” ์—”ํŠธ๋ฆฌ๋ฅผ ์ด๋”ฐ๊ธˆ ์ฒญ์†Œํ•ด์•ผํ•œ๋‹ค. ScheduledThreadPoolExecutor ๊ฐ™์€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๋ฅผ ํ™œ์šฉํ•˜๊ฑฐ๋‚˜ ์บ์‹œ์— ์ƒˆ ์—”ํŠธ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ๋ถ€์ˆ˜ ์ž‘์—…์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

- LinkedHahshMap์€ removeEldestEntry ๋ฉ”์„œ๋“œ๋ฅผ ์จ์„œ ํ›„์ž์˜ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.

- ๋” ๋ณต์žกํ•œ ์บ์‹œ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด java.lang.ref ํŒจํ‚ค์ง€๋ฅผ ์ง์ ‘ ํ™œ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์•„์ดํ…œ 8. finalizer์™€ cleaner ์‚ฌ์šฉ์„ ํ”ผํ•˜๋ผ


ยท ์ž๋ฐ”๋Š” finalizer, cleaner ๋‘ ๊ฐ€์ง€ ๊ฐ์ฒด ์†Œ๋ฉธ์ž๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

ยท finalizer๋Š” ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๊ณ , ์ƒํ™ฉ์— ๋”ฐ๋ผ ์œ„ํ—˜ํ•  ์ˆ˜ ์žˆ์–ด ์ผ๋ฐ˜์ ์œผ๋กœ ๋ถˆํ•„์š”ํ•˜๋‹ค.

- ์˜ค๋™์ž‘, ๋‚ฎ์€ ์„ฑ๋Šฅ, ์ด์‹์„ฑ ๋ฌธ์ œ์˜ ์›์ธ์ด ๋˜๊ธฐ๋„ ํ•œ๋‹ค.

ยท ์ž๋ฐ” 9์—์„œ finalizer๊ฐ€ deprecated๋˜๊ณ , cleaner๋ฅผ ๊ทธ ๋Œ€์•ˆ์œผ๋กœ ์†Œ๊ฐœํ–ˆ์ง€๋งŒ, ์—ฌ์ „ํžˆ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๊ณ , ๋Š๋ฆฌ๊ณ , ์ผ๋ฐ˜์ ์œผ๋กœ ๋ถˆํ•„์š”ํ•˜๋‹ค.

ยท C++์—์„œ์˜ ํŒŒ๊ดด์ž(destructor)์™€ ์ž๋ฐ”์˜ finalizer, cleaner๋Š” ๋‹ค๋ฅธ ๊ฐœ๋…์ด๋‹ค.

- C++์˜ ํŒŒ๊ดด์ž๋Š” ๋น„๋ฉ”๋ชจ๋ฆฌ ์ž์›์„ ํšŒ์ˆ˜ํ•˜๋Š” ์šฉ๋„๋กœ ์“ฐ์ด๊ณ , ์ž๋ฐ”์—์„œ๋Š” try-with-resources์™€ try-finally๋ฅผ ์‚ฌ์šฉํ•ด ํ•ด๊ฒฐํ•œ๋‹ค.

finalizer์™€ cleaner์˜ ๋ถ€์ž‘์šฉ

ยท finalizer์™€ cleaner๋Š” ์ฆ‰์‹œ ์ˆ˜ํ–‰๋œ๋‹ค๋Š” ๋ณด์žฅ์ด ์—†๊ณ , ์‹คํ–‰๋˜๊ธฐ๊นŒ์ง€ ์–ผ๋งˆ๋‚˜ ๊ฑธ๋ฆด์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.

- ๋”ฐ๋ผ์„œ ํŒŒ์ผ ๋‹ซ๊ธฐ์™€ ๊ฐ™์ด ์ œ๋•Œ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ž‘์—…์„ ๋‘˜์—๊ฒŒ ๋งก๊ธฐ๋ฉด ์ค‘๋Œ€ํ•œ ์˜ค๋ฅ˜๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ์‹œ์Šคํ…œ์ด ๋™์‹œ์— ์—ด ์ˆ˜ ์žˆ๋Š” ํŒŒ์ผ ๊ฐœ์ˆ˜์— ํ•œ๊ณ„๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ƒˆ๋กœ์šด ํŒŒ์ผ์„ ์—ด์ง€ ๋ชปํ•ด ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํŒจํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ์ž๋ฐ” ์–ธ์–ด ๋ช…์„ธ๋Š” finalizer๋‚˜ clearner์˜ ์ˆ˜ํ–‰ ์‹œ์ ๋ฟ ์•„๋‹ˆ๋ผ ์ˆ˜ํ–‰ ์—ฌ๋ถ€์กฐ์ฐจ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

ยท System.gc๋‚˜ System.runFinalization ๋ฉ”์„œ๋“œ๊ฐ€ finalize์™€ cleaner๊ฐ€ ์‹คํ–‰๋  ๊ฐ€๋Šฅ์„ฑ์„ ๋†’์—ฌ์ค„ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋ณด์žฅํ•ด์ฃผ์ง„ ์•Š๋Š”๋‹ค.

- System.runFinalizerOnExit๊ณผ Runtime.runFinalizerOnExit ๋ฉ”์„œ๋“œ๊ฐ€ ์ด๋ฅผ ๋ณด์žฅํ•ด์ค„ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋‘ ๋ฉ”์„œ๋“œ๋Š” ThreadStop์ด๋ผ๋Š” ์‹ฌ๊ฐํ•œ ๊ฒฐํ•จ์ด ์žˆ๋‹ค.

ยท finalizer ๋™์ž‘ ์ค‘ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋Š” ๋ฌด์‹œ๋˜๋ฉฐ, ์ฒ˜๋ฆฌํ•  ์ž‘์—…์ด ๋‚จ์•˜๋”๋ผ๋„ ๊ทธ ์ˆœ๊ฐ„ ์ข…๋ฃŒ๋œ๋‹ค. ๊ฒฝ๊ณ ์กฐ์ฐจ ์ถœ๋ ฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

- ํ•ด๋‹น ๊ฐ์ฒด๋Š” ๋งˆ๋ฌด๋ฆฌ๊ฐ€ ๋œ ๋œ ์ƒํƒœ๋กœ ๋‚จ์•„ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ํ›ผ์†๋œ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

(cleaner๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ž์‹ ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ํ†ต์ œํ•˜๋ฏ€๋กœ ์ด๋Ÿฐ ๋ฌธ์ œ๋Š” ๋ฐœ์ƒ x)

ยท finalizer์™€ cleaner๋Š” ์‹ฌ๊ฐํ•œ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ๋™๋ฐ˜ํ•œ๋‹ค.

- ์ €์ž์˜ ์ปดํ“จํ„ฐ์—์„œ AutoCloseable ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ์ˆ˜๊ฑฐํ•˜๊ธฐ๊นŒ์ง€ 12ns๊ฐ€ ๊ฑธ๋ฆฐ ๋ฐ˜๋ฉด, finalizer๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด 550ns๊ฐ€ ๊ฑธ๋ ธ๋‹ค. cleaner๋„ ์ด์™€ ๋น„์Šทํ•˜๋‹ค.

ยท finalizer๋ฅผ ์‚ฌ์šฉํ•œ ํด๋ž˜์Šค๋Š” finalizer ๊ณต๊ฒฉ์— ๋…ธ์ถœ๋˜์–ด ์‹ฌ๊ฐํ•œ ๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

- finalizer ๊ณต๊ฒฉ: ์ƒ์„ฑ์ž๋‚˜ ์ง๋ ฌํ™” ๊ณผ์ •์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, ์ƒ์„ฑ๋˜๋‹ค ๋งŒ ๊ฐ์ฒด์—์„œ ์•…์˜์ ์ธ ํ•˜์œ„ ํด๋ž˜์Šค์˜ finalizer๊ฐ€ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

- ์ด finalizer๋Š” ์ •์  ํ•„๋“œ์— ์ž์‹ ์˜ ์ฐธ์กฐ๋ฅผ ํ• ๋‹นํ•˜์—ฌ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ์ˆ˜์ง‘ ๋ชปํ•˜๊ฒŒ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

- ์ด๋ ‡๊ฒŒ ์ผ๊ทธ๋Ÿฌ์ง„ ๊ฐ์ฒด๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋ฉด, ์ด ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ํ—ˆ์šฉ๋˜์ง€ ์•Š์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

- ๋ฐฉ์–ด ๋ฐฉ๋ฒ•1: final ํด๋ž˜์Šค๋Š” ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†์–ด ์ด ๊ณต๊ฒฉ์—์„œ ์•ˆ์ „ํ•˜๋‹ค.

- ๋ฐฉ์–ด ๋ฐฉ๋ฒ•2: final์ด ์•„๋‹Œ ํด๋ž˜์Šค๋ฅผ finalizer ๊ณต๊ฒฉ์œผ๋กœ๋ถ€ํ„ฐ ๋ฐฉ์–ดํ•˜๋ ค๋ฉด, ์•„๋ฌด ์ผ๋„ ํ•˜์ง€ ์•Š๋Š” finalize ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  final ๋กœ ์„ฑ์–ธํ•˜์ž.

์ข…๋ฃŒํ•ด์•ผ ํ•  ์ž์›์„ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์˜ ํด๋ž˜์Šค(ํŒŒ์ผ์ด๋‚˜ ์Šค๋ ˆ๋“œ ๋“ฑ)์—์„œ finalizer์™€ Cleaner๋ฅผ ๋Œ€์‹ ํ•˜๋Š” ๋ฐฉ๋ฒ•

ยท AutoCloseable์„ ๊ตฌํ˜„ํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ์—์„œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‹ค ์“ฐ๊ณ  ๋‚˜๋ฉด close ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

- ์ผ๋ฐ˜์ ์œผ๋กœ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ์ œ๋Œ€๋กœ ์ข…๋ฃŒ๋˜๋„๋ก try-with-resources ์‚ฌ์šฉ

ยท ๊ฐ ์ธ์Šคํ„ด์Šค๋Š” ์ž์‹ ์ด ๋‹ซํ˜“๋Š”์ง€ ์ถ”์ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

- ์ฆ‰, close ๋ฉ”์„œ๋“œ์—์„œ ์ด ๊ฐ์ฒด๋Š” ๋” ์ด์ƒ ์œ ํšจํ•˜์ง€ ์•Š์Œ์„ ํ•„๋“œ์— ๊ธฐ๋กํ•˜๊ณ , ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋Š” ์ด ํ•„๋“œ๋ฅผ ๊ฒ€์‚ฌํ•ด์„œ ๊ฐ์ฒด๊ฐ€ ๋‹ซํžŒ ํ›„์— ๋ถˆ๋ ธ๋‹ค๋ฉด IllegalStateException์„ ๋˜์ง„๋‹ค.

finalizer์™€ Cleaner์˜ ์šฉ๋„

1. ์ž์›์˜ ์†Œ์œ ์ž๊ฐ€ close ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์— ๋Œ€๋น„ํ•œ ์•ˆ์ „๋ง ์—ญํ• ์„ ํ•œ๋‹ค.

- finalizer๋‚˜ cleaner๊ฐ€ ์ฆ‰์‹œ ํ˜ธ์ถœ๋˜๋ฆฌ๋ผ๋Š” ๋ณด์žฅ์€ ์—†์ง€๋งŒ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•˜์ง€ ์•Š์€ ์ž์› ํšŒ์ˆ˜๋ฅผ ์•„์˜ˆ ์•ˆํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ๋‚ซ๋‹ค.

- FileInputStream, FileOutputStream, ThreadPoolExecutor ๋“ฑ ์ž๋ฐ”๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ผ๋ถ€์—์„œ ์•ˆ์ „๋ง ์—ญํ• ์˜ finalizer๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

2. ๋„ค์ดํ‹ฐ๋ธŒ ํ”ผ์–ด์™€ ์—ฐ๊ฒฐ๋œ ๊ฐ์ฒด์—์„œ ์ž์› ํšŒ์ˆ˜์šฉ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

- ๋„ค์ดํ‹ฐ๋ธŒ ํ”ผ์–ด: ์ผ๋ฐ˜ ์ž๋ฐ” ๊ฐ์ฒด๊ฐ€ ๋„ค์ดํ‹ฐ๋ธŒ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ธฐ๋Šฅ์„ ์œ„์ž„ํ•œ ๋„ค์ดํ‹ฐ๋ธŒ ๊ฐ์ฒด๋‹ค. ์ž๋ฐ” ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ, ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๋Š” ๊ทธ ์กด์žฌ๋ฅผ ์•Œ์ง€ ๋ชปํ•œ๋‹ค.

- ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๊ฐ๋‹นํ•  ์ˆ˜ ์žˆ๊ณ , ๋„ค์ดํ‹ฐ๋ธŒ ํ”ผ์–ด๊ฐ€ ์‹ฌ๊ฐํ•œ ์ž์›์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์„ ๋•Œ์—๋งŒ ์ ํ•ฉํ•œ ์ž‘์—…์ด๋‹ค. ์ด์— ํ•ด๋‹นํ•˜์ง€ ์•Š์œผ๋ฉด, ์•ž์„œ ์„ค๋ช…ํ•œ close ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

์•„์ดํ…œ 9. try-finally๋ณด๋‹ค๋Š” try-with-resources๋ฅผ ์‚ฌ์šฉํ•˜๋ผ


ยท ์ž๋ฐ” ๋ผ์ด๋ธŒ๋Ÿฌ์ด์—๋Š” close ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ์ง์ ‘ ๋‹ซ์•„์ค˜์•ผ ํ•˜๋Š” ์ž์›์ด ๋งŽ๋‹ค.

ex) InputStream, OutputStream, java.sql.Connection

ยท ์ž์› ๋‹ซ๊ธฐ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋†“์น˜๊ธฐ ์‰ฌ์›Œ์„œ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” ์„ฑ๋Šฅ ๋ฌธ์ œ๋กœ ์ด์–ด์ง€๊ธฐ๋„ ํ•œ๋‹ค.

- ์ด๋Ÿฐ ์ž์› ์ค‘ ์ƒ๋‹น์ˆ˜๋Š” ์•ˆ์ „๋ง์œผ๋กœ finalizer๋ฅผ ํ™œ์šฉํ•˜์ง€๋งŒ, finalizer๋Š” ๋ฏฟ์Œ์งํ•˜์ง€ ๋ชปํ•˜๋‹ค.

ยท ์ „ํ†ต์ ์œผ๋กœ ์ž์›์„ ๋‹ซ๋Š” ์ˆ˜๋‹จ์œผ๋กœ try-finally๊ฐ€ ์“ฐ์˜€์ง€๋งŒ, ์ž์›์ด ๋‘˜ ์ด์ƒ์ด๋ฉด ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ์ง€์ €๋ถ„ํ•ด์ง„๋‹ค.

// ์ž์› ํ•˜๋‚˜ ํšŒ์ˆ˜
static String firstLineOfFile(String path) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        br.close();
    }
}
// ์ž์› ๋ณต์ˆ˜๊ฐœ ํšŒ์ˆ˜
static void copy(String src, String dst) throws IOException {
    InputStream in = new FileInputStream(src);
    try {
        OutputStream out = new FileOutputStream(dst);
        try {
            byte[] buf = new byte[BUFFER_SIZE];
            int n;
            while ((n = in.read(buf)) >= 0) {
                out.write(buf, 0, n);
            }
        } finally {
            out.close();
        }
    } finally {
        in.close();
    }
}

- ์‹ฌ์ง€์–ด ์•ž์„  ์ฝ”๋“œ ๋˜ํ•œ ๋ฏธ๋ฌ˜ํ•œ ๊ฒฐ์ ์ด ์žˆ๋‹ค.

๋”๋ณด๊ธฐ

ยท ์ž๋ฐ”7์—์„œ ๋“ฑ์žฅํ•œ try-with-resources์€ try-finally์˜ ๊ฒฐ์ ์„ ํ•ด๊ฒฐํ•œ๋‹ค.

- ์ด ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํ•˜๋‹น ์ž์›์ด AutoCloseable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

- ๋‹จ์ˆœํžˆ void๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” close ๋ฉ”์„œ๋“œ ํ•˜๋‚˜๋งŒ ์ •์˜ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค.

ยท ๋‹ค์Œ์€ ์•ž์„  ์ฝ”๋“œ๋ฅผ try-with-resources๋ฅผ ์‚ฌ์šฉํ•ด ์žฌ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋‹ค.

static String firstLineOfFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}
static void copy(String src, String dst) throws IOException {
    try (InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dst)) {
        byte[] buf = new byte[BUFFER_SIZE];
        int n;
        while ((n = in.read(buf)) >= 0) {
            out.write(buf, 0, n);
        }
    }
}

ยท ์•ž์„  ์ฝ”๋“œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋“ฏ์ด try-with-resources ๋ฒ„์ „์ด ์งง๊ณ  ์ฝ๊ธฐ ์ˆ˜์›”ํ•˜๋ฉฐ, ๋ฌธ์ œ๋ฅผ ์ง„๋‹จํ•˜๊ธฐ๋„ ํ›จ์”ฌ ์ข‹๋‹ค.

- firstLineOfFile ๋ฉ”์„œ๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž. readLine๊ณผ (์ฝ”๋“œ์—๋Š” ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๋Š”)close ํ˜ธ์ถœ ์–‘์ชฝ์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, close์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋Š” ์ˆจ๊ฒจ์ง€๊ณ  readLine์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๊ฐ€ ๊ธฐ๋ก๋œ๋‹ค.

- ์ด๋ ‡๊ฒŒ ์ˆจ๊ฒจ์ง„ ์˜ˆ์™ธ๋“ค๋„ ์Šคํƒ ์ถ”์  ๋‚ด์—ญ์— '์ˆจ๊ฒจ์กŒ๋‹ค(suppressed)'๋Š” ๊ผฌ๋ฆฌํ‘œ๋ฅผ ๋‹ฌ๊ณ  ์ถœ๋ ฅ๋œ๋‹ค.

- ์ž๋ฐ” 7์—์„œ Throwable์— ์ถ”๊ฐ€๋œ getSuppressed ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ ์ฝ”๋“œ์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋„ ์žˆ๋‹ค.

ยท try-with-resources๋„ catch ์ ˆ์„ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

- ์ด๋ฅผ ํ†ตํ•ด try ๋ฌธ์„ ๋” ์ค‘์ฒฉํ•˜์ง€ ์•Š๊ณ  ๋‹ค์ˆ˜์˜ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

static String firstLineOfFile(String path, String defaultVal) {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    } catch (IOException e) {
        return defaultVal;
    }
}

Last updated