item 20 junghyunlyoo - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

์ž๋ฐ”๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋‹ค์ค‘ ๊ตฌํ˜„ ๋งค์ปค๋‹ˆ์ฆ˜์€ interface, abstract class 2๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

๋‘ ๋งค์ปค๋‹ˆ์ฆ˜ ๋ชจ๋‘ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

(์ถ”์ƒ ํด๋ž˜์Šค๋Š” ์›๋ž˜ ์ œ๊ณตํ–ˆ๊ณ , ์ธํ„ฐํŽ˜์ด์Šค๋Š” java8์— ๋“ฑ์žฅํ•œ default ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•œ๋‹ค)

ํ•œํŽธ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ถ”์ƒํด๋ž˜์Šค๋ณด๋‹ค ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋‚˜์€์ ์ด ์žˆ๋‹ค. ์•„๋ž˜์—์„œ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด์ž.

์ƒ์† ํ˜น์€ ๊ตฌํ˜„ ๊ฐฏ์ˆ˜ ์ œํ•œ

๋‘ ๋งค์ปค๋‹ˆ์ฆ˜์˜ ๊ฐ€์žฅ ํฐ ์ฐจ์ด๋Š” ๋ฐ”๋กœ ์ด๊ฒƒ์ด๋‹ค.

์ถ”์ƒํด๋ž˜์Šค๊ฐ€ ์ •์˜ํ•œ ํƒ€์ž…์„ ์ƒ์†ํ•˜๋Š” ํด๋ž˜์Šค๋Š” ๋ฐ˜๋“œ์‹œ ์ถ”์ƒ ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

์ž๋ฐ”๋Š” ๋‹จ์ผ ์ƒ์†์„ ์ง€์›ํ•œ๋‹ค.

์ฆ‰ ์ถ”์ƒํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์œผ๋ฉด ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์„ ์ˆ˜๊ฐ€ ์—†๋‹ค.

๋ฐ˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋‹ค์ˆ˜ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ํ—ˆ์šฉ๋œ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์„ ์–ธํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ์ •์˜ํ•˜๊ณ  ๊ทธ ์ผ๋ฐ˜ ๊ทœ์•ฝ์„ ์ž˜ ์ง€ํ‚จ ํด๋ž˜์Šค๋ผ๋ฉด

๋‹ค๋ฅธ ์–ด๋–ค ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ–ˆ๋“  ๋˜๋Š” ๋‹ค๋ฅธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ–ˆ๋“  ๋ชจ๋‘ ๋™์ผํ•œ ํƒ€์ž…์œผ๋กœ ์ทจ๊ธ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ธฐ์กด ํด๋ž˜์Šค์— ์ƒ์œ„ ํƒ€์ž… ์ง€์ •

๋˜ํ•œ ์–ด๋”˜๊ฐ€์—์„œ ์‚ฌ์šฉ์ค‘์ธ ๊ธฐ์กด ํด๋ž˜์Šค์— ๊ตฌํ˜„, ๋˜๋Š” ์ƒ์†์„ ํ†ตํ•˜์—ฌ ์ƒ์œ„ ํƒ€์ž…์„ ์ง€์ •ํ•  ๋•Œ๋„, ์ด ๋‘˜์€ ์ฐจ์ด์ ์„ ๊ฐ–๋Š”๋‹ค.

๊ธฐ์กด ์‚ฌ์šฉ์ค‘์ธ ํด๋ž˜์Šค์— ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ์ƒ๋Œ€์ ์œผ๋กœ ๋ถ€๋‹ด์ด ๋œํ•˜๋‹ค.

์™œ๋ƒํ•˜๋ฉด implemets ๊ตฌ๋ฌธ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋œ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ƒˆ๋กœ ์ถ”๊ฐ€๋งŒ ํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด์˜ ์ฝ”๋“œ๋“ค์— ์˜ํ–ฅ์ด ๊ฑฐ์˜ ์—†๋‹ค.

๋™์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ฒŒ๋  ๋‹ค๋ฅธ ํด๋ž˜์Šค์—๋„ ์˜ํ–ฅ์ด ์—†๋‹ค.

(Comparable, Iterable, AutoCloseable ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์œ„ ํŠน์ง•์„ ๋ณด์—ฌ์ฃผ๋Š” ์‚ฌ๋ก€๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.)

ํ•˜์ง€๋งŒ ๊ธฐ์กด ์‚ฌ์šฉ์ค‘์ธ ํด๋ž˜์Šค์— ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ์ƒ๋Œ€์ ์œผ๋กœ ๋ถ€๋‹ด์ด ํฌ๋‹ค.

