Study/Effective Java

[Effective Java 3/E] 2์žฅ ๊ฐ์ฒด ์ƒ์„ฑ๊ณผ ํŒŒ๊ดด

youn12 2023. 4. 30. 13:17
๐Ÿ“‹ ๋ชฉ์ฐจ.

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

    .์•„์ดํ…œ 3 - private ์ƒ์„ฑ์ž๋‚˜ ์—ด๊ฑฐ ํƒ€์ž…์œผ๋กœ ์‹ฑ๊ธ€ํ„ด์ž„์„ ๋ณด์ฆํ•˜๋ผ.
    .์•„์ดํ…œ 4 - ์ธ์Šคํ„ด์Šคํ™”๋ฅผ ๋ง‰์œผ๋ ค๊ฑฐ๋“  private ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ผ
    .์•„์ดํ…œ 5 - ์ž์›์„ ์ง์ ‘ ๋ช…์‹œํ•˜์ง€ ๋ง๊ณ  ์˜์กด ๊ฐ์ฒด ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋ผ
    .์•„์ดํ…œ 6 - ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ์„ ํ”ผํ•˜๋ผ
    .์•„์ดํ…œ 7 - ๋‹ค ์“ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•˜๋ผ.
    .์•„์ดํ…œ 8 - finalizer์™€ cleaner ์‚ฌ์šฉ์„ ํ”ผํ•˜๋ผ
    .์•„์ดํ…œ 9 - try-finally ๋ณด๋‹ค๋Š” try-with-resources๋ฅผ ์‚ฌ์šฉํ•˜๋ผ.


โœ”๏ธ ๋‚ด์šฉ.

 

2. ๊ฐ์ฒด ์ƒ์„ฑ๊ณผ ํŒŒ๊ดด

 

 ํ•™์Šต ๋‚ด์šฉ

1. ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•  ๋•Œ์™€ ๋งŒ๋“ค์ง€ ๋ง์•„์•ผ ํ•  ๋•Œ ๊ตฌ๋ถ„๋ฒ•
2. ์˜ฌ๋ฐ”๋ฅธ ๊ฐ์ฒด ์ƒ์„ฑ๋ฐฉ๋ฒ•
3. ๋ถˆํ•„์š”ํ•œ ์ƒ์„ฑ์„ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•
4. ์ œ ๋•Œ ํŒŒ๊ดด๋จ์„ ๋ณด์žฅํ•˜๊ณ  ํŒŒ๊ดด ์ „์— ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ์ •๋ฆฌ ์ž‘์—…์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•

 

 


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

 

 ํด๋ž˜์Šค๋Š” ํด๋ผ์ด์–ธํŠธ์— Public ์ƒ์„ฑ์ž ๋Œ€์‹  ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๊ฐ ์žฅ์ ๊ณผ ๋‹จ์ 

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

1. ์˜๋ฏธ ํ‘œํ˜„์ด ๋” ์ž˜ ๋œ๋‹ค.
ex) BigInteger(int) -> BigInteger.probablePrime(int)

2. ํ•˜๋‚˜์˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋กœ๋Š” ์ƒ์„ฑ์ž๋ฅผ ํ•˜๋‚˜๋งŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋ฐ˜๋ฉด ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์—๋Š” ์ œ์•ฝ์ด ์—†๋‹ค. 
ex) BigInteger(int) -> BigInteger.probablePrime(int), BigInteger.probablePrime2(int), BigInteger.probablePrime3(int) ๋“ฑ๋“ฑ

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


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


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

๋”ฐ๋ผ์„œ ๊ฐ™์€ ๊ฐ์ฒด๊ฐ€ ์ž์ฃผ ์š”์ฒญ๋˜๋Š” ์ƒํ™ฉ์—์„œ ์„ฑ๋Šฅ ํšจ๊ณผ๊ฐ€ ๋›ฐ์–ด๋‚˜๋‹ค.

*ํ”Œ๋ผ์ด์›จ์ดํŠธ ํŒจํ„ด(Flyweight pattern)๋„ ์ด์™€ ๋น„์Šทํ•œ ๊ธฐ๋ฒ•์ด๋‹ค.

ex) Boolean.valueOf(boolean)

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

public static
Boolean valueOf(boolean var0) {
    return var0 ? TRUE : FALSE;
}

2. ๋ฐ˜๋ณต๋˜๋Š” ์š”์ฒญ์— ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์‹์œผ๋กœ ์–ธ์ œ ์–ด๋Š ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ด์•„ ์žˆ๊ฒŒ ํ• ์ง€๋ฅผ ์ฒ ์ €ํžˆ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

 ์ด๋Ÿฐ ํ†ต์ œ๋ฅผ ์ธ์Šคํ„ด์Šค ํ†ต์ œ ํด๋ž˜์Šค๋ผ ํ•œ๋‹ค. ์ธ์Šคํ„ด์Šค๋ฅผ ํ†ต์ œ ํ•˜๋ฉด ์‹ฑ๊ธ€ํ„ด(์•„์ดํ…œ 3)์œผ๋กœ ๋ฐ˜๋“ค ์ˆ˜๋„, ์ธ์Šคํ„ด์Šคํ™” ๋ถˆ๊ฐ€(์•„์ดํ…œ 4)๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
 
 ๋˜ํ•œ ๋ถˆ๋ณ€ ๊ฐ’ ํด๋ž˜์Šค(์•„์ดํ…œ 17)์—์„œ ๋™์น˜์ธ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‹จ ํ•˜๋‚˜๋ฟ ์ž„์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.( a == b์ผ ๋•Œ๋งŒ a.equals(b) ๊ฐ€ ์„ฑ๋ฆฝ) 

 ์ธ์Šคํ„ด์Šค ํ†ต์ œ๋Š” ํ”Œ๋ผ์ด์›จ์ดํŠธ ํŒจํ„ด์˜ ๊ทผ๊ฐ„์ด ๋œ๋‹ค.
 
 ์—ด๊ฑฐ ํƒ€์ž…(์•„์ดํ…œ 34)์€ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•˜๋‚˜๋งŒ ๋งŒ๋“ค์–ด์ง์„ ๋ณด์žฅํ•œ๋‹ค.

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

 ์ƒ์„ฑ์ž์™€ ๊ฐ™์ด ๋ช…ํ™•ํžˆ ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์œผ๋‹ˆ ์‚ฌ์šฉ์ž๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ ๋ฐฉ์‹ ํด๋ž˜์Šค๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•  ๋ฐฉ๋ฒ•์„ ์•Œ์•„์•ผ ํ•œ๋‹ค. 
 (์‚ฌ์šฉ ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ์ •์  ํŒฉํ† ๋ฆฌ์ธ์ง€ ํ™•์ธํ•  ๋ฐฉ๋ฒ•?)

 ๋”ฐ๋ผ์„œ ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ์— ํ”ํžˆ ์‚ฌ์šฉํ•˜๋Š” ๋ช…๋ช… ๋ฐฉ์‹์œผ๋กœ ๊ทœ์•ฝ์„ ๋”ฐ๋ผ ์ง“๋Š”๋‹ค.

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

Date d = Date.from(Instant.now());


- 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์™€ ๊ฐ™์ง€๋งŒ, ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด ๋ฐ˜ํ™˜ํ•จ์„ ๋ณด์žฅํ•œ๋‹ค.

Object newArray = Array.newInstance(classObject, arrayLen);

 - getType : getInstance์™€ ๊ฐ™์œผ๋‚˜, ์ƒ์„ฑํ•  ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ํด๋ž˜์Šค์— ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ๋•Œ ์“ด๋‹ค. "Type"์€ ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•  ๊ฐ์ฒด์˜ ํƒ€์ž…์ด๋‹ค.