์–ด๋–ค ํด๋ž˜์Šค์— ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ƒ์œ„ ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์ถ”์ƒ ํด๋ž˜์Šค์— ์„œ๋น„์Šค ๋กœ์ง์ด ์ž๋ฆฌํ•˜์—ฌ

ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์ด ๋กœ์ง์— ๋Œ€ํ•œ ์˜์กด์„ฑ์ด ์ƒ๊ธฐ๋ฉด ์ด ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•  ๋‹ค๋ฅธ ํด๋ž˜์Šค์— ๋ถ€๋‹ด์ด ์ƒ๊ธฐ๊ฒŒ ๋œ๋‹ค.

์ถ”์ƒ ํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ๋‚˜ ํ•„๋“œ ๋“ฑ์ด ํŠน์ • ์ž์‹ ํด๋ž˜์Šค์— ์ตœ์ ํ™”๋  ์ˆ˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๊ฒŒ ๋  ๋˜ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋Š” ํŠน์ • ์ž์‹ ํด๋ž˜์Šค๊ฐ€ ์ข…์†ํ•˜๊ณ  ์žˆ๋Š”

์ถ”์ƒ ํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ๋‚˜ ํ•„๋“œ ๋•Œ๋ฌธ์— ๊ธฐ๋Šฅ ๊ตฌํ˜„์— ์ œํ•œ์ด ์ƒ๊ธธ ์ˆ˜๋„ ์žˆ๋‹ค.

ํ˜น์€ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ถ€๋ถ„๊นŒ์ง€ ์ƒ์†๋ฐ›์•„์•ผ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋ฏน์Šค์ธ ์ง€์›

๋Œ€์ƒ ํƒ€์ž…์˜ ์ฃผ๋œ ๊ธฐ๋Šฅ์— ์„ ํƒ์  ๊ธฐ๋Šฅ์„ ํ˜ผํ•ฉํ•˜๋Š” ๊ฒƒ์ด ๋ฏน์Šค์ธ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

(์ฃผ ๊ธฐ๋Šฅ์ด ์•„๋‹Œ ๋ถ€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ธฐ๋ฒ•)

์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ถ”์ƒํด๋ž˜์Šค์™€ ๋‹ค๋ฅด๊ฒŒ ๊ธฐ๋Šฅ์„ ์„ธ๋ถ„ํ™”ํ•จ์œผ๋กœ์จ ๋ฏน์Šค์ธ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ถ”์ƒํด๋ž˜์Šค๋Š” 1๊ฐœ์”ฉ๋ฐ–์— ์ƒ์†ํ•  ์ˆ˜ ์—†์ง€๋งŒ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์—ฌ๋Ÿฌ๊ฐœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ธฐ์กด ํด๋ž˜์Šค์— ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š”๊ฒƒ์ด ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— ์ถ”์ƒ ํด๋ž˜์Šค๋กœ๋Š” ๋ฏน์Šค์ธ์„ ์ •์˜ํ•  ์ˆ˜ ์—†๋‹ค.

์ฑ…์ž„์„ ์—ฌ๋Ÿฌ๊ฐœ ๊ฐ–๊ณ  ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ผ๋ฉด ์ฑ…์ž„์„ ์ตœ๋Œ€ํ•œ ์„ธ์„ธํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•˜์—ฌ

ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ด ํ•„์š”ํ•œ ๊ฐ์ฒด๋“ค์ด ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์„ ํƒํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋„๋ก ํ•œ๋‹ค.

์ด๋Ÿฌํ•œ ์„ธ์„ธํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฏน์Šค์ธ ์ธํ„ฐํŽ˜์ด์Šค๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด Comparable์€ ์ž์‹ ์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋“ค๋ผ๋ฆฌ๋Š” ์ˆœ์„œ๋ฅผ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์„ ์–ธํ•˜๋Š” ๋ฏน์Šค์ธ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ฏน์Šค์ธ ์ •์˜์— ์•ˆ์„ฑ๋งž์ถค์ด๋‹ค.

๊ณ„์ธต๊ตฌ์กฐ๊ฐ€ ์—†๋Š” ํƒ€์ž… ํ”„๋ ˆ์ž„์›Œํฌ

์ธํ„ฐํŽ˜์ด์Šค๋กœ๋Š” ๊ณ„์ธต๊ตฌ์กฐ๊ฐ€ ์—†๋Š” ํƒ€์ž… ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

ํƒ€์ž…์„ ๊ณ„์ธต์ ์œผ๋กœ ์ •์˜ํ•˜๋ฉด ์ˆ˜๋งŽ์€ ๊ฐœ๋…์„ ๊ตฌ์กฐ์ ์œผ๋กœ ์ž˜ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ

ํ˜„์‹ค์—๋Š” ๊ณ„์ธต์„ ์—„๊ฒฉํžˆ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๊ฐ€์ˆ˜(Singer) ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ž‘๊ณก๊ฐ€(SongWriter) ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•ด๋ณด์ž.

public interface Singer {
    AudioClip sing(Song s);
}
public interface Songwriter {
    Song compose(int chartPosition);
}

์šฐ๋ฆฌ ์ฃผ๋ณ€์—” ์ž‘๊ณก๋„ ํ•˜๋Š” ๊ฐ€์ˆ˜๊ฐ€ ์ œ๋ฒ• ์žˆ๋‹ค.

์ด ์ฝ”๋“œ์ฒ˜๋Ÿผ ํƒ€์ž…์„ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ •์˜ํ•˜๋ฉด ๊ฐ€์ˆ˜ ํด๋ž˜์Šค๊ฐ€ Singer์™€ Songwriter ๋ชจ๋‘๋ฅผ ๊ตฌํ˜„ํ•ด๋„ ์ „ํ˜€ ๋ฌธ์ œ๋˜์ง€ ์•Š๋Š”๋‹ค.

์‹ฌ์ง€์–ด Singer์™€ Songwriter ๋ชจ๋‘๋ฅผ ํ™•์žฅํ•˜๊ณ  ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๊นŒ์ง€ ์ถ”๊ฐ€ํ•œ ์ œ3์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

public interface SingerSongwriter extends Singer, Songwriter {
    AudioClip strum();
    void actSensitive();
}

์ด ์ •๋„์˜ ์œ ์—ฐ์„ฑ์ด ํ•ญ์ƒ ํ•„์š”ํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด๋‘” ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๊ฒฐ์ •์ ์ธ ๋„์›€์„ ์ค„ ์ˆ˜๋„ ์žˆ๋‹ค.

๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„  ๊ฐ€๋Šฅํ•œ ์กฐํ•ฉ ์ „๋ถ€๋ฅผ ๊ฐ๊ฐ์˜ ํด๋ž˜์Šค๋กœ ์ •์˜ํ•œ ๊ณ ๋„๋น„๋งŒ ๊ณ„์ธต๊ตฌ์กฐ๊ฐ€ ๋งŒ๋“ค์–ด์งˆ ๊ฒƒ์ด๋‹ค.

์†์„ฑ์ด n๊ฐœ๋ผ๋ฉด ์ง€์›ํ•ด์•ผ ํ•  ์กฐํ•ฉ์˜ ์ˆ˜๋Š” 2^n๊ฐœ๋‚˜ ๋œ๋‹ค. ํ”ํžˆ ์กฐํ•ฉ ํญ๋ฐœ์ด๋ผ ๋ถ€๋ฅด๋Š” ํ˜„์ƒ์ด๋‹ค.

๊ฑฐ๋Œ€ํ•œ ํด๋ž˜์Šค ๊ณ„์ธต๊ตฌ์กฐ์—๋Š” ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ •์˜ํ•ด๋†“์€ ํƒ€์ž…์ด ์—†์œผ๋‹ˆ

์ž์นซ ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…๋งŒ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋“ค์„ ์ˆ˜์—†์ด ๋งŽ์ด ๊ฐ€์ง„ ๊ฑฐ๋Œ€ํ•œ ํด๋ž˜์Šค๋ฅผ ๋‚ณ์„ ์ˆ˜ ์žˆ๋‹ค.

๋ž˜ํผ ํด๋ž˜์Šค

์ธํ„ฐํŽ˜์ด์Šค๋Š” item 18์—์„œ ๋“ฑ์žฅํ•˜๋Š” ๋ž˜ํผ ํด๋ž˜์Šค ๊ด€์šฉ๊ตฌ์— ์ ์šฉ๋˜๊ธฐ๋„ ํ•œ๋‹ค.

์ด๋Š” ๊ธฐ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ์•ˆ์ „ํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ์ˆ˜๋‹จ์ด ๋œ๋‹ค.

ํƒ€์ž…์„ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ์ •์˜ํ•ด๋‘๋ฉด ๊ทธ ํƒ€์ž…์— ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ƒ์†๋ฟ์ด๋‹ค.

์ƒ์†ํ•ด์„œ ๋งŒ๋“  ํด๋ž˜์Šค๋Š” ๋ž˜ํผ ํด๋ž˜์Šค๋ณด๋‹ค ํ™œ์šฉ๋„๊ฐ€ ๋–จ์–ด์ง€๊ณ  ๊นจ์ง€๊ธฐ๋Š” ๋” ์‰ฝ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค์˜ Default ๋ฉ”์„œ๋“œ