FileStore fs = Files.getFileStore(path);


 - newType: newInstance์™€ ๊ฐ™์œผ๋‚˜, ์ƒ์„ฑํ•  ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ํด๋ž˜์Šค์— ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ๋•Œ ์“ด๋‹ค. "Type"์€ ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•  ๊ฐ์ฒด์˜ ํƒ€์ž…์ด๋‹ค.

BufferedReader br = Files.newBufferedReader(path);

 - type: getType๊ณผ newType์˜ ๊ฐ„๊ฒฐํ•œ ๋ฒ„์ „

List<Complaint> litany = Collections.list(legacyLitany);




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


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

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


 ๋ฐ˜ํ™˜ ํƒ€์ž…์˜ ํ•˜์œ„ ํƒ€์ž…์ด๊ธฐ๋งŒ ํ•˜๋ฉด ์–ด๋–ค ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋“  ์ƒ๊ด€ ์—†๋‹ค.

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

public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> var0) {
    Enum[] var1 = getUniverse(var0);
    if (var1 == null) {
        throw new ClassCastException(var0 + " not an enum");
    } else {
        return (EnumSet)(var1.length <= 64 ? new RegularEnumSet(var0, var1) : new JumboEnumSet(var0, var1));
    }
}

 ํด๋ผ์ด์–ธํŠธ๋Š” ์œ„์˜ ๋‘ ํด๋ž˜์Šค์˜ ์กด์žฌ๋ฅผ ๋ชจ๋ฅธ๋‹ค. ์•Œํ•„์š”๋„ ์—†๋‹ค. EnumSet์˜ ํ•˜์œ„ ํด๋ž˜์Šค์ด๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
 
 ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์‹œ์ ์—๋Š” ๋ฐ˜ํ™˜ํ•  ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.


๋Œ€ํ‘œ์ ์œผ๋กœ JDBC ๋“œ๋ผ์ด๋ฒ„ ํด๋ž˜์Šค๋ฅผ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด Class.forName()์„ ์‚ฌ์šฉํ•œ๋‹ค. ํด๋ž˜์Šค ์ด๋ฆ„์„ ๋ฌธ์ž์—ด๋กœ ๋ฐ›์•„ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ Class ๊ฐ์ฒด๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ๋Š” JDBC ๋“œ๋ผ์ด๋ฒ„ ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•  ํ•„์š” ์—†์ด Class.forName()๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค.

try {
    Class<?> testClass = Class.forName("test");
} catch (ClassNotFoundException e) {
    throw new RuntimeException(e);
}

ex)
class LoggerFactory {
    private LoggerFactory() {
    // private constructor
    }

    public static Logger getLogger(Class clazz) {
    // implementation
    }

    public static Logger getLogger(String name) {
    // implementation
    }
}

public class Main {
    private static final Logger logger = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) {
        logger.info("Hello, world!");
    }
}


 LoggerFactory๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ logger ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ํด๋ž˜์Šค์˜ ์ด๋ฆ„์ด๋‚˜ ๋ฌธ์ž์—ด ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ ํ•  ์ˆ˜ ์žˆ๋‹ค. 
 

 

ํ•ต์‹ฌ ์ •๋ฆฌ

 ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ์™€ public ์ƒ์„ฑ์ž๋Š” ๊ฐ์ž์˜ ์“ฐ์ž„์ƒˆ๊ฐ€ ์žˆ์œผ๋‹ˆ ์ƒ๋Œ€์ ์ธ ์žฅ๋‹จ์ ์„ ์ดํ•ดํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.  ๊ทธ๋ ‡๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ ์ •์  ํŒฉํ„ฐ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์œ ๋ฆฌํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ์œผ๋ฏ€๋กœ ๋ฌด์ž‘์  public ์ƒ์„ฑ์ž๋ฅผ ์ œ๊ณตํ•˜๋˜ ์Šต๊ด€์ด ์žˆ๋‹ค๋ฉด ๊ณ ์น˜์ž

 

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

 

 ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ์„ ๋•Œ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•˜๋‹ค.

 

- ์ ์ธต์  ์ƒ์„ฑ์ž ํŒจํ„ด

    public NutritionFacts(int servingSize, int servings) {
        this(servingSize, servings, 0);
    }

    public NutritionFacts(int servingSize, int servings, int calories) {
        this(servingSize, servings, calories, 0);
    }

    public NutritionFacts(int servingSize, int servings, int calories, int fat) {
        this(servingSize, servings, calories, fat, 0);
    }

    public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) {
        this(servingSize, servings, calories, fat, sodium, 0);
    }
NutritionFacts nutritionFacts = new NutritionFacts(1, 2, 3, 4, 5, 6);

 

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

 

- ์ž๋ฐ”๋นˆ์ฆˆ ํŒจํ„ด


    public void
setServingSize(int servingSize) {
        this.servingSize = servingSize;
    }

    public void setServings(int servings) {
        this.servings = servings;
    }
    public void setCalories(int calories) {
        this.calories = calories;
    }
    public void setFat(int fat) {
        this.fat = fat;
    }

    public void setSodium(int sodium) {
        this.sodium = sodium;
    }

    public void setCarbohydrate(int carbohydrate) {
        this.carbohydrate = carbohydrate;
    }

NutritionFacts nutritionFacts2 = new NutritionFacts();
nutritionFacts2.setServingSize(1);
nutritionFacts2.setServings(2);
nutritionFacts2.setCalories(3);
nutritionFacts2.setFat(4);
nutritionFacts2.setSodium(5);
nutritionFacts2.setCarbohydrate(6);

 

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

 

- ๋นŒ๋” ํŒจํ„ด

 ์ ์ธต์  ์ƒ์ •์ž ํŒจํ„ด์˜ ์•ˆ์ „์„ฑ๊ณผ ์ž๋ฐ”๋นˆ์ฆˆ ํŒจํ„ด์˜ ๊ฐ€๋…์„ฑ์„ ๊ฒธ๋น„ํ•œ ํŒจํ„ด.

 

 

๋นŒ๋”๋Š” ์ƒ์„ฑํ•  ํด๋ž˜์Šค ์•ˆ์— ์ •์  ๋ฉค๋ฒ„ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์–ด ๋‘๋Š” ๊ฒŒ ๋ณดํ†ต์ด๋‹ค.

 

public static class Builder {
// ํ•„์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜
    
    private final int servingSize; // (mL, 1ํšŒ ์ œ๊ณต๋Ÿ‰) ํ•„์ˆ˜
    private final int servings; // (ํšŒ, ์ด nํšŒ ์ œ๊ณต๋Ÿ‰) ํ•„์ˆ˜

// ์„ ํƒ ๋งค๊ฐœ๋ณ€์ˆ˜ - ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
    private int calories = 0; // (1ํšŒ ์ œ๊ณต๋Ÿ‰๋‹น) ์„ ํƒ
    private int fat = 0; // (g/1ํšŒ ์ œ๊ณต๋Ÿ‰) ์„ ํƒ
    private int sodium = 0; // (mg/1ํšŒ ์ œ๊ณต๋Ÿ‰) ์„ ํƒ
    private int carbohydrate = 0;// (g/1ํšŒ ์ œ๊ณต๋Ÿ‰) ์„ ํƒ
    
public Builder(int servingSize, int servings) {
    this.servingSize = servingSize;
    this.servings = servings;
}

public Builder calories(int val) {
    calories = val;
    return this;
}

public Builder fat(int val) {
    fat = val;
    return this;
}

public Builder sodium(int val) {
    sodium = val;
    return this;
}

public Builder carbohydrate(int val) {
    carbohydrate = val;
    return this;
}

public NutritionFacts build() {
    return new NutritionFacts(this);
}
}
NutritionFacts nutritionFacts3 = new NutritionFacts.Builder(1, 2)
.calories(3)
.fat(4)
.sodium(5)
.carbohydrate(6)
.build();

 