์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์„œ๋“œ ์ค‘ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์ด ๋ช…๋ฐฑํ•œ ๊ฒƒ์ด ์žˆ๋‹ค๋ฉด ๊ทธ ๊ตฌํ˜„์„ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•ด ํ”„๋กœ๊ทธ๋ž˜๋จธ๋“ค์˜ ์ผ๊ฐ์„ ๋œ์–ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

item 21์—์„œ ๋“ฑ์žฅํ•˜๋Š” removeIf ๋ฉ”์†Œ๋“œ๊ฐ€ ๊ทธ ์˜ˆ์ด๋‹ค.

๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•  ๋•Œ๋Š” ์ƒ์†ํ•˜๋ ค๋Š” ์‚ฌ๋žŒ์„ ์œ„ํ•œ ์„ค๋ช…์„ @implSpec ์ž๋ฐ”๋… ํƒœ๊ทธ๋ฅผ ๋ถ™์—ฌ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•œ๋‹ค. (item 19)

๋””ํดํŠธ ๋ฉ”์„œ๋“œ์—๋„ ์ œ์•ฝ์€ ์žˆ๋‹ค.

๋งŽ์€ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ equals์™€ hashCode, toString ๊ฐ™์€ Object์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๊ณ  ์žˆ์ง€๋งŒ ์ด๋“ค์€ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.

์™œ๋ƒํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด์˜ ์ƒํƒœ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š”๋ฐ,

equals๋‚˜ hashCode, toString ๋ฉ”์†Œ๋“œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ํ•„์ˆ˜์ ์œผ๋กœ ์ฐธ์กฐํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋˜ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†๊ณ  public์ด ์•„๋‹Œ ์ •์  ๋ฉค๋ฒ„๋„ ๊ฐ€์งˆ ์ˆ˜ ์—†๋‹ค. (๋‹จ private ์ •์  ๋ฉ”์„œ๋“œ๋Š” ์˜ˆ์™ธ๋‹ค)

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

์ถ”์ƒ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค

ํ•œํŽธ, ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ถ”์ƒ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ํ•จ๊ป˜ ์ œ๊ณตํ•˜๋Š” ์‹์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ถ”์ƒ ํด๋ž˜์Šค์˜ ์žฅ์ ์„ ๋ชจ๋‘ ์ทจํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค๋กœ๋Š” ํƒ€์ž…์„ ์ •์˜ํ•˜๊ณ , ํ•„์š”ํ•˜๋ฉด ๋””ํดํŠธ ๋ฉ”์„œ๋“œ ๋ช‡ ๊ฐœ๋„ ํ•จ๊ป˜ ์ œ๊ณตํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋Š” ๋‚˜๋จธ์ง€ ๋ฉ”์„œ๋“œ๋“ค๊นŒ์ง€ ๊ตฌํ˜„ํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•ด๋‘๋ฉด ๋‹จ์ˆœํžˆ ๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ํ™•์žฅํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ผ์ด ๋Œ€๋ถ€๋ถ„ ์™„๋ฃŒ๋œ๋‹ค.

๋ฐ”๋กœ ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด์ด๋‹ค.

๊ด€๋ก€์ƒ ์ธํ„ฐํŽ˜์ด์Šค ์ด๋ฆ„์ด Interface๋ผ๋ฉด 

๊ทธ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค์˜ ์ด๋ฆ„์€ AbstractInterface๋กœ ์ง“๋Š”๋‹ค.

์˜ˆ๋ฅผ ๋“ค๋ฉด, AbstractCollection, AbstractSet, AbstractList, AbstractMap ๊ฐ๊ฐ์ด 

๋ฐ”๋กœ ํ•ต์‹ฌ ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ณจ๊ฒฉ ๊ตฌํ˜„์ด๋‹ค.

(SkeletalCollection, SkeletalSet, SkeletalList, SkeletalMap ํ˜•ํƒœ๊ฐ€ ๋” ์ ์ ˆํ–ˆ์„์ง€๋„ ๋ชจ๋ฅด์ง€๋งŒ

์ด๋ฏธ Abstract๋ฅผ ์ ‘๋‘์–ด๋กœ ์“ฐ๋Š” ํ˜•ํƒœ๊ฐ€ ํ™•๊ณ ํžˆ ์ž๋ฆฌ์žก์•˜๋‹ค.)

๊ณจ๊ฒฉ ๊ตฌํ˜„ ์ž‘์„ฑ์€ ์–ด๋ ต์ง€ ์•Š๋‹ค.