NutritionFacts ํด๋ž˜์Šค๋Š” ๋ถˆ๋ณ€์ด๋ฉฐ, ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ธฐ๋ณธ๊ฐ’๋“ค์„ ํ•œ ๊ณณ์— ๋ชจ์•„ ๋‘์—ˆ๋‹ค. ๋นŒ๋”์˜ ์„ธํ„ฐ ๋ฉ”์„œ๋“ค์€ ์ž๊ธฐ ์ž์‹ ์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฐ์‡„์ ์œผ๋กœ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•˜๋‹ค (๋ฉ”์„œ๋“œ ์ฒด์ด๋‹)

 

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

 

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

 

ํ•ต์‹ฌ ์ •๋ฆฌ

 ์ƒ์„ฑ์ž๋‚˜ ์ •์  ํŒฉํ„ฐ๋ฆฌ๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ๋‹ค๋ฉด ๋นŒ๋” ํŒจํ„ด์„ ์„ ํƒํ•˜๋Š” ๊ฒŒ ๋” ๋‚ซ๋‹ค.
๋งค๊ฐœ ๋ณ€์ˆ˜ ์ค‘ ๋‹ค์ˆ˜๊ฐ€ ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ๊ฑฐ๋‚˜ ๊ฐ™์€ ํƒ€์ž…์ด๋ฉด ํŠนํžˆ ๋” ๊ทธ๋ ‡๋‹ค. ๋นŒ๋”๋Š” ์ ์ธต์  ์ƒ์„ฑ์ž๋ณด๋‹ค ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋ฅผ ์ฝ๊ณ  ์“ฐ๊ธฐ๊ฐ€ ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•˜๊ณ , ์ž๋ฐ”๋นˆ์ฆˆ๋ณด๋‹ค ํ›จ์”ฌ ์•ˆ์ „ํ•˜๋‹ค.

 


 

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

 

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

์ „ํ˜•์ ์ธ ์˜ˆ๋กœ ํ•จ์ˆ˜(์•„์ดํ…œ 24)์™€ ๊ฐ™์€ ๋ฌด์ƒํƒœ(stateless) ๊ฐ์ฒด๋‚˜ ์„ค๊ณ„์ƒ ์œ ์ผํ•ด์•ผ ํ•˜๋Š” ์‹œ์Šคํ…œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋“ค ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ํด๋ž˜์Šค๋ฅผ ์‹ฑ๊ธ€ํ„ด์œผ๋กœ ๋งŒ๋“ค ๊ฒฝ์šฐ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค.  ํƒ€์ž…์„ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ •์˜ํ•œ ๋‹ค์Œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ๋งŒ๋“  ์‹ฑ๊ธ€ํ„ด์ด ์•„๋‹ˆ๋ผ๋ฉด ์‹ฑ๊ธ€ํ„ด ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์งœ(Mock) ๊ตฌํ˜„์œผ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

 ์‹ฑ๊ธ€ํ„ด์„ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹์€ ๋ณดํ†ต ๋‘ ๊ฐ€์ง€๋กœ ๋‚˜๋‰œ๋‹ค. 

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

 

 - public static ๋ฉค๋ฒ„ final ํ•„๋“œ์ธ ๋ฐฉ์‹

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

private Elvis() {
}

public void leaveTheBuilding() {
    System.out.println("Elvis has left the building.");
}
}

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

public, protected ์ƒ์„ฑ์ž๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ „์ฒด ์‹œ์Šคํ…œ์—์„œ ํ•˜๋‚˜๋ฟ์ž„์„ ๋ณด์žฅํ•œ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์†์“ธ ๋ฐฉ๋ฒ•์€ ๋ฆฌํ”Œ๋ ‰์…˜ API(์•„์ดํ…œ 65)์ธ AccessibleObject.setAccessible์„ ์‚ฌ์šฉํ•ด ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

์ด๋Ÿฌํ•œ ๋ฆฌํ”Œ๋ ‰์…˜ ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•˜๋ ค๋ฉด ์ƒ์„ฑ์ž๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ๋‘ ๋ฒˆ์งธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋ ค ํ•  ๋•Œ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๊ฒŒ ํ•˜๋ฉด ๋œ๋‹ค.

 

 - ์žฅ์ 

 

1. ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์‹ฑ๊ธ€ํ„ด์ž„์ด ๋ช…๋ฐฑํžˆ ๋“œ๋Ÿฌ๋‚œ๋‹ค.

2. ๊ฐ„๊ฒฐํ•จ

 

 - ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฐฉ์‹์˜ ์‹ฑ๊ธ€ํ„ด

 

private static final Elvis INSTANCE2 = new Elvis();

public static Elvis getInstance() {
    return INSTANCE2;
}

public void leaveTheBuilding2() {
    System.out.println("Elvis has left the building.");
}

Elvis.getInstance๋Š” ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ์ฒด์˜ ์ฐธ์กฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ์ œ2์˜ Elvis ์ธ์Šคํ„ด์Šค๋Š” ๊ฒฐ์ฝ” ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š๋Š”๋‹ค. (์•ž์„  ๋ฐฉ์‹๊ณผ ๊ฐ™์ด ๋ฆฌํ”Œ๋ ‰์…˜ ์˜ˆ์™ธ๋Š” ๋˜‘๊ฐ™์ด ์ ์šฉ)

 

- ์žฅ์ 

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

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

3. ์ •์  ํŒฉํ„ฐ๋ฆฌ์˜ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ๊ณต๊ธ‰์ž(supplier)๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. - Elvis::getInstance -> Supplier<Elvis> (์•„์ดํ…œ 43, 44)

 

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

 ๋ชจ๋“  ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋ฅผ ์ผ์‹œ์ (transient)์ด๋ผ๊ณ  ์„ ์–ธํ•˜๊ณ  readResolve ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค(์•„์ดํ…œ 89) ์ด๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š์œผ๋ฉด ์ง๋ ฌํ™”๋œ ์ธ์Šคํ„ด์Šค๋ฅผ ์—ญ์ง๋ ฌํ™”ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๊ฐ€ ๋งŒ๋“ค์–ด์ง„๋‹ค. 

 ๊ฐ€์งœ Elvis ํƒ„์ƒ์„ ์˜ˆ๋ฐฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด Elvis ํด๋ž˜์Šค์— ๋‹ค์Œ์˜ readResolve ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์ž.

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

 

 - ์—ด๊ฑฐ ํƒ€์ž… ๋ฐฉ์‹์˜ ์‹ฑ๊ธ€ํ„ด - ๋ฐ”๋žŒ์งํ•œ ๋ฐฉ๋ฒ•

 

 public ํ•„๋“œ ๋ฐฉ์‹๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ, ๋” ๊ฐ„๊ฒฐํ•˜๊ณ  ์ถ”๊ฐ€ ๋…ธ๋ ฅ ์—†์ด ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ๊ณ , ์‹ฌ์ง€์–ด ์•„์ฃผ ๋ณต์žกํ•œ ์ง๋ ฌํ™” ์ƒํ™ฉ์ด๋‚˜ ๋ฆฌํ”Œ๋ ‰์…˜ ๊ณต๊ฒฉ์—์„œ๋„ ์ œ2์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ๊ธฐ๋Š” ์ผ์„ ์™„๋ฒฝํžˆ ๋ง‰์•„์ค€๋‹ค.

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

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

 


 

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

 

 ์ด๋”ฐ๊ธˆ ๋‹จ์ˆœํžˆ ์ •์  ๋ฉ”์„œ๋“œ์™€ ์ •์  ํ•„๋“œ๋งŒ์„ ๋‹ด์€ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์„ ๋•Œ์ด๋‹ค.

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

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

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

 

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

 

 ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์œผ๋กœ๋Š” ์ธ์Šคํ„ด์Šคํ™”๋ฅผ ๋ง‰์„ ์ˆ˜ ์—†๋‹ค. ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ์ธ์Šคํ„ด์Šคํ™”ํ•˜๋ฉด ๊ทธ๋งŒ์ด๋‹ค. ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒ์†ํ•ด์„œ ์‚ฌ์šฉํ•˜๋ผ๋Š” ๋œป์œผ๋กœ ์˜คํ•ดํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ ํฐ ๋ฌธ์ œ๋‹ค(์•„์ดํ…œ 19).

 

 ๋•Œ๋ฌธ์— private์œผ๋กœ ์ƒ์„ฑ์ž๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ public ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์•„ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šคํ™”๋ฅผ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

 


 

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

 

 ๋งŽ์€ ํด๋ž˜์Šค๊ฐ€ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ž์›์— ์˜์กดํ•œ๋‹ค. ๊ฐ€๋ น ๋งž์ถค๋ฒ• ๊ฒ€์‚ฌ๊ธฐ๋Š” ์‚ฌ์ „(dictionary)์— ์˜์กดํ•˜๋Š”๋ฐ, ์ด๋Ÿฐ ํด๋ž˜์Šค๋ฅผ ์ •์  ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค(์•„์ดํ…œ 4)๋กœ ๊ตฌํ˜„ํ•œ ๋ชจ์Šต์„ ๋“œ๋ฌผ์ง€ ์•Š๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

 ๋Œ€์‹  ํด๋ž˜์Šค(SpellChecker)๊ฐ€ ์—ฌ๋Ÿฌ ์ž์› ์ธ์Šคํ„ด์Šค๋ฅผ ์ง€์›ํ•ด์•ผ ํ•˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” ์ž์›(dictionary)์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

 

 ์ด๋ฅผ ๋งŒ์กฑํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์กฐ๊ฑด์€ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์ƒ์„ฑ์ž์— ํ•„์š”ํ•œ ์ž์›์„ ๋„˜๊ฒจ์ค€๋‹ค. ์ด๋Š” ์˜์กด ๊ฐ์ฒด ์ฃผ์ž…์˜ ํ•œ ํ˜•ํƒœ์ด๋‹ค.

 

public class SpellChecker {
private final Lexicon dictionary;

public SpellChecker(Lexicon dictionary) { // ์˜์กด ๊ฐ์ฒด ์ฃผ์ž…
    this.dictionary = Objects.requireNonNull(dictionary);  
}

public boolean isValid(String word){
    return true;
}

public static List<String> suggestions(String typo){
    return new ArrayList<>();
}
}

 

ํ•ต์‹ฌ ์ •๋ฆฌ

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

 

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

 

 ๋˜‘๊ฐ™์€ ๊ธฐ๋Šฅ์˜ ๊ฐ์ฒด๋ฅผ ๋งค๋ฒˆ ์ƒ์„ฑํ•˜๊ธฐ๋ณด๋‹ค๋Š” ๊ฐ์ฒด ํ•˜๋‚˜๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ๋‚˜์„ ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ์žฌ์‚ฌ์šฉ์€ ๋น ๋ฅด๊ณ  ์„ธ๋ จ๋˜๋‹ค.

ํŠนํžˆ ๋ถˆ๋ณ€ ๊ฐ์ฒด(์•„์ดํ…œ 17)๋Š” ์–ธ์ œ๋“  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

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๋กœ ์ •๊ทœํ‘œํ˜„์‹์„ ํ™œ์šฉํ•œ ๋ฉ”์„œ๋“œ์ด๋‹ค. 

๋ฌธ์ œ์ ์œผ๋กœ๋Š” String.matches๋Š” ์ •๊ทœํ‘œํ˜„์‹์œผ๋กœ ๋ฌธ์ž์—ด ํ˜•ํƒœ๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์ด์ง€๋งŒ, ์„ฑ๋Šฅ์ด ์ค‘์š”ํ•œ ์ƒํ™ฉ์—์„œ ๋ฐ˜๋ณตํ•ด ์‚ฌ์šฉํ•˜๊ธฐ์—” ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค. 

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

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

 

public boolean matches(String var1) {
    return Pattern.matches(var1, this);
}

public static boolean matches(String var0, CharSequence var1) {
    Pattern var2 = compile(var0);
    Matcher var3 = var2.matcher(var1);
    return var3.matches();
}

public static Pattern compile(String var0) {
    return new Pattern(var0, 0);
}

 

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

 

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})$"
);

/* String.matches */
static boolean isRomanNumeral(String s){
    return ROMAN.matcher(s).matches();
}
}

 

 ๋งŒ์ผ ๊ฐœ์„ ๋œ isRomanNumberal ๋ฐฉ์‹์˜ ํด๋ž˜์Šค๊ฐ€ ์ดˆ๊ธฐํ™” ํ›„ ํ•œ ๋ฒˆ๋„ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋ถˆํ•„์š”ํ•œ ์ดˆ๊ธฐํ™”๊ฐ€ ๋œ ๊ผด์ด๋‹ค.

์ด๋ฅผ ์œ„ํ•ด ์ง€์—ฐ ์ดˆ๊ธฐํ™”(์•„์ดํ…œ 83)๋กœ ์—†์•จ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ , ๊ถŒํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. 

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

 

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

์˜คํ†  ๋ฐ•์‹ฑ์€ ๊ธฐ๋ณธ ํƒ€์ž…๊ณผ ๊ทธ์— ๋Œ€์‘ํ•˜๋Š” ๋ฐ•์‹ฑ ๋œ ๊ธฐ๋ณธ ํƒ€์ž…์˜ ๊ตฌ๋ถ„์„ ํ๋ ค์ฃผ์ง€๋งŒ, ์™„์ „ํžˆ ์—†์• ์ฃผ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

 

 

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

 

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

๋‹จ์ˆœํžˆ sum ํƒ€์ž…์„ long์œผ๋กœ๋งŒ ๋ฐ”๊ฟ”์ฃผ๋ฉด ๋นจ๋ผ์ง„๋‹ค.

 

 ๋ฐ•์‹ฑ๋œ ๊ธฐ๋ณธ ํƒ€์ž…๋ณด๋‹ค๋Š” ๊ธฐ๋ณธํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๊ณ , ์˜๋„์น˜ ์•Š์€ ์˜คํ† ๋ฐ•์‹ฑ์ด ์ˆจ์–ด๋“ค์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•˜์ž.

 

 ์ด๋ฒˆ ์•„์ดํ…œ์€ ๋ฐฉ์–ด์  ๋ณต์‚ฌ(์•„์ดํ…œ 50)์™€ ๋Œ€์กฐ์ ์ด๋‹ค.

์ด๋ฒˆ ์•„์ดํ…œ์ด '๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์ง€ ๋งˆ๋ผ' ๋ผ๋ฉด, ๋ฐฉ์–ด์  ๋ณต์‚ฌ(์•„์ดํ…œ 50)๋Š” '์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋ฉด ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์ง€ ๋งˆ๋ผ'๋‹ค.

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

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


 

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

 

public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;

public Stack() {
this.elements = new Object[DEFAULT_INITIAL_CAPACITY];
}

public void push(Object e){
ensureCapacity();
elements[size++] = e;
}

public Object pop(){
if(size == 0)
throw new EmptyStackException();
Object result = elements[--size];
return result;
}