๋จผ์ €, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ถ„์„ํ•˜์—ฌ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋“ค์˜ ๊ตฌํ˜„์— ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋ฐ˜ ๋ฉ”์„œ๋“œ๋“ค์„ ์„ ์ •ํ•œ๋‹ค.

์ด ๊ธฐ๋ฐ˜ ๋ฉ”์„œ๋“œ๋“ค์€ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๊ฐ€ ๋œ๋‹ค.

๊ทธ๋‹ค์Œ์œผ๋กœ ๊ธฐ๋ฐ˜ ๋ฉ”์„œ๋“œ๋“ค์„ ์‚ฌ์šฉํ•ด ์ง์ ‘ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•œ๋‹ค.

equals์™€ hashCode๊ฐ™์€ Object์˜ ๋ฉ”์„œ๋“œ๋Š” ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•˜๋ฉด ์•ˆ ๋œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ํ•ญ์ƒ ์œ ๋…ํ•˜์ž.

๋งŒ์•ฝ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์„œ๋“œ ๋ชจ๋‘๊ฐ€ ๊ธฐ๋ฐ˜ ๋ฉ”์„œ๋“œ์™€ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๊ฐ€ ๋œ๋‹ค๋ฉด ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ๋ณ„๋„๋กœ ๋งŒ๋“ค ์ด์œ ๋Š” ์—†๋‹ค.

๊ธฐ๋ฐ˜ ๋ฉ”์„œ๋“œ๋‚˜ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ ๋งŒ๋“ค์ง€ ๋ชปํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ๋‚จ์•„ ์žˆ๋‹ค๋ฉด

์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด ๋‚จ์€ ๋ฉ”์„œ๋“œ๋“ค์„ ์ž‘์„ฑํ•ด ๋„ฃ๋Š”๋‹ค.

๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค์—๋Š” ํ•„์š”ํ•˜๋ฉด public์ด ์•„๋‹Œ ํ•„๋“œ์™€ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด๋„ ๋œ๋‹ค.

๊ฐ„๋‹จํ•œ ์˜ˆ๋กœ Map.Entry ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ดํŽด๋ณด์ž.

interface Entry<K, V> {
    /**
     * Returns the key corresponding to this entry.
     *
     * @return the key corresponding to this entry
     * @throws IllegalStateException implementations may, but are not
     *         required to, throw this exception if the entry has been
     *         removed from the backing map.
     */
    K getKey();

    /**
     * Returns the value corresponding to this entry.  If the mapping
     * has been removed from the backing map (by the iterator's
     * {@code remove} operation), the results of this call are undefined.
     *
     * @return the value corresponding to this entry
     * @throws IllegalStateException implementations may, but are not
     *         required to, throw this exception if the entry has been
     *         removed from the backing map.
     */
    V getValue();

    /**
     * Replaces the value corresponding to this entry with the specified
     * value (optional operation).  (Writes through to the map.)  The
     * behavior of this call is undefined if the mapping has already been
     * removed from the map (by the iterator's {@code remove} operation).
     *
     * @param value new value to be stored in this entry
     * @return old value corresponding to the entry
     * @throws UnsupportedOperationException if the {@code put} operation
     *         is not supported by the backing map
     * @throws ClassCastException if the class of the specified value
     *         prevents it from being stored in the backing map
     * @throws NullPointerException if the backing map does not permit
     *         null values, and the specified value is null
     * @throws IllegalArgumentException if some property of this value
     *         prevents it from being stored in the backing map
     * @throws IllegalStateException implementations may, but are not
     *         required to, throw this exception if the entry has been
     *         removed from the backing map.
     */
    V setValue(V value);

    /**
     * Compares the specified object with this entry for equality.
     * Returns {@code true} if the given object is also a map entry and
     * the two entries represent the same mapping.  More formally, two
     * entries {@code e1} and {@code e2} represent the same mapping
     * if<pre>
     *     (e1.getKey()==null ?
     *      e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &amp;&amp;
     *     (e1.getValue()==null ?
     *      e2.getValue()==null : e1.getValue().equals(e2.getValue()))
     * </pre>
     * This ensures that the {@code equals} method works properly across
     * different implementations of the {@code Map.Entry} interface.
     *
     * @param o object to be compared for equality with this map entry
     * @return {@code true} if the specified object is equal to this map
     *         entry
     */
    boolean equals(Object o);

    /**
     * Returns the hash code value for this map entry.  The hash code
     * of a map entry {@code e} is defined to be: <pre>
     *     (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
     *     (e.getValue()==null ? 0 : e.getValue().hashCode())
     * </pre>
     * This ensures that {@code e1.equals(e2)} implies that
     * {@code e1.hashCode()==e2.hashCode()} for any two Entries
     * {@code e1} and {@code e2}, as required by the general
     * contract of {@code Object.hashCode}.
     *
     * @return the hash code value for this map entry
     * @see Object#hashCode()
     * @see Object#equals(Object)
     * @see #equals(Object)
     */
    int hashCode();