/**
* ์›์†Œ๋ฅผ ์œ„ํ•œ ๊ณต๊ฐ„์„ ์ ์–ด๋„ ํ•˜๋‚˜ ์ด์ƒ ํ™•๋ณดํ•œ๋‹ค.
* ๋ฐฐ์—ด ํฌ๊ธฐ๋ฅผ ๋Š˜๋ ค์•ผ ํ•  ๋•Œ๋งˆ๋‹ค ๋Œ€๋žต ๋‘ ๋ฐฐ์”ฉ ๋Š˜๋ฆฐ๋‹ค.
*/
private void ensureCapacity() {
if (elements.length == size)
elements = java.util.Arrays.copyOf(elements, 2 * size + 1);
}
}

 ์Šคํƒ์„ ์˜ˆ์‹œ๋กœ ๋ณด๋ฉด ์ด ์ฝ”๋“œ์—์„œ๋Š” ์Šคํƒ์ด ์ปค์กŒ๋‹ค๊ฐ€ ์ค„์–ด๋“ค์—ˆ์„ ๋•Œ ์Šคํƒ์—์„œ ๊บผ๋‚ด์ง„ ๊ฐ์ฒด๋“ค์„ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ํšŒ์ˆ˜ํ•˜์ง€ ์•Š๋Š”๋‹ค.

 ํ”„๋กœ๊ทธ๋žจ์—์„œ ๊ทธ ๊ฐ์ฒด๋“ค์„ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ ๋ง์ด๋‹ค. ์ด ์Šคํƒ์ด ๊ทธ ๊ฐ์ฒด๋“ค์˜ ๋‹ค ์“ด ์ฐธ์กฐ(obsolete reference)๋ฅผ ์—ฌ์ „ํžˆ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์—ฌ๊ธฐ์„œ ๋‹ค ์“ด ์ฐธ์กฐ๋ž€. ๋ฌธ์ž ๊ทธ๋Œ€๋กœ ์•ž์œผ๋กœ ๋‹ค์‹œ ์“ฐ์ง€ ์•Š์„ ์ฐธ์กฐ๋ฅผ ๋œปํ•œ๋‹ค.

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

 

 ํ•ด๋ฒ•์€ ๊ฐ„๋‹จํ•˜๋‹ค. ํ•ด๋‹น ์ฐธ์กฐ๋ฅผ ๋‹ค ์ผ์„ ๋•Œ Null ์ฒ˜๋ฆฌ(์ฐธ์กฐ ํ•ด์ œ)ํ•˜๋ฉด ๋œ๋‹ค.

์œ„์˜ ์ฝ”๋“œ์—์„œ๋Š” ์›์†Œ์˜ ์ฐธ์กฐ๊ฐ€ ๋” ์ด์ƒ ํ•„์š” ์—†์–ด์ง€๋Š” ์‹œ์ ์€ ์Šคํƒ์—์„œ ๊บผ๋‚ด์ง€๋Š” pop() ๋ฉ”์„œ๋“œ์—์„œ ์ด๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด null๋กœ ์ฐธ์กฐํ•ด์ œ ํ•˜๋ฉด ๋œ๋‹ค.

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

 

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

 

๊ทธ๋ ‡๋‹ค๋ฉด null ์ฒ˜๋ฆฌ๋Š” ์–ธ์ œ ํ•ด์•ผ ํ• ๊นŒ? Stack ํด๋ž˜์Šค๋Š” ์™œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์— ์ทจ์•ฝํ•  ๊ฑธ๊นŒ?

๋ฐ”๋กœ ์Šคํƒ์ด ์ž๊ธฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด ์Šคํƒ์€ elements ๋ฐฐ์—ด๋กœ ์ €์žฅ์†Œ ํ’€์„ ๋งŒ๋“ค์–ด ์›์†Œ๋“ค์„ ๊ด€๋ฆฌํ•œ๋‹ค. ๋ฐฐ์—ด์˜ ํ™œ์„ฑ ์˜์—ญ์— ์†ํ•œ ์›์†Œ๋“ค์ด ์‚ฌ์šฉ๋˜๊ณ  ๋น„ํ™œ์„ฑ ์˜์—ญ์€ ์“ฐ์ด์ง€ ์•Š๋Š”๋‹ค. ๋ฌธ์ œ๋Š” GC๋Š” ์ด ์‚ฌ์‹ค์„ ์•Œ ๊ธธ์ด ์—†๋‹ค๋Š” ๋ฐ ์žˆ๋‹ค. GC๊ฐ€ ๋ณด๊ธฐ์—๋Š” ๋น„ํ™œ์„ฑ ์˜์—ญ์—์„œ ์ฐธ์กฐํ•˜๋Š” ๊ฐ์ฒด๋„ ๋˜‘๊ฐ™์ด ์œ ํšจํ•œ ๊ฐ์ฒด๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ๋น„ํ™œ์„ฑ ์˜์—ญ์ด ๋˜๋Š” ์ˆœ๊ฐ„ null ์ฒ˜๋ฆฌํ•ด์„œ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋”๋Š” ์“ฐ์ง€ ์•Š์„ ๊ฒƒ์ž„์„ GC์— ์•Œ๋ ค์•ผ ํ•œ๋‹ค.

 

 ์ผ๋ฐ˜์ ์œผ๋กœ ์ž๊ธฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค๋ผ๋ฉด ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ํ•ญ์‹œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์— ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค. ์›์†Œ๋ฅผ ๋‹ค ์‚ฌ์šฉํ•œ ์ฆ‰์‹œ ์›์†Œ๊ฐ€ ์ฐธ์กฐํ•œ ๊ฐ์ฒด๋“ค์„ ๋‹ค null ์ฒ˜๋ฆฌํ•ด์ค˜์•ผ ํ•œ๋‹ค.

 

 ์บ์‹œ ์—ญ์‹œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์ผ์œผํ‚ค๋Š” ์ฃผ๋ฒ”์ด๋‹ค. ์šด ์ข‹๊ฒŒ ์บ์‹œ ์™ธ๋ถ€์—์„œ ํ‚ค(key)๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋™์•ˆ๋งŒ ์—”ํŠธ๋ฆฌ๊ฐ€ ์‚ด์•„ ์žˆ๋Š” ์บ์‹œ๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์ด๋ผ๋ฉด WeakHashMap์„ ์‚ฌ์šฉํ•ด ์บ์‹œ๋ฅผ ๋งŒ๋“ค์ž. ๋‹ค ์“ด ์—”ํŠธ๋ฆฌ๋Š” ๊ทธ ์ฆ‰์‹œ ์ž๋™์œผ๋กœ ์ œ๊ฑฐ๋  ๊ฒƒ์ด๋‹ค.

๋‹จ, WeakHashMap์€ ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ๋งŒ ์œ ์šฉํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•ด์•ผ ํ•œ๋‹ค.

 

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

 LinkedHashMap์€ removeEldestEntry ๋ฉ”์„œ๋“œ๋ฅผ ์จ์„œ ํ›„์ž์˜ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค. ๋” ๋ณต์žกํ•œ ์บ์‹œ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด java.lang.ref ํŒจํ‚ค์ง€๋ฅผ ์ง์ ‘ ํ™œ์šฉํ•ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค.

 

 ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์˜ ์„ธ ๋ฒˆ์งธ ์ฃผ๋ฒ”์€ ๋ฐ”๋กœ ๋ฆฌ์Šค๋„ˆ ํ˜น์€ ์ฝœ๋ฐฑ์ด๋ผ ๋ถ€๋ฅด๋Š” ๊ฒƒ์ด๋‹ค. 

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ฝœ๋ฐฑ์„ ๋“ฑ๋ก๋งŒ ํ•˜๊ณ  ๋ช…ํ™•ํžˆ ํ•ด์น˜ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๋ญ”๊ฐ€ ์กฐ์น˜ํ•ด์ฃผ์ง€ ์•Š๋Š” ํ•œ ์ฝœ๋ฐฑ์€ ๊ณ„์† ์Œ“์—ฌ๊ฐˆ ๊ฒƒ์ด๋‹ค. ์ด๋Ÿด ๋•Œ ์ฝœ๋ฐฑ์„ ์•ฝํ•œ ์ฐธ์กฐ(weak reference)๋กœ ์ €์žฅํ•˜๋ฉด ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ์ฆ‰์‹œ ์ˆ˜๊ฑฐํ•ด ๊ฐ„๋‹ค. ์˜ˆ๋กœ WeakHashMap์— ํ‚ฌ๋กœ ์ €์žฅํ•˜๋ฉด ๋œ๋‹ค.

* WeakReference : ์•ฝํ•œ ์ฐธ์กฐ ๊ณต๋ถ€ํ•˜๊ธฐ
ํ•ต์‹ฌ ์ •๋ฆฌ

 ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋Š” ๊ฒ‰์œผ๋กœ ์ž˜ ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์•„ ์‹œ์Šคํ…œ์— ์ˆ˜๋…„๊ฐ„ ์ž ๋ณตํ•˜๋Š” ์‚ฌ๋ก€๋„ ์žˆ๋‹ค. ์ด๋Ÿฐ ๋ˆ„์ˆ˜๋Š” ์ฒ ์ €ํ•œ ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋‚˜ ํž™ ํ”„๋กœํŒŒ์ผ๋Ÿฌ ๊ฐ™์€ ๋””๋ฒ„๊น… ๋„๊ตฌ๋ฅผ ๋™์›ํ•ด์•ผ๋งŒ ๋ฐœ๊ฒฌ๋˜๊ธฐ๋„ ํ•œ๋‹ค. ๊ทธ๋ž˜์•ผ ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ๋ฌธ์ œ๋Š” ์˜ˆ๋ฐฉ๋ฒ•์„ ์ตํ˜€๋‘๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค.

 


 

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

 

 ์ž๋ฐ”๋Š” ๋‘ ๊ฐ€์ง€ ๊ฐ์ฒด ์†Œ๋ฉธ์ž๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ๊ทธ์ค‘ finalizer๋Š” ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๊ณ , ์ƒํ™ฉ์— ๋”ฐ๋ผ ์œ„ํ—˜ํ•  ์ˆ˜ ์žˆ์–ด ์ผ๋ฐ˜์ ์œผ๋กœ ๋ถˆํ•„์š”ํ•˜๋‹ค. ์˜ค๋™์ž‘, ๋‚ฎ์€ ์„ฑ๋Šฅ ์ด์‹์„ฑ ๋ฌธ์ œ์˜ ์›์ธ์ด ๋˜๊ธฐ๋„ ํ•œ๋‹ค.  ์ด๋ฒˆ ์žฅ์—์„œ ๋ช‡ ๊ฐ€์ง€ ์“ฐ์ž„์ƒˆ๋ฅผ ์†Œ๊ฐœํ•˜์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ '์“ฐ์ง€ ๋ง์•„์•ผ' ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์ž๋ฐ” 9์—์„œ๋Š” finalizer๋ฅผ ์‚ฌ์šฉ ์ž์ œ(deprecated) API๋กœ ์ง€์ •ํ•˜๊ณ  cleaner๋ฅผ  ๊ทธ ๋Œ€์•ˆ์œผ๋กœ ์†Œ๊ฐœํ–ˆ๋‹ค.

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

 

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

์˜ˆ์ปจ๋Œ€ ํŒŒ์ผ ๋‹ซ๊ธฐ๋ฅผ finalizer๋‚˜ cleaner์— ๋งก๊ธฐ๋ฉด ์ค‘๋Œ€ํ•œ ์˜ค๋ฅ˜๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ์‹œ์Šคํ…œ์ด ๋™์‹œ์— ์—ด ์ˆ˜ ์žˆ๋Š” ํŒŒ์ผ ๊ฐœ์ˆ˜์— ํ•œ๊ณ„๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

 finalizer์™€ cleaner๋ฅผ ์–ผ๋งˆ๋‚˜ ์‹ ์†ํžˆ ์ˆ˜ํ–‰ํ• ์ง€๋Š” ์ „์ ์œผ๋กœ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋‹ฌ๋ ค์žˆ๋‹ค.

 

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

์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ์ผ๋ถ€ ๊ฐ์ฒด์— ๋”ธ๋ฆฐ ์ข…๋ฃŒ ์ž‘์—…์„ ์ „ํ˜€ ์ˆ˜ํ–‰ํ•˜์ง€ ๋ชปํ•œ ์ฑ„ ํ”„๋กœ๊ทธ๋žจ์ด ์ค‘๋‹จ๋  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์–˜๊ธฐ๋‹ค ๋”ฐ๋ผ์„œ ํ”„๋กœ๊ทธ๋žจ ์ƒ์•  ์ฃผ๊ธฐ์™€ ์ƒ๊ด€์—†๋Š”, ์ƒํƒœ๋ฅผ ์˜๊ตฌ์ ์œผ๋กœ ์ˆ˜์ •ํ•˜๋Š” ์ž‘์—…์—์„œ๋Š” ์ ˆ๋Œ€ finlizer๋‚˜ cleaner์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.

 ์˜ˆ๋กœ DB ๊ฐ™์€ ๊ณต์œ  ์ž์›์˜ ์˜๊ตฌ ๋ฝ ํ•ด์ œ๋ฅผ finalizer๋‚˜ cleaner์— ๋งก๊ฒจ ๋†“์œผ๋ฉด ๋ถ„์‚ฐ ์‹œ์Šคํ…œ ์ „์ฒด๊ฐ€ ์„œ์„œํžˆ ๋ฉˆ์ถ”๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

 

 finalizer๋Š” ์‚ฌ์šฉํ•œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํŒŒ๊ดดํ•˜๋‹ˆ GC์˜ ํšจ์œจ์„ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค. 

 

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

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

 

 

 

 finalizer๋‚˜ cleaner ๋Œ€์•ˆ์œผ๋กœ๋Š” AutoCloseable์„ ๊ตฌํ˜„ํ•ด ์ฃผ๊ณ , ํด๋ผ์ด์–ธํŠธ์—์„œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‹ค ์“ฐ๊ณ  ๋‚˜๋ฉด close ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค. (์•„์ดํ…œ 9 ์ฐธ์กฐ).

 

 finalizer์™€ cleaner์˜ ์“ฐ์ž„์ƒˆ๋Š” ์–ด๋””์ผ๊นŒ?

 

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

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

 

2. ๋„ค์ดํ‹ฐ๋ธŒ ํ”ผ์–ด ์—ฐ๊ฒฐ ๊ฐ์ฒด ํšŒ์ˆ˜

 - ๋„ค์ดํ‹ฐ๋ธŒ ํ”ผ์–ด(Native peer)๋ž€ ์ผ๋ฐ˜ ์ž๋ฐ” ๊ฐ์ฒด๊ฐ€ ๋„ค์ดํ‹ฐ๋ธŒ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ธฐ๋Šฅ์„ ์œ„์ž„ํ•œ ๋„ค์ดํ‹ฐ๋ธŒ ๊ฐ์ฒด๋ฅผ ๋งํ•œ๋‹ค. ๋„ค์ดํ‹ฐ๋ธŒ ํ”ผ์–ด๋Š” ์ž๋ฐ” ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋‹ˆ GC๋Š” ๊ทธ ์กด์žฌ๋ฅผ ์•Œ์ง€ ๋ชปํ•œ๋‹ค. ๋”ฐ๋ผ์„œ finalizer๋‚˜ cleaner ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๊ธฐ์— ์ ๋‹นํ•œ ์ž‘์—…์ด๋‹ค.