    /**
     * Returns a comparator that compares {@link Map.Entry} in natural order on key.
     *
     * <p>The returned comparator is serializable and throws {@link
     * NullPointerException} when comparing an entry with a null key.
     *
     * @param  <K> the {@link Comparable} type of then map keys
     * @param  <V> the type of the map values
     * @return a comparator that compares {@link Map.Entry} in natural order on key.
     * @see Comparable
     * @since 1.8
     */
    public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparingByKey() {
        return (Comparator<Map.Entry<K, V>> & Serializable)
            (c1, c2) -> c1.getKey().compareTo(c2.getKey());
    }

    /**
     * Returns a comparator that compares {@link Map.Entry} in natural order on value.
     *
     * <p>The returned comparator is serializable and throws {@link
     * NullPointerException} when comparing an entry with null values.
     *
     * @param <K> the type of the map keys
     * @param <V> the {@link Comparable} type of the map values
     * @return a comparator that compares {@link Map.Entry} in natural order on value.
     * @see Comparable
     * @since 1.8
     */
    public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K, V>> comparingByValue() {
        return (Comparator<Map.Entry<K, V>> & Serializable)
            (c1, c2) -> c1.getValue().compareTo(c2.getValue());
    }

    /**
     * Returns a comparator that compares {@link Map.Entry} by key using the given
     * {@link Comparator}.
     *
     * <p>The returned comparator is serializable if the specified comparator
     * is also serializable.
     *
     * @param  <K> the type of the map keys
     * @param  <V> the type of the map values
     * @param  cmp the key {@link Comparator}
     * @return a comparator that compares {@link Map.Entry} by the key.
     * @since 1.8
     */
    public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
        Objects.requireNonNull(cmp);
        return (Comparator<Map.Entry<K, V>> & Serializable)
            (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
    }

    /**
     * Returns a comparator that compares {@link Map.Entry} by value using the given
     * {@link Comparator}.
     *
     * <p>The returned comparator is serializable if the specified comparator
     * is also serializable.
     *
     * @param  <K> the type of the map keys
     * @param  <V> the type of the map values
     * @param  cmp the value {@link Comparator}
     * @return a comparator that compares {@link Map.Entry} by the value.
     * @since 1.8
     */
    public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
        Objects.requireNonNull(cmp);
        return (Comparator<Map.Entry<K, V>> & Serializable)
            (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
    }
}

getKey, getValue๋Š” ํ™•์‹คํžˆ ๊ธฐ๋ฐ˜ ๋ฉ”์„œ๋“œ์ด๋ฉฐ, ์„ ํƒ์ ์œผ๋กœ setValue๋„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” equals์™€ hashCode์˜ ๋™์ž‘ ๋ฐฉ์‹๋„ ์ •์˜ํ•˜์—ฌ ๊ตฌํ˜„์ฒด์—์„œ ์ด ๋ฉ”์†Œ๋“œ๋“ค์„ ์žฌ์ •์˜ํ•˜๋„๋ก ๊ฐ•์ œํ–ˆ๋‹ค.

์•„๋ž˜๋Š” Map.Entry ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ AbstractMapEntry ์ถ”์ƒ ํด๋ž˜์Šค์ด๋‹ค.

import java.util.*;

// ์ฝ”๋“œ 20-2 ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค (134-135์ชฝ)
public abstract class AbstractMapEntry<K, V>
        implements Map.Entry<K, V> {
    // ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์—”ํŠธ๋ฆฌ๋Š” ์ด ๋ฉ”์„œ๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ์žฌ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค.
    @Override
    public V setValue(V value) {
        throw new UnsupportedOperationException();
    }

    // Map.Entry.equals์˜ ์ผ๋ฐ˜ ๊ทœ์•ฝ์„ ๊ตฌํ˜„ํ•œ๋‹ค.
    @Override
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof Map.Entry))
            return false;
        Map.Entry<?, ?> e = (Map.Entry) o;
        return Objects.equals(e.getKey(), getKey())
                && Objects.equals(e.getValue(), getValue());
    }

    // Map.Entry.hashCode์˜ ์ผ๋ฐ˜ ๊ทœ์•ฝ์„ ๊ตฌํ˜„ํ•œ๋‹ค.
    @Override
    public int hashCode() {
        return Objects.hashCode(getKey())
                ^ Objects.hashCode(getValue());
    }

    @Override
    public String toString() {
        return getKey() + "=" + getValue();
    }
}

Object ๋ฉ”์„œ๋“œ๋“ค์€ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•ด์„œ๋Š” ์•ˆ ๋˜๋ฏ€๋กœ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋“ค์€ ๋ชจ๋‘ ์ด ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค์— ๊ตฌํ˜„ํ•œ๋‹ค.

toString๋„ ๊ธฐ๋ฐ˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๊ตฌํ˜„ํ•ด๋†จ๋‹ค.

๊ณจ๊ฒฉ ๊ตฌํ˜„์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒ์†ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฑธ ๊ฐ€์ •ํ•˜๋ฏ€๋กœ item 19์—์„œ ์ด์•ผ๊ธฐํ•œ ์„ค๊ณ„ ๋ฐ ๋ฌธ์„œํ™” ์ง€์นจ์„ ๋ชจ๋‘ ๋”ฐ๋ผ์•ผ ํ•œ๋‹ค.

๊ฐ„๋žตํžˆ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ์œ„ ์ฝ”๋“œ์—์„œ๋Š” ๋ฌธ์„œํ™” ์ฃผ์„์„ ์ƒ๋žตํ–ˆ์ง€๋งŒ

์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜ํ•œ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋“  ๋ณ„๋„์˜ ์ถ”์ƒ ํด๋ž˜์Šค๋“  ๊ณจ๊ฒฉ ๊ตฌํ˜„์€ ๋ฐ˜๋“œ์‹œ ๊ทธ ๋™์ž‘ ๋ฐฉ์‹์„ ์ž˜ ์ •๋ฆฌํ•ด ๋ฌธ์„œ๋กœ ๋‚จ๊ฒจ์•ผ ํ•œ๋‹ค.


ํ•œํŽธ ๋‹จ์ˆœ ๊ตฌํ˜„์€ ๊ณจ๊ฒฉ ๊ตฌํ˜„์˜ ์ž‘์€ ๋ณ€์ข…์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. AbstractMap.SimpleEntry๊ฐ€ ์ข‹์€ ์˜ˆ๋‹ค.

public static class SimpleEntry<K, V> implements Entry<K, V>, Serializable {
    private static final long serialVersionUID = -8499721149061103585L;
    private final K key;
    private V value;