๋‹จ, ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๊ฐ๋‹นํ•  ์ˆ˜ ์—†๊ฑฐ๋‚˜, ๋„ค์ดํ‹ฐ๋ธŒ ํ”ผ์–ด๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์ž์›์„ ์ฆ‰์‹œ ํšŒ์ˆ˜ ํ•ด์•ผ ํ•œ๋‹ค๋ฉด close๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

 

 cleaner ์‚ฌ์šฉ ์˜ˆ

Room ํด๋ž˜์Šค๋กœ ๋ฐฉ(room) ์ž์›์„ ์ˆ˜๊ฑฐํ•˜๊ธฐ ์ „์— ๋ฐ˜๋“œ์‹œ ์ฒญ์†Œ(clean) ํ•ด์•ผ ํ•œ๋‹ค. 

import java.lang.ref.Cleaner;

public class Room implements AutoCloseable {

private static final Cleaner cleaner = Cleaner.create();

// ์ฒญ์†Œ๊ฐ€ ํ•„์š”ํ•œ ์ž์›. ์ ˆ๋Œ€ Room์„ ์ฐธ์กฐํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค!
private static class State implements Runnable{

int numJunkPiles; // Room ์•ˆ์˜ ์“ฐ๋ ˆ๊ธฐ ์ˆ˜

State(int numJunkPiles){
    this.numJunkPiles = numJunkPiles;
}

// close ๋ฉ”์„œ๋“œ๋‚˜ cleaner๊ฐ€ ํ˜ธ์ถœํ•œ๋‹ค.
@Override
public void run() {
    System.out.println("Cleaning Room");
    numJunkPiles = 0;
}
}

private final State state;

private final Cleaner.Cleanable cleanable;

public Room(int numJunkPiles){
    state = new State(numJunkPiles);
    cleanable = cleaner.register(this, state);
}

@Override
public void close() throws Exception {
cleanable.clean();
}
}

 

 run() ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ์ƒํ™ฉ์€ ๋‘˜ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

๋ณดํ†ต์€  Room์˜ close ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋‹ค. close ๋ฉ”์„œ๋“œ์—์„œ Cleanable์˜ clean์„ ํ˜ธ์ถœํ•˜๋ฉด ์ด ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ run์„ ํ˜ธ์ถœํ•œ๋‹ค.

 ํ˜น์€ GC๊ฐ€ Room์„ ํšŒ์ˆ˜ํ•  ๋•Œ๊นŒ์ง€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ close๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, cleaner๊ฐ€ State์˜ run ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ์ค„ ๊ฒƒ์ด๋‹ค.

 State ์ธ์Šคํ„ด์Šค๋Š” '์ ˆ๋Œ€๋กœ' Room ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.

Room ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•  ๊ฒฝ์šฐ ์ˆœํ™˜์ฐธ์กฐ๊ฐ€ ์ƒ๊ฒจ GC๊ฐ€ Room ์ธ์Šคํ„ด์ˆ˜๋ฅผ ํšŒ์ˆ˜ ํ•ด๊ฐˆ ๊ธฐํšŒ๊ฐ€ ์˜ค์ง€ ์•Š๋Š”๋‹ค.

State๊ฐ€ ์ •์  ์ค‘์ฒฉ ํด๋ž˜์Šค์ธ ์ด์œ ๊ฐ€ ์žˆ๋‹ค. ์ •์  ์ด์•„๋‹Œ ์ค‘์ฒฉ ํด๋ž˜์Šค๋Š” ์ž๋™์œผ๋กœ ๋ฐ”๊นฅ ๊ฐ์ฒด์˜ ์ฐธ์กฐ๋ฅผ ๊ฐ–๊ฒŒ ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค(์•„์ดํ…œ 24)

 

 ์•ž์„œ ์ด์•ผ๊ธฐํ•œ ๋Œ€๋กœ Room์˜ cleaner๋Š” ๋‹จ์ง€ ์•ˆ์ •๋ง์ด๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ชจ๋“  Room ์ƒ์„ฑ์„ try-with-resources ๋ธ”๋ก์œผ๋กœ ๊ฐ์ŒŒ๋‹ค๋ฉด ์ž๋™ ์ฒญ์†Œ๋Š” ์ „ํ˜€ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค.

 

 ์ข‹์€ ์˜ˆ

public static void main(String[] args) throws Exception {
// try-with-resources๋ฅผ ์‚ฌ์šฉํ•ด ์˜ˆ์™ธ๋ฅผ ํšŒํ”ผํ•œ๋‹ค.
    try(Room room = new Room(7)){
        System.out.println("์•ˆ๋…•");
    }
}

 ์ข‹์ง€ ์•Š์€ ์˜ˆ

public static void main(String[] args) {
// try-with-resources๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„ ๋ฐฉ์ฒญ์†Œ๋ฅผ ์ถœ๋ ฅ๋˜๋ฆฌ๋ผ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์—†๋‹ค.
// Room ์ƒ์„ฑ์ž์—์„œ Cleaner์˜ register ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ Room์„ ์ฐธ์กฐํ•˜๋ฏ€๋กœ Room์€ Cleaner๊ฐ€ ์ˆ˜๊ฑฐํ•  ๋•Œ๊นŒ์ง€ ํšŒ์ˆ˜๋˜์ง€ ์•Š๋Š”๋‹ค.
// ๋”ฐ๋ผ์„œ Room์˜ close ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœ๋˜์ง€ ์•Š๊ณ , Room์— ๋‹ด๊ธด ์“ฐ๋ ˆ๊ธฐ ์ˆ˜๋„ 0์œผ๋กœ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š๋Š”๋‹ค.
// ์ด ํ”„๋กœ๊ทธ๋žจ์€ "Peace out"์„ ์ถœ๋ ฅํ•˜๊ณ  ์ข…๋ฃŒ๋œ๋‹ค.
// ์ด๋Ÿฐ ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด Room์„ try-with-resources ๋ธ”๋ก ๋ฐ”๊นฅ์—์„œ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•œ๋‹ค.
// try-with-resources ๋ธ”๋ก ๋ฐ”๊นฅ์—์„œ ์ดˆ๊ธฐํ™”ํ•˜๋ฉด Room์ด ์˜์›ํžˆ ์—ด๋ ค์žˆ์ง€ ์•Š๊ฒŒ ๋œ๋‹ค.
    Room room = new Room(99);
    System.out.println("Peace out");
}

  - System.exit์„ ํ˜ธ์ถœํ•   ๋•Œ์˜ cleaner ๋™์ž‘์€ ๊ตฌํ˜„ํ•˜๊ธฐ ๋‚˜๋ฆ„์ด๋‹ค. ์ฒญ์†Œ๊ฐ€ ์ด๋ค„์งˆ์ง€๋Š” ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

ํ•ต์‹ฌ ์ •๋ฆฌ

 cleaner(์ž๋ฐ” 8๊นŒ์ง€๋Š” finalizer)๋Š” ์•ˆ์ „๋ง ์—ญํ• ์ด๋‹ˆ ์ค‘์š”ํ•˜์ง€ ์•Š์€ ๋„ค์ดํ‹ฐ๋ธŒ ์ž์› ํšŒ์ˆ˜์šฉ์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•˜์ž. ๋ฌผ๋ก  ์ด๋Ÿฐ ๊ฒฝ์šฐ๋ผ๋„ ๋ถˆํ™•์‹ค์„ฑ๊ณผ ์„ฑ๋Šฅ ์ €ํ•˜์— ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.

 

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

 

 java ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—๋Š” close ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ์ง์ ‘ ๋‹ซ์•„์ค˜์•ผ ํ•˜๋Š” ์ž์›์ด ๋งŽ๋‹ค. Stream, Connection ๋“ฑ์ด ์žˆ๋‹ค.

 

์ „ํ†ต์ ์œผ๋กœ ์ž์›์ด ์ œ๋Œ€๋กœ ๋‹ซํž˜์„ ๋ณด์žฅํ•˜๋Š” ์ˆ˜๋‹จ์ธ try-finally

 