    public SimpleEntry(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public SimpleEntry(Entry<? extends K, ? extends V> entry) {
        this.key = entry.getKey();
        this.value = entry.getValue();
    }

    public K getKey() {
        return this.key;
    }

    public V getValue() {
        return this.value;
    }

    public V setValue(V value) {
        V oldValue = this.value;
        this.value = value;
        return oldValue;
    }

    public boolean equals(Object o) {
        if (!(o instanceof Entry)) {
            return false;
        } else {
            Entry<?, ?> e = (Entry)o;
            return AbstractMap.eq(this.key, e.getKey()) && AbstractMap.eq(this.value, e.getValue());
        }
    }

    public int hashCode() {
        return (this.key == null ? 0 : this.key.hashCode()) ^ (this.value == null ? 0 : this.value.hashCode());
    }

    public String toString() {
        return this.key + "=" + this.value;
    }
}

๋‹จ์ˆœ ๊ตฌํ˜„๋„ ๊ณจ๊ฒฉ ๊ตฌํ˜„๊ณผ ๊ฐ™์ด ์ƒ์†์„ ์œ„ํ•ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ด์ง€๋งŒ ์ถ”์ƒ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹ˆ๋ž€ ์ ์ด ๋‹ค๋ฅด๋‹ค.


๋…๋ฆฝ๋œ ์ถ”์ƒ ํด๋ž˜์Šค์˜ ํ˜•ํƒœ๋กœ๋“  ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ ์ด๋ค„์ง„ ์ธํ„ฐํŽ˜์ด์Šค์˜ ํ˜•ํƒœ๋กœ๋“  ๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ์ œ๋Œ€๋กœ ์„ค๊ณ„ํ–ˆ๋‹ค๋ฉด

๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋‚˜๋ฆ„์˜ ๊ตฌํ˜„์„ ๋งŒ๋“ค๋ ค๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ์ผ์„ ์ƒ๋‹นํžˆ ๋œ์–ด์ค€๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ ์ฝ”๋“œ๋Š” ์™„๋ฒฝํžˆ ๋™์ž‘ํ•˜๋Š” List ๊ตฌํ˜„์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” AbstractList ๊ณจ๊ฒฉ ๊ตฌํ˜„์ด ์ ์šฉ๋œ ์ •์  ํŒฉํ„ฐ๋ฆฌ๋ฉ”์„œ๋“œ์ด๋‹ค.

static List<Integer> intArrayAsList(int[] a) {
    Objects.requireNonNull(a);

    // ๋‹ค์ด์•„๋ชฌ๋“œ ์—ฐ์‚ฐ์ž๋ฅผ ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฑด ์ž๋ฐ” 9๋ถ€ํ„ฐ ๊ฐ€๋Šฅํ•˜๋‹ค.
    // ๋” ๋‚ฎ์€ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด <Integer>๋กœ ์ˆ˜์ •ํ•˜์ž.
    return new AbstractList<>() {
        @Override public Integer get(int i) {
            return a[i];  // ์˜คํ† ๋ฐ•์‹ฑ(์•„์ดํ…œ 6)
        }

        @Override public Integer set(int i, Integer val) {
            int oldVal = a[i];
            a[i] = val;     // ์˜คํ† ์–ธ๋ฐ•์‹ฑ
            return oldVal;  // ์˜คํ† ๋ฐ•์‹ฑ
        }

        @Override public int size() {
            return a.length;
        }
    };
}

List ๊ตฌํ˜„์ฒด๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์—๊ฒŒ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ๋“ค์„ ์ƒ๊ฐํ•˜๋ฉด

์ด ์ฝ”๋“œ๋Š” ๊ณจ๊ฒฉ ๊ตฌํ˜„์˜ ํž˜์„ ์ž˜ ๋ณด์—ฌ์ฃผ๋Š” ์ธ์ƒ์ ์ธ ์˜ˆ๋ผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ์˜ˆ๋Š” int ๋ฐฐ์—ด์„ ๋ฐ›์•„ Integer ์ธ์Šคํ„ด์Šค์˜ ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ๋กœ ๋ณด์—ฌ์ฃผ๋Š” ์–ด๋Œ‘ํ„ฐ์ด๊ธฐ๋„ ํ•˜๋‹ค.

int ๊ฐ’๊ณผ Integer ์ธ์Šคํ„ด์Šค ์‚ฌ์ด์˜ ๋ณ€ํ™˜(๋ฐ•์‹ฑ๊ณผ ์–ธ๋ฐ•์‹ฑ) ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ์€ ๊ทธ๋ฆฌ ์ข‹์ง€ ์•Š๋‹ค.

๋˜ํ•œ, ์ด ๊ตฌํ˜„์—์„œ ์ต๋ช… ํด๋ž˜์Šค(item 24) ํ˜•ํƒœ๋ฅผ ์‚ฌ์šฉํ–ˆ์Œ์— ์ฃผ๋ชฉํ•  ํ•„์š”๋„ ์žˆ๋‹ค.

๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค์˜ ์•„๋ฆ„๋‹ค์›€์€ ์ถ”์ƒ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ๊ตฌํ˜„์„ ๋„์™€์ฃผ๋Š” ๋™์‹œ์—

์ถ”์ƒ ํด๋ž˜์Šค๋กœ ํƒ€์ž…์„ ์ •์˜ํ•  ๋•Œ ๋”ฐ๋ผ์˜ค๋Š” ์‹ฌ๊ฐํ•œ ์ œ์•ฝ์—์„œ๋Š” ์ž์œ ๋กญ๋‹ค๋Š” ์ ์— ์žˆ๋‹ค.


๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ํ™•์žฅํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์ด ๊ฑฐ์˜ ๋๋‚˜์ง€๋งŒ ๊ผญ ์ด๋ ‡๊ฒŒ ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

๊ตฌ์กฐ์ƒ ๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ํ™•์žฅํ•˜์ง€ ๋ชปํ•˜๋Š” ์ฒ˜์ง€๋ผ๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

์ด๋Ÿฐ ๊ฒฝ์šฐ๋ผ๋„ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ง์ ‘ ์ œ๊ณตํ•˜๋Š” ๋””ํดํŠธ ๋ฉ”์„œ๋“œ์˜ ์ด์ ์„ ์—ฌ์ „ํžˆ ๋ˆ„๋ฆด ์ˆ˜ ์žˆ๋‹ค.

๋˜ํ•œ, ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ์šฐํšŒ์ ์œผ๋กœ ์ด์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์—์„œ ํ•ด๋‹น ๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ํ™•์žฅํ•œ private ๋‚ด๋ถ€ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๊ณ 

๊ฐ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ๋‚ด๋ถ€ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์— ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

item 18์—์„œ ๋‹ค๋ฃฌ ๋ž˜ํผํด๋ž˜์Šค์™€ ๋น„์Šทํ•œ ์ด ๋ฐฉ์‹์„ ์‹œ๋ฎฌ๋ ˆ์ดํŠธํ•œ ๋‹ค์ค‘ ์ƒ์†์ด๋ผ ํ•œ๋‹ค.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