static String firstLineOfFile(String path) throws Exception {
    BufferedReader br = new BufferedReader(new java.io.FileReader(path));
    try {
        return br.readLine();
    } finally {
        br.close();
    }
}

์ž์›์„ ํ•˜๋‚˜ ๋” ์ผ์„ ๊ฒฝ์šฐ?

static void copy(String src, String dst) throws Exception {
    InputStream in = new FileInputStream(src);
    try {
        OutputStream out = new FileOutputStream(dst);
        try {
            byte[] buf = new byte[100];
            int n;
        while((n = in.read(buf)) >= 0)
        out.write(buf, 0, n);
        } finally {
            out.close(); 
        }
    } finally {
    in.close();
    }
}

 try-finally ๋ฌธ์„ ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ•œ ์•ž์˜ ๋‘ ์ฝ”๋“œ ์˜ˆ์ œ์—์กฐ์ฐจ ๋ฏธ๋ฌ˜ํ•œ ๊ฒฐ์ ์ด ์žˆ๋‹ค.

์˜ˆ์™ธ๋Š” tryh ๋ธ”๋ก๊ณผ finally ๋ธ”๋ก ๋ชจ๋‘์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋กœ ๊ธฐ๊ธฐ์— ๋ฌผ๋ฆฌ์  ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ๊ฒฝ์šฐ firstLineOfFile ๋ฉ”์„œ๋“œ ์•ˆ์˜ readLine ๋ฉ”์„œ๋“œ๊ฐ€ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๊ณ , ๊ฐ™์€ ์ด์œ ๋กœ close ๋ฉ”์„œ๋“œ๋„ ์‹คํŒจํ•  ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฐ ์ƒํ™ฉ์ด๋ผ๋ฉด ๋‘ ๋ฒˆ์งธ ์˜ˆ์™ธ๊ฐ€ ์ฒซ ๋ฒˆ์งธ ์˜ˆ์™ธ๋ฅผ ์™„์ „ํžˆ ์ง‘์–ด์‚ผํ‚ค๊ฒŒ ๋œ๋‹ค. ์ด๋กœ์ธ ํ—ค ์‹ค์ œ ์˜ค๋ฅ˜ ํŒŒ์•…์ด ํž˜๋“ค๊ฒŒ ๋˜๊ณ  ๋””๋ฒ„๊น…์„ ๋ชน์‹œ ์–ด๋ ต๊ฒŒ ํ•œ๋‹ค.

 

 ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋“ค์€ ์ž๋ฐ” 7์—์„œ try-with-resources ๋•์— ๋ชจ๋‘ ํ•ด๊ฒฐ๋˜์—ˆ๋‹ค.

์ด ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํ•ด๋‹น ์ž์›์ด AutoCloseable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค. ๋‹จ์ˆœํžˆ void๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” close ๋ฉ”์„œ๋“œ ํ•˜๋‚˜๋งŒ ๋ฉ๊ทธ๋Ÿฌ๋‹ˆ ์ •์˜ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค. ์ž๋ฐ” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์„œ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์˜ ์ˆ˜๋งŽ์€ ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ด๋ฏธ AutoCloseable์„ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ํ™•์žฅํ•ด ๋’€๋‹ค. ๋งŒ์ผ ๋‹ซ์•„์•ผ ํ•˜๋Š” ์ž์›์„ ๋œปํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ฉด AutoCloseable์„ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•˜๊ธฐ ๋ฐ”๋ž€๋‹ค.

 

 ์œ„์˜ ๋‘ ๋ฉ”์„œ๋“œ๋ฅผ try-with-resources๋ฅผ ์ ์šฉํ•œ ๋ชจ์Šต์ด๋‹ค.

static String firstLineOfFile(String path) throws Exception {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
         return br.readLine();
    }
}

static void copy(String src, String dst) throws Exception {
    try (InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dst)) {
        byte[] buf = new byte[100];
        int n;
        while ((n = in.read(buf)) >= 0)
        out.write(buf, 0, n);
    }
}

 

 ์ˆ˜์ • ๋ฒ„์ „์ด ์ฝ๊ธฐ ์ˆ˜์›”ํ•  ๋ฟ ์•„๋‹ˆ๋ผ. ๋ฌธ์ œ ์ง„๋‹จ์—๋„ ํ›จ์”ฌ ์ข‹๋‹ค.

readLine๊ณผ close ํ˜ธ์ถœ ์–‘์ชฝ์—์„œ ์˜ˆ์™ธ ๋ฐœ์ƒํ•˜๊ฒŒ ๋  ๊ฒฝ์šฐ, close์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋Š” ์ˆจ๊ฒจ์ง€๊ณ  readLine์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๊ฐ€ ๊ธฐ๋ก๋œ๋‹ค. ์ด๋ ‡๊ฒŒ ์ˆจ๊ฒจ์ง„ ์˜ˆ์™ธ๋“ค๋„ ๊ทธ๋ƒฅ ๋ฒ„๋ ค์ง€์ง€๋Š” ์•Š๊ณ , ์Šคํƒ ์ถ”์  ๋‚ด์—ญ์— '์ˆจ๊ฒจ์กŒ๋‹ค(suppressed)'๋ผ๋Š” ๊ผฌ๋ฆฌํ‘œ๋ฅผ ๋‹ฌ๊ณ  ์ถœ๋ ฅ๋œ๋‹ค. ๋˜ํ•œ Java 7์—์„œ Throwable์— ์ถ”๊ฐ€๋˜๋‹ˆ getSuppressed ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ ์ฝ”๋“œ์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋„ ์žˆ๋‹ค.

 

 ๋ณดํ†ต์˜ try-finally์ฒ˜๋Ÿผ try-with-resoureces์—์„œ๋„ catch ์ ˆ์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

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

 

ํ•ต์‹ฌ ์ •๋ฆฌ

 ๊ผญ ํšŒ์ˆ˜ํ•ด์•ผ ํ•˜๋Š” ์ž์›์„ ๋‹ค๋ฃฐ ๋•Œ๋Š” try-finally ๋ง๊ณ , try-with-resources๋ฅผ ์‚ฌ์šฉํ•˜์ž.
์˜ˆ์™ธ๋Š” ์—†๋‹ค. ์ฝ”๋“œ๋Š” ๋” ์งง๊ณ  ๋ถ„๋ช…ํ•ด์ง€๊ณ , ๋งŒ๋“ค์–ด์ง€๋Š” ์˜ˆ์™ธ ์ •๋ณด๋„ ํ›จ์”ฌ ์œ ์šฉํ•˜๋‹ค. try-finally๋กœ ์ž‘์„ฑํ•˜๋ฉด ์‹ค์šฉ์ ์ด์ง€ ๋ชปํ•  ๋งŒํผ ์ฝ”๋“œ๊ฐ€ ์ง€์ €๋ถ„ํ•ด์ง€๋Š” ๊ฒฝ์šฐ๋ผ๋„, try-with-resources๋กœ๋Š” ์ •ํ™•ํ•˜๊ณ  ์‰ฝ๊ฒŒ ์ž์›์„ ํšŒ์ˆ˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

 


Gihub Code - https://github.com/younwony/effectiveJava/tree/master/src/main/java/dev/wony/effectivejava/chapter_1
๐Ÿ“ ๋Š๋‚€์ .

์ƒ๊ฐ๋ณด๋‹ค ๋ชฐ๋ž๋˜ ๋ถ€๋ถ„๋“ค์ด ๋งŽ์•„์„œ ๋ถ€์กฑํ•œ ๋ถ€๋ถ„์„ ๋งŽ์ด ์ฑ„์šด ๋Š๋‚Œ์ด์—ˆ๋‹ค.