Search
๐Ÿ“š

Effective Java 3/E

Effective Java 3/E ๐Ÿ’ก

Java๋ผ๋Š” ์–ธ์–ด ์ž์ฒด์˜ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ๋ฐ”ํƒ•์œผ๋กœ ์ข‹์€ Java ์ฝ”๋“œ๋ž€ ๋ฌด์—‡์ธ๊ฐ€๋ฅผ ์ดํ•ดํ•˜๋Š”๋ฐ ๋งŽ์€ ๋„์›€์ด ๋œ ์ฑ…์ด๋‹ค. ์ถ”ํ›„ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ์ฐธ๊ณ ํ•  ์šฉ๋„๋กœ ์ •๋ฆฌํ•œ๋‹ค. ๋” ์ข‹์€ ์ฝ”๋“œ, ๋” ๋‚˜์€ ์ฝ”๋“œ๋ฅผ ์งœ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๊ณ  ์‹ถ๋‹ค.

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

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

์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ (static factory method)
public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
Java
๋ณต์‚ฌ
โ€ข
์žฅ์ 
โ—ฆ
์ด๋ฆ„์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.
โ–ช
์ƒ์„ฑ์ž์˜ ๊ฒฝ์šฐ, ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ƒ์„ฑ์ž ์ž์ฒด๋งŒ์œผ๋กœ๋Š” ๋ฐ˜ํ™˜๋  ๊ฐ์ฒด์˜ ํŠน์„ฑ์„ ์ œ๋Œ€๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์—†๋‹ค.
โ–ช
๋ฐ˜๋ฉด, ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” ์ด๋ฆ„๋งŒ ์ž˜์ง€์œผ๋ฉด ๋ฐ˜ํ™˜๋  ๊ฐ์ฒด์˜ ํŠน์„ฑ์„ ์‰ฝ๊ฒŒ ๋ฌ˜์‚ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
โ€ข
์ƒ์„ฑ์ž: BigInteger(int, int, Random)
โ€ข
์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ: BigInteger.probablePrime
โ—ฆ
ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
โ–ช
์ธ์Šคํ„ด์Šค๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด ๋†“๊ฑฐ๋‚˜, ์ƒˆ๋กœ ์ƒ์„ฑํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์บ์‹ฑํ•˜์—ฌ ์žฌํ™œ์šฉํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
๋ฐ˜ํ™˜ ํƒ€์ž…์˜ ํ•˜์œ„ ํƒ€์ž… ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์ด ์žˆ๋‹ค.
โ–ช
๋ฐ˜ํ™˜ํ•  ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค. โ†’ ์œ ์—ฐ์„ฑ
โ—ฆ
์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋”ฐ๋ผ ๋งค๋ฒˆ ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
โ–ช
๋ฐ˜ํ™˜ ํƒ€์ž…์˜ ํ•˜์œ„ ํƒ€์ž…์ด๊ธฐ๋งŒ ํ•˜๋ฉด ์–ด๋–ค ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด๋„ ์ƒ๊ด€์—†๋‹ค.
โ—ฆ
์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์‹œ์ ์—๋Š” ๋ฐ˜ํ™˜ํ•  ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
โ€ข
๋‹จ์ 
โ—ฆ
์ƒ์†์„ ํ•˜๋ ค๋ฉด public์ด๋‚˜ protected ์ƒ์„ฑ์ž๊ฐ€ ํ•„์š”ํ•˜๋‹ˆ ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋งŒ ์ œ๊ณตํ•˜๋ฉด ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค.
โ—ฆ
์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ฐพ๊ธฐ ์–ด๋ ต๋‹ค.
โ–ช
์ƒ์„ฑ์ž์ฒ˜๋Ÿผ API ์„ค๋ช…์— ๋ช…ํ™•ํžˆ ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์œผ๋‹ˆ, ์‚ฌ์šฉ์ž๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ ๋ฐฉ์‹ ํด๋ž˜์Šค๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•  ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ด์•ผํ•œ๋‹ค.
โ–ช
๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ๋„๋ฆฌ ์•Œ๋ ค์ง„ ๊ทœ์•ฝ์„ ๋”ฐ๋ผ ์ง€์–ด ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ์™„ํ™”ํ•œ๋‹ค.
โ€ข
from : ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ํ•˜๋‚˜ ๋ฐ›์•„์„œ ํ•ด๋‹น ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ˜•๋ณ€ํ™˜ ๋ฉ”์„œ๋“œ
โ—ฆ
Date d = Date.from(instant);
โ€ข
of : ์—ฌ๋Ÿฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„ ์ ํ•ฉํ•œ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ง‘๊ณ„ ๋ฉ”์„œ๋“œ
โ—ฆ
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
โ€ข
valueOf : from๊ณผ of์˜ ๋” ์ž์„ธํ•œ ๋ฒ„์ „
โ€ข
instance ํ˜น์€ getInstance : ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ช…์‹œํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ, ๊ฐ™์€ ์ธ์Šคํ„ด์Šค ์ž„์„ ๋ณด์žฅํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค.
โ€ข
create ํ˜น์€ newInstance : instance ํ˜น์€ getInstance์™€ ๊ฐ™์ง€๋งŒ, ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด ๋ฐ˜ํ™˜ํ•จ์„ ๋ณด์žฅํ•œ๋‹ค.
โ€ข
getType : getInstance์™€ ๊ฐ™์œผ๋‚˜, ์ƒ์„ฑํ•  ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ํด๋ž˜์Šค์— ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ๋•Œ ์“ด๋‹ค. โ€œTypeโ€์€ ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•  ๊ฐ์ฒด์˜ ํƒ€์ž…์ด๋‹ค.
โ—ฆ
FileStore fs = Files.getFileStore(path);
โ€ข
newType : newInstance์™€ ๊ฐ™์œผ๋‚˜, ์ƒ์„ฑํ•  ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ํด๋ž˜์Šค์— ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ๋•Œ ์“ด๋‹ค. โ€œTypeโ€์€ ํŽ™ํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•  ๊ฐ์ฒด์˜ ํƒ€์ž…์ด๋‹ค.
โ—ฆ
BufferReader br = Files.newBufferdReader(path);
โ€ข
type : getType๊ณผ newType์˜ ๊ฐ„๊ฒฐํ•œ ๋ฒ„์ „
โ—ฆ
List<Complaint> litany = Collections.list(legacyLitany);

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

โ€ข
์ƒ์„ฑ์ž๋Š” ์„ ํƒ์  ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ์„ ๋•Œ ์ ์ ˆํžˆ ๋Œ€์‘ํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
โ€ข
์ƒ์„ฑ์ž/์ •์  ํŒฉํ„ฐ๋ฆฌ๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผํ•  ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ์„ ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŒจํ„ด
โ—ฆ
์ ์ธต์  ์ƒ์„ฑ์ž ํŒจํ„ด ์‚ฌ์šฉ โ†’ ์—ฌ๋Ÿฌ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€์‘ํ•˜๋Š” ์ƒ์„ฑ์ž ๊ฐ€๋Šฅ
โ–ช
ํ•˜์ง€๋งŒ, ์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ •ํ•˜๊ธธ ์›์น˜ ์•Š๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๊นŒ์ง€ ํฌํ•จํ•œ๋‹ค. โ†’ ์–ด์ฉ” ์ˆ˜ ์—†์ด ํ•ด๋‹น ๋งค๊ฐœ๋ณ€์ˆ˜์—๋„ ๊ฐ’์„ ์ง€์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.
โ–ช
ํ™•์žฅํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
โ—ฆ
์ž๋ฐ”๋นˆ์ฆˆ ํŒจํ„ด ์‚ฌ์šฉ โ†’ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” ์ƒ์„ฑ์ž๋กœ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ , setter ๋ฉ”์„œ๋“œ๋“ค์„ ํ˜ธ์ถœํ•ด ์›ํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์„ค์ •
โ–ช
๊ฐ์ฒด ํ•˜๋‚˜๋ฅผ ๋งŒ๋“œ๋ ค๋ฉด ๋ฉ”์„œ๋“œ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ ํ˜ธ์ถœํ•ด์•ผํ•œ๋‹ค.
โ–ช
๊ฐ์ฒด๊ฐ€ ์™„์ „ํžˆ ์ƒ์„ฑ๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์ผ๊ด€์„ฑ์ด ๋ฌด๋„ˆ์ง„ ์ƒํƒœ์— ๋†“์ด๊ฒŒ ๋œ๋‹ค.
โ–ช
ํด๋ž˜์Šค๋ฅผ ๋ถˆ๋ณ€์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค.
โ–ช
์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ์–ป์œผ๋ ค๋ฉด ์ถ”๊ฐ€ ์ž‘์—…์„ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
โ—ฆ
๋นŒ๋” ํŒจํ„ด ์‚ฌ์šฉ
โ–ช
์ ์ธต์  ์ƒ์„ฑ์ž ํŒจํ„ด์˜ ์•ˆ์ „์„ฑ + ์ž๋ฐ” ๋นˆ์ฆˆ ํŒจํ„ด์˜ ๊ฐ€๋…์„ฑ
โ–ช
์“ฐ๊ธฐ ์‰ฝ๊ณ , ์ฝ๊ธฐ ์‰ฌ์šด ์ฝ”๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.
โ–ช
๋ช…๋ช…๋œ ์„ ํƒ์  ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ‰๋‚ด๋‚ธ ๊ฒƒ์ด๋‹ค. (ํŒŒ์ด์ฌ, ์Šค์นผ๋ผ)
๋นŒ๋” ํŒจํ„ด (Builder Pattern)
โ€ข
ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ๋งŒ๋“œ๋Š” ๋Œ€์‹ , ํ•„์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋งŒ์œผ๋กœ ์ƒ์„ฑ์ž(ํ˜น์€ ์ •์  ํŒฉํ„ฐ๋ฆฌ)๋ฅผ ํ˜ธ์ถœํ•ด ๋นŒ๋” ๊ฐ์ฒด๋ฅผ ์–ป๋Š”๋‹ค.
โ€ข
๋‚˜๋จธ์ง€ ์„ ํƒ ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์€ ์„ธํ„ฐ ๋ฉ”์„œ๋“œ๋กœ ์„ค์ •ํ•œ๋‹ค.
โ€ข
๋งˆ์ง€๋ง‰์œผ๋กœ, ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” build ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์–ป๋Š”๋‹ค.
public 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 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); } } private NutritionFacts(Builder builder) { servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; } public static void main(String[] args) { NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8) .calories(100) .sodium(35) .carbohydrate(27) .build(); } }
Java
๋ณต์‚ฌ

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

โ€ข
์‹ฑ๊ธ€ํ„ด์ด๋ž€?
โ—ฆ
์ธ์Šคํ„ด์Šค๋ฅผ ์˜ค์ง ํ•˜๋‚˜๋งŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค
โ—ฆ
ํด๋ž˜์Šค๋ฅผ ์‹ฑ๊ธ€ํ„ด์œผ๋กœ ๋งŒ๋“ค๋ฉด ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ๋‹ค.
โ€ข
์‹ฑ๊ธ€ํ„ด์„ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹
โ—ฆ
public static ๋ฉค๋ฒ„๊ฐ€ final ํ•„๋“œ์ธ ๋ฐฉ์‹
โ–ช
ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์‹ฑํดํ„ด์ž„์ด API์— ๋ช…๋ฐฑํžˆ ๋“œ๋Ÿฌ๋‚œ๋‹ค.
โ–ช
๊ฐ„๊ฒฐํ•˜๋‹ค.
public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public void leaveTheBuilding() { ... } }
Java
๋ณต์‚ฌ
โ—ฆ
์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ public static ๋ฉค๋ฒ„๋กœ๋กœ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ์‹
โ–ช
API๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๊ณ ๋„ ์‹ฑ๊ธ€ํ„ด์ด ์•„๋‹ˆ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
โ–ช
์›ํ•œ๋‹ค๋ฉด ์ •์  ํŒฉํ„ฐ๋ฆฌ๋ฅผ ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒฉํ„ฐ๋ฆฌ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
โ–ช
์ •์  ํŒฉํ„ฐ๋ฆฌ์˜ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ๊ณต๊ธ‰์ž๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
public class Elvis { private static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public static Elvis getInstance() { return INSTNACE; } public void leaveTheBuilding() { ... } }
Java
๋ณต์‚ฌ
โ—ฆ
์—ด๊ฑฐ ํƒ€์ž… ๋ฐฉ์‹์˜ ์‹ฑ๊ธ€ํ„ด ๋ฐฉ์‹ - ๋ฐ”๋žŒ์งํ•œ ๋ฐฉ์‹
โ–ช
๋งค์šฐ ๊ฐ„๊ฒฐํ•˜๊ณ , ์ถ”๊ฐ€ ๋…ธ๋ ฅ ์—†์ด ์ง๋ ฌํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.
โ–ช
์•„์ฃผ ๋ณต์žกํ•œ ์ง๋ ฌํ™” ์ƒํ™ฉ์ด๋‚˜ ๋ฆฌํ”Œ๋ ‰์…˜ ๊ณต๊ฒฉ์—์„œ๋„ ์ œ 2์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ๊ธฐ๋Š” ์ผ์„ ์™„๋ฒฝํžˆ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.
โ–ช
๋‹จ, ๋งŒ๋“ค๋ ค๋Š” ์‹ฑ๊ธ€ํ„ด์ด Enum ์™ธ์˜ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ด ๋ฐฉ๋ฒ•์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
public enum Elvis { INSTANCE; public void leaveTheBuilding() { ... } }
Java
๋ณต์‚ฌ

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

โ€ข
ํด๋ž˜์Šค๊ฐ€ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ž์›์— ์˜์กดํ•˜๊ณ , ๊ทธ ์ž์›์ด ํด๋ž˜์Šค ๋™์ž‘์— ์˜ํ–ฅ์„ ์ค€๋‹ค๋ฉด, ์ •์  ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค๋‚˜ ์‹ฑ๊ธ€ํ„ด ๋ฐฉ์‹์€ ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค.
์˜์กด ๊ฐ์ฒด ์ฃผ์ž…
โ€ข
์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์ƒ์„ฑ์ž์— ํ•„์š”ํ•œ ์ž์›์„ ๋„˜๊ฒจ์ฃผ๋Š” ๋ฐฉ์‹
โ€ข
ํด๋ž˜์Šค์˜ ์œ ์—ฐ์„ฑ, ์žฌ์‚ฌ์šฉ์„ฑ, ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ๊ฐœ์„ ํ•œ๋‹ค.
public class SpellChecker { private final Lexicon dictionary; public SpellChecker(Lexicon dictionary) { this.dictionary = Objects.requireNonNull(dictionary); } ... }
Java
๋ณต์‚ฌ

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

โ€ข
๋˜‘๊ฐ™์€ ๊ธฐ๋Šฅ์˜ ๊ฐ์ฒด๋ฅผ ๋งค๋ฒˆ ์ƒ์„ฑํ•˜๊ธฐ ๋ณด๋‹ค๋Š” ๊ฐ์ฒด ํ•˜๋‚˜๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ๋‚˜์„ ๋•Œ๊ฐ€ ๋งŽ๋‹ค.
โ—ฆ
์ƒ์„ฑ ๋น„์šฉ์ด ์•„์ฃผ ๋น„์‹ผ ๊ฐ์ฒด๊ฐ€ ๋ฐ˜๋ณตํ•ด์„œ ํ•„์š”ํ•˜๋‹ค๋ฉด, ์บ์‹ฑํ•˜์—ฌ ์žฌ์‚ฌ์šฉํ•˜๋ผ.
// ๊ฐ’๋น„์‹ผ ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•ด ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•œ๋‹ค. (32์ชฝ) public class RomanNumerals { // ์ฝ”๋“œ 6-1 ์„ฑ๋Šฅ์„ ํ›จ์”ฌ ๋” ๋Œ์–ด์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋‹ค! static boolean isRomanNumeralSlow(String s) { return s.matches("^(?=.)M*(C[MD]|D?C{0,3})" + "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$"); } // ์ฝ”๋“œ 6-2 ๊ฐ’๋น„์‹ผ ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•ด ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•œ๋‹ค. 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 isRomanNumeralFast(String s) { return ROMAN.matcher(s).matches(); } public static void main(String[] args) { int numSets = Integer.parseInt(args[0]); int numReps = Integer.parseInt(args[1]); boolean b = false; for (int i = 0; i < numSets; i++) { long start = System.nanoTime(); for (int j = 0; j < numReps; j++) { // ์„ฑ๋Šฅ ์ฐจ์ด๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด xxxSlow ๋ฉ”์„œ๋“œ๋ฅผ xxxFast ๋ฉ”์„œ๋“œ๋กœ ๋ฐ”๊ฟ” ์‹คํ–‰ํ•ด๋ณด์ž. b ^= isRomanNumeralSlow("MCMLXXVI"); } long end = System.nanoTime(); System.out.println(((end - start) / (1_000. * numReps)) + " ฮผs."); } // VM์ด ์ตœ์ ํ™”ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰๋Š” ์ฝ”๋“œ if (!b) System.out.println(); } }
Java
๋ณต์‚ฌ
โ€ข
์˜คํ† ๋ฐ•์‹ฑ์„ ์ฃผ์˜ํ•˜๋ผ!
โ—ฆ
๋ฐ•์‹ฑ๋œ ๊ธฐ๋ณธ ํƒ€์ž…๋ณด๋‹ค๋Š” ๊ธฐ๋ณธ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๊ณ , ์˜๋„์น˜ ์•Š์€ ์˜คํ†  ๋ฐ•์‹ฑ์ด ์ˆจ์–ด๋“ค์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•˜์ž.
// ์ฝ”๋“œ 6-3 ๋”์ฐ์ด ๋А๋ฆฌ๋‹ค! ๊ฐ์ฒด๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋Š” ์œ„์น˜๋ฅผ ์ฐพ์•˜๋Š”๊ฐ€? (34์ชฝ) public class Sum { private static long sum() { Long sum = 0L; for (long i = 0; i <= Integer.MAX_VALUE; i++) sum += i; return sum; } public static void main(String[] args) { int numSets = Integer.parseInt(args[0]); long x = 0; for (int i = 0; i < numSets; i++) { long start = System.nanoTime(); x += sum(); long end = System.nanoTime(); System.out.println((end - start) / 1_000_000. + " ms."); } // VM์ด ์ตœ์ ํ™”ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰๋Š” ์ฝ”๋“œ if (x == 42) System.out.println(); } }
Java
๋ณต์‚ฌ

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

โ€ข
์ž๊ธฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค๋ผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์— ์ฃผ์˜ํ•ด์•ผํ•œ๋‹ค.
โ—ฆ
๋‹ค ์“ด ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ ์ฐธ์กฐ ํ•ด์ œํ•ด๋ผ. (null ์ฒ˜๋ฆฌ ํ•˜๋Š” ์ผ์€ ์˜ˆ์™ธ์ ์ธ ๊ฒฝ์šฐ์—ฌ์•ผ ํ•œ๋‹ค.)
โ–ช
๋‹ค ์“ด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ๊ทธ ์ฐธ์กฐ๋ฅผ ๋‹ด์€ ๋ณ€์ˆ˜๋ฅผ ์œ ํšจ ๋ฒ”์œ„ ๋ฐ–์œผ๋กœ ๋ฐ€์–ด๋‚ด๋Š” ๊ฒƒ์ด๋‹ค.
// ์ฝ”๋“œ 7-1 ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์œ„์น˜๋Š” ์–ด๋””์ธ๊ฐ€? (36์ชฝ) 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); } // ์ฝ”๋“œ 7-2 ์ œ๋Œ€๋กœ ๊ตฌํ˜„ํ•œ pop ๋ฉ”์„œ๋“œ (37์ชฝ) public Object pop() { if (size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; // ๋‹ค ์“ด ์ฐธ์กฐ ํ•ด์ œ return result; } public static void main(String[] args) { Stack stack = new Stack(); for (String arg : args) stack.push(arg); while (true) System.err.println(stack.pop()); } }
Java
๋ณต์‚ฌ
โ€ข
์บ์‹œ ์—ญ์‹œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์ผ์œผํ‚ค๋Š” ์ฃผ๋ฒ”์ด๋‹ค.
โ€ข
๋ฆฌ์Šค๋„ˆ ํ˜น์€ ์ฝœ๋ฐฑ์„ ์‹ ๊ฒฝ์“ฐ์ž.

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

โ€ข
close ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ์ง์ ‘ ๋‹ซ์•„์ค˜์•ผ ํ•˜๋Š” ์ž์›์ด ์žˆ๋‹ค๋ฉด, ์ž์›์ด ํšŒ์ˆ˜๋จ์„ ๋ณด์žฅํ•˜๋Š” ์ˆ˜๋‹จ์œผ๋กœ try-with-resources๋ฅผ ์‚ฌ์šฉํ•˜๋ผ
โ—ฆ
close ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ์ง์ ‘ ๋‹ซ์•„์ค˜์•ผ ํ•˜๋Š” ์ž์›์˜ ์˜ˆ
โ–ช
InputStream, OutputStream, java.sql.Connection ๋“ฑ
โ€ข
try-finally ์‚ฌ์šฉ
โ—ฆ
๋ณต์ˆ˜์˜ ์ž์›์ผ ๊ฒฝ์šฐ์—๋Š” ์ฝ”๋“œ๊ฐ€ ์ง€์ €๋ถ„ํ•ด์ง„๋‹ค.
โ—ฆ
์—ฌ๋Ÿฌ ์˜ˆ์™ธ๊ฐ€ ํ•œ๊บผ๋ฒˆ์— ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ์ฒซ๋ฒˆ์งธ ์˜ˆ์™ธ์— ๋Œ€ํ•œ ๋ฌธ์ œ ์ง„๋‹จ์ด ์–ด๋ ค์›Œ์ง„๋‹ค.
// ์ฝ”๋“œ 9-1 try-finally - ๋” ์ด์ƒ ์ž์›์„ ํšŒ์ˆ˜ํ•˜๋Š” ์ตœ์„ ์˜ ๋ฐฉ์ฑ…์ด ์•„๋‹ˆ๋‹ค! (47์ชฝ) static String firstLineOfFile(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); // ์ฒซ ๋ฒˆ์งธ ์˜ˆ์™ธ ๋ฐœ์ƒ } finally { br.close(); // ๋‘ ๋ฒˆ์งธ ์˜ˆ์™ธ ๋ฐœ์ƒ } } // close()์— ๋Œ€ํ•œ ์˜ˆ์™ธ๊ฐ€ readLin()์— ๋Œ€ํ•œ ์˜ˆ์™ธ๋ฅผ ์ง‘์–ด์‚ผํ‚จ๋‹ค. // ์ฝ”๋“œ 9-2 ์ž์›์ด ๋‘˜ ์ด์ƒ์ด๋ฉด try-finally ๋ฐฉ์‹์€ ๋„ˆ๋ฌด ์ง€์ €๋ถ„ํ•˜๋‹ค! (47์ชฝ) 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(); } }
Java
๋ณต์‚ฌ
try-with-resources ์‚ฌ์šฉ
โ€ข
์ฝ”๋“œ๋Š” ๋” ์งง๊ณ  ๋ถ„๋ช…ํ•ด์ง„๋‹ค.
โ€ข
๋งŒ๋“ค์–ด์ง€๋Š” ์˜ˆ์™ธ์ •๋ณด๋„ ํ›จ์”ฌ ์œ ์šฉํ•˜๋‹ค.
โ—ฆ
์‹ค์ œ ๋ฌธ์ œ ์ง„๋‹จ์ด ํ•„์š”ํ•œ ์ฒซ๋ฒˆ์งธ ์˜ˆ์™ธ (readLine)๋งŒ ๊ธฐ๋ก๋˜๊ณ , close์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋Š” ์ˆจ๊ฒจ์ง„๋‹ค. (์Šคํƒ ์ถ”์  ๋‚ด์—ญ์— ์ˆจ๊ฒจ์กŒ๋‹ค๋Š” ๊ผฌ๋ฆฌํ‘œ๋ฅผ ๋‹ฌ๊ณ  ์ถœ๋ ฅ๋œ๋‹ค.)
// ์ฝ”๋“œ 9-3 try-with-resources - ์ž์›์„ ํšŒ์ˆ˜ํ•˜๋Š” ์ตœ์„ ์ฑ…! (48์ชฝ) static String firstLineOfFile(String path) throws IOException { try (BufferedReader br = new BufferedReader( new FileReader(path))) { return br.readLine(); } } // ์ฝ”๋“œ 9-4 ๋ณต์ˆ˜์˜ ์ž์›์„ ์ฒ˜๋ฆฌํ•˜๋Š” try-with-resources - ์งง๊ณ  ๋งคํ˜น์ ์ด๋‹ค! (49์ชฝ) 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); } }
Java
๋ณต์‚ฌ

๋ชจ๋“  ๊ฐ์ฒด์˜ ๊ณตํ†ต ๋ฉ”์„œ๋“œ

Object์˜ equals, hashCode, toString, clone, finalize ๊ทธ๋ฆฌ๊ณ  Comparable.compareTo

equals๋Š” ์ผ๋ฐ˜ ๊ทœ์•ฝ์„ ์ง€์ผœ ์žฌ์ •์˜ํ•˜๋ผ

โ€ข
์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ์žฌ์ •์˜ํ•˜์ง€ ๋ง์ž. ๊ทธ๋ƒฅ ๋‘๋ฉด ๊ทธ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋Š” ์˜ค์ง ์ž๊ธฐ์ž์‹ ๊ณผ๋งŒ ๊ฐ™๊ฒŒ ๋œ๋‹ค.
โ—ฆ
๊ฐ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ณธ์งˆ์ ์œผ๋กœ ๊ณ ์œ ํ•˜๋‹ค.
โ–ช
์˜ˆ) Thread
โ—ฆ
์ธ์Šคํ„ด์Šค์˜ โ€˜๋…ผ๋ฆฌ์  ๋™์น˜์„ฑ(logical equality)โ€™์„ ๊ฒ€์‚ฌํ•  ์ผ์ด ์—†๋‹ค.
โ—ฆ
์ƒ์œ„ ํด๋ž˜์Šค์—์„œ ์žฌ์ •์˜ํ•œ equals๊ฐ€ ํ•˜์œ„ ํด๋ž˜์Šค์—๋„ ๋”ฑ ๋“ค์–ด๋งž๋Š”๋‹ค.
โ—ฆ
ํด๋ž˜์Šค๊ฐ€ private์ด๊ฑฐ๋‚˜ package-private์ด๊ณ , equals ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ผ์ด ์—†๋‹ค.
@Override public boolean equals(Object o) { throw new AssertionError(); // ํ˜ธ์ถœ ๊ธˆ์ง€! }
Java
๋ณต์‚ฌ
โ€ข
equals๋ฅผ ์žฌ์ •์˜ํ•ด์•ผ ํ•  ๋•Œ
โ—ฆ
๊ฐ์ฒด ์‹๋ณ„์„ฑ์ด ์•„๋‹Œ ๋…ผ๋ฆฌ์  ๋™์น˜์„ฑ์„ ํ™•์ธํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ โ†’ ์ฃผ๋กœ ๊ฐ’ ํด๋ž˜์Šค
โ—ฆ
๊ฐ’์ด ๊ฐ™์€ ์ง€๋ฅผ ์•Œ๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ
โ€ข
Object ๋ช…์„ธ์— ์ ํžŒ equals ๋ฉ”์†Œ๋“œ ๊ทœ์•ฝ
โ—ฆ
equals ๋ฉ”์„œ๋“œ๋Š” ๋™์น˜๊ด€๊ณ„(equivalence relation)์„ ๊ตฌํ˜„ํ•˜๋ฉฐ, ๋‹ค์Œ์„ ๋งŒ์กฑํ•œ๋‹ค.
โ–ช
Obejct์—์„œ ๋งํ•˜๋Š” ๋™์น˜๊ด€๊ณ„๋ž€?
โ€ข
Object์—์„œ ๋งํ•˜๋Š” ๋™์น˜๊ด€๊ณ„๋Š” ์‰ฝ๊ฒŒ ๋งํ•ด, ์„œ๋กœ ๊ฐ™์€ ์›์†Œ๋“ค๋กœ ์ด๋ฃจ์–ด์ง„ ๋ถ€๋ถ„์ง‘ํ•ฉ์œผ๋กœ ๋‚˜๋ˆ„๋Š” ์—ฐ์‚ฐ์„ ๋งํ•˜๋ฉฐ, ์ด ๋ถ€๋ถ„์ง‘ํ•ฉ์„ ๋™์น˜ ํด๋ž˜์Šค๋ผ ํ•œ๋‹ค.
โ€ข
equals()๊ฐ€ ์“ธ๋ชจ ์žˆ์œผ๋ ค๋ฉด, ๋ชจ๋“  ์›์†Œ๊ฐ€ ๊ฐ™์€ ๋™์น˜๋ฅ˜์— ์†ํ•˜์—ฌ ์–ด๋–ค ์›์†Œ์™€๋„ ์„œ๋กœ ๊ตํ™˜ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
โ—ฆ
X = {a, b, c, a, b, c}
โ—ฆ
A = {a, a}
โ—ฆ
B = {b, b}
โ—ฆ
C = {c, c}
โ—ฆ
A, B, C๊ฐ€ ๋™์น˜ํด๋ž˜์Šค์ด๋‹ค.
โ—ฆ
๋ฐ˜์‚ฌ์„ฑ(reflexivity) : null์ด ์•„๋‹Œ ๋ชจ๋“  ์ฐธ์กฐ ๊ฐ’ x์— ๋Œ€ํ•ด, x.equals(x)๋Š” true๋‹ค.
โ–ช
๋ฐ˜์‚ฌ์„ฑ์€ ๋‹จ์ˆœํžˆ ๋งํ•ด ๊ฐ์ฒด๋Š” ์ž๊ธฐ ์ž์‹ ๊ณผ ๊ฐ™์•„์•ผ ํ•œ๋‹ค๋Š” ๋œป์ด๋‹ค.
โ€ข
์ด ์š”๊ฑด์„ ์–ด๊ธด ํด๋ž˜์Šค๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด, ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ปฌ๋ ‰์…˜์— ๋„ฃ๊ณ  contains()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ธ์Šคํ„ด์Šค๊ฐ€ ์—†๋‹ค๊ณ  ๋‹ตํ•  ๊ฒƒ์ด๋‹ค.
var x = new MyEquals(); var list = List.of(x); list.contains(x);//List์˜ contains๋Š” Object์˜ equals๋ฅผ ์‚ฌ์šฉ
Java
๋ณต์‚ฌ
โ—ฆ
๋Œ€์นญ์„ฑ(symmetry) : null์ด ์•„๋‹Œ ๋ชจ๋“  ์ฐธ์กฐ ๊ฐ’ x, y์— ๋Œ€ํ•ด, x.equals(y)๊ฐ€ true๋ฉด y.equals(x)๋„ true๋‹ค.
โ–ช
๋‘ ๊ฐ์ฒด๋Š” ์„œ๋กœ์— ๋Œ€ํ•œ ๋™์น˜ ์—ฌ๋ถ€์— ๋˜‘๊ฐ™์ด ๋‹ตํ•ด์•ผํ•œ๋‹ค.
โ–ช
equals ๊ทœ์•ฝ์„ ์–ด๊ธฐ๋ฉด ๊ทธ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์ด ์–ด๋–ป๊ฒŒ ๋ฐ˜์‘ํ•  ์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.
// ๋Œ€์นญ์„ฑ ์œ„๋ฐ˜ public final class CaseInsensitiveString{ private final String s; public CaseInsensitiveString(String s){ this.s = Obejcts.requireNonNull(s); } @Override public boolean equals(Object o){ if(o instanceof CaseInsensitiveString) return s.equalsIgnoreCase(((CaseInsensitiveString) o).s); if(o instanceof String) // ํ•œ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ์ž‘๋™ํ•œ๋‹ค. return s.equalsIgnoreCase((String) o); return false; // CaseInsensitiveString์˜ equals๋Š” ์ผ๋ฐ˜ String์„ ์•Œ๊ณ  ์žˆ๋‹ค. // cis.equals(s)๋Š” true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. // ํ•˜์ง€๋งŒ, String์˜ equals๋Š” CaseInsensitiveString์˜ ์กด์žฌ๋ฅผ ๋ชจ๋ฅธ๋‹ค. // ๋”ฐ๋ผ์„œ, s.equals(cis)๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. -> ๋Œ€์นญ์„ฑ ์œ„๋ฐ˜ } } CaseInsensitiveString cis = new CaseInsensitiveString("Polish"); String s = "polish"; cis.equals(s);// true s.equals(cis);// false // ๋Œ€์นญ์„ฑ์„ ๋งŒ์กฑํ•˜๋„๋ก ์ˆ˜์ • // String์— ๋Œ€ํ•œ instanceof ๋ถ€๋ถ„์„ ๋นผ๊ณ  ๊ตฌํ˜„ํ•œ๋‹ค. @Override public boolean equals(Object o){ return o instanceof CaseInsensitiveString && ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
Java
๋ณต์‚ฌ
โ—ฆ
์ถ”์ด์„ฑ(transitivity) : null์ด ์•„๋‹Œ ๋ชจ๋“  ์ฐธ์กฐ ๊ฐ’ x, y, z์— ๋Œ€ํ•ด, x.equals(y)๊ฐ€ true์ด๊ณ , y.equals(z)๋„ true๋ฉด, x.equals(z)๋„ true๋‹ค.
โ–ช
์ƒ์œ„ ํด๋ž˜์Šค์— ์—†๋Š” ์ƒˆ๋กœ์šด ํ•„๋“œ๋ฅผ ํ•˜์œ„ ํด๋ž˜์Šค์— ์ถ”๊ฐ€ํ•˜๋Š” ์ƒํ™ฉ์ผ ๊ฒฝ์šฐ
โ€ข
๋Œ€์นญ์„ฑ ์œ„๋ฐฐ ๋ฌธ์ œ
// ColorPoint.java ์˜ equals @Override public boolean equals(Object o){ if(!(o instanceof ColorPoint)) return false; return super.equals(o) && ((ColorPoint) o).color == color; } public static void main(){ Point p = new Point(1,2); ColorPoint cp = new ColorPoint(1,2, Color.RED); p.equals(cp);// true (Point์˜ equals๋กœ ๊ณ„์‚ฐ) cp.equals(p);// false (ColorPoint์˜ equals๋กœ ๊ณ„์‚ฐ: color ํ•„๋“œ ๋ถ€๋ถ„์—์„œ false) }
Java
๋ณต์‚ฌ
โ€ข
์ถ”์ด์„ฑ ์œ„๋ฐฐ ๋ฌธ์ œ
//ColorPoint.java์˜ equals @Override public boolean equals(Obejct o){ if(!(o instanceof Point)) return false; if(!(o instanceof ColorPoint)) return o.equals(this); return super.equals(o) && ((ColorPoint) o).color == color; } public static void main(){ ColorPoint p1 = new ColorPoint(1,2, Color.RED); Point p2 = new Point(1,2); ColorPoint p3 = new ColorPoint(1,2, Color.BLUE); p1.equals(p2);// true (ColorPoint์˜ equals ๋น„๊ต //2๋ฒˆ์งธ if๋ฌธ์—์„œ Point์˜ equals๋กœ ๋ณ€ํ™˜) p2.equals(p3);// true (Point์˜ equals ๋น„๊ต // x,y ๊ฐ™์œผ๋‹ˆ true) p1.equals(p3);// false (ColorPoint์˜ equals ๋น„๊ต) }
Java
๋ณต์‚ฌ
โ€ข
๋ฌดํ•œ ์žฌ๊ท€์— ๋น ์งˆ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์  ๋ฐœ์ƒ
//SmellPoint.java์˜ equals @Override public boolean equals(Obejct o){ if(!(o instanceof Point)) return false; if(!(o instanceof SmellPoint)) return o.equals(this); return super.equals(o) && ((SmellPoint) o).color == color; } public static void main(){ ColorPoint p1 = new ColorPoint(1,2, Color.RED); SmellPoint p2 = new SmellPoint(1,2); p1.equals(p2); // ์ฒ˜์Œ์— ColorPoint์˜ equals๋กœ ๋น„๊ต : 2๋ฒˆ์งธ if๋ฌธ ๋•Œ๋ฌธ์— SmellPoint์˜ equals๋กœ ๋น„๊ต// ์ดํ›„ SmellPoint์˜ equals๋กœ ๋น„๊ต : 2๋ฒˆ์งธ if๋ฌธ ๋•Œ๋ฌธ์— ColorPoint์˜ equals๋กœ ๋น„๊ต// ๋ฌดํ•œ ์žฌ๊ท€์˜ ์ƒํƒœ! }
Java
๋ณต์‚ฌ
โ€ข
๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜์›์น™ ์œ„๋ฐฐย 
@Override public boolean equals(Object o){ if(o == null || o.getClass() != getClass()) return false; Point p = (Point) o; return p.x == x && p.y == y; }
Java
๋ณต์‚ฌ
โ—ฆ
Point์˜ ํ•˜์œ„ํด๋ž˜์Šค๋Š” ์ •์˜์ƒ ์—ฌ์ „ํžˆ Point์ด๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋””์„œ๋“  Point๋กœ ํ™œ์šฉ๋˜์–ด์•ผํ•œ๋‹ค.
โ—ฆ
๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜์›์น™ (Liskov substitution principle)ย 
โ–ช
์–ด๋–ค ํƒ€์ž…์— ์žˆ์–ด ์ค‘์š”ํ•œ ์†์„ฑ์ด๋ผ๋ฉด ๊ทธ ํ•˜์œ„ ํƒ€์ž…์—์„œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ค‘์š”ํ•˜๋‹ค. ๋”ฐ๋ผ์„œ ๊ทธ ํƒ€์ž…์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๊ฐ€ ํ•˜์œ„ ํƒ€์ž…์—์„œ๋„ ๋˜‘๊ฐ™์ด ์ž˜ ์ž‘๋™ํ•ด์•ผํ•œ๋‹ค.
โ–ช
ํ•ด๊ฒฐ๋ฐฉ๋ฒ•
โ€ข
์ƒ์†๋Œ€์‹  ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•˜๋ผ
public class ColorPoint{ private final Point point; private final Color color; public Point asPoint(){//view ๋ฉ”์„œ๋“œ ํŒจํ„ด return point } @Override public boolean equals(Object o){ if(!(o instanceof ColorPoint)){ return false; } ColorPoint cp = (ColorPoin) o; return cp.point.equals(point) && cp.color.equals(color); } }
Java
๋ณต์‚ฌ
โ—ฆ
ColorPoint - ColorPoint
โ–ช
ColorPoint์˜ equals๋ฅผ ์ด์šฉํ•˜์—ฌ color ๊ฐ’๊นŒ์ง€ ๋ชจ๋‘ ๋น„๊ต
โ—ฆ
ColorPoint - Point
โ–ช
ColorPoint๋ฅผ asPoint() ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•ด Point๋กœ ๋ฐ”๊พธ์–ด์„œ, Point์˜ equlas๋ฅผ ์ด์šฉํ•ด x,y๋งŒ ๋น„๊ต
โ—ฆ
Point - Point
โ–ช
Point์˜ equals๋ฅผ ์ด์šฉํ•˜์—ฌ x,y ๊ฐ’ ๋ชจ๋‘ ๋น„๊ต
โ€ข
์ถ”์ƒํด๋ž˜์Šค์˜ ํ•˜์œ„ํด๋ž˜์Šค ์‚ฌ์šฉ
โ—ฆ
์ถ”์ƒํด๋ž˜์Šค์˜ ํ•˜์œ„ํด๋ž˜์Šค์—์„œ๋Š” equals ๊ทœ์•ฝ์„ ์ง€ํ‚ค๋ฉด์„œ๋„ ๊ฐ’์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
์ƒ์œ„ ํด๋ž˜์Šค๋ฅผ ์ง์ ‘ ์ธ์Šคํ„ด์Šค๋กœ ๋งŒ๋“œ๋Š”๊ฒŒ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•˜์œ„ํด๋ž˜์Šค๋ผ๋ฆฌ์˜ ๋น„๊ต๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.
โ—ฆ
๊ตฌ์ฒด ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•ด ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ถ”๊ฐ€ํ•˜๋ฉด์„œ equals ๊ทœ์•ฝ์„ ๋งŒ์กฑ์‹œํ‚ฌ ๋ฐฉ๋ฒ•์€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค.
โ—ฆ
์ผ๊ด€์„ฑ(consistency) : null์ด ์•„๋‹Œ ๋ชจ๋“  ์ฐธ์กฐ ๊ฐ’ x, y์— ๋Œ€ํ•ด, x.equals(y)๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ ํ˜ธ์ถœํ•˜๋ฉด ํ•ญ์ƒ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ ํ•ญ์ƒ false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
โ–ช
๋‘ ๊ฐ์ฒด๊ฐ€ ๊ฐ™๋‹ค๋ฉด (์–ด๋А ํ•˜๋‚˜ ํ˜น์€ ๋‘ ๊ฐ์ฒด ๋ชจ๋‘๊ฐ€ ์ˆ˜์ •๋˜์ง€ ์•Š๋Š”ํ•œ) ์•ž์œผ๋กœ๋„ ์˜์›ํžˆ ๊ฐ™์•„์•ผํ•œ๋‹ค.
โ–ช
๊ฐ€๋ณ€๊ฐ์ฒด
โ€ข
๋น„๊ต ์‹œ์ ์— ๋”ฐ๋ผ ์„œ๋กœ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค.
โ–ช
๋ถˆ๋ณ€๊ฐ์ฒด
โ€ข
ํ•œ ๋ฒˆ ๋‹ค๋ฅด๋ฉด ๋๊นŒ์ง€ ๋‹ฌ๋ผ์•ผํ•œ๋‹ค.
โ–ช
equals๋Š” ํ•ญ์‹œ ๋ฉ”๋ชจ๋ฆฌ์— ์กด์žฌํ•˜๋Š” ๊ฐ์ฒด๋งŒ์„ ์‚ฌ์šฉํ•œ ๊ฒฐ์ •์ (deterministic) ๊ณ„์‚ฐ๋งŒ ์ˆ˜ํ–‰ํ•ด์•ผํ•œ๋‹ค.
โ–ช
ํด๋ž˜์Šค๊ฐ€ ๋ถˆ๋ณ€์ด๋“  ๊ฐ€๋ณ€์ด๋“ , equals์˜ ํŒ๋‹จ์— ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ์ž์›์ด ๋ผ์–ด๋“ค๋ฉด ์•ˆ๋œ๋‹ค.
โ—ฆ
null-์•„๋‹˜ : null์ด ์•„๋‹Œ ๋ชจ๋“  ์ฐธ์กฐ ๊ฐ’ x์— ๋Œ€ํ•ด, x.equals(null)์€ false๋‹ค.
โ–ช
๋ช…์‹œ์  null ๊ฒ€์‚ฌ - ํ•„์š” ์—†๋‹ค!
@Override public boolean equals(Object o){ if( o == null){ return false; } }
Java
๋ณต์‚ฌ
โ–ช
๋ฌต์‹œ์  null ๊ฒ€์‚ฌ - ์ด ์ชฝ์ด ๋‚ซ๋‹ค!
@Override public boolean equals(Obejct o){ if(!(o instanceof MyType)) // instanceof ์ž์ฒด๊ฐ€ ํƒ€์ž…๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ null์ด๋ฉด false ๋ฐ˜ํ™˜ํ•จ. return false; MyType mt = (MyType) o; }
Java
๋ณต์‚ฌ
โ€ข
์–‘์งˆ์˜ equals ๋ฉ”์†Œ๋“œ ๊ตฌํ˜„ ๋ฐฉ๋ฒ• (๋‹จ๊ณ„๋ณ„ ์ •๋ฆฌ)
1.
== ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด ์ž…๋ ฅ์ด ์ž๊ธฐ ์ž์‹ ์˜ ์ฐธ์กฐ์ธ์ง€ ํ™•์ธํ•œ๋‹ค.
2.
instanceof ์—ฐ์‚ฐ์ž๋กœ ์ž…๋ ฅ์ด ์˜ฌ๋ฐ”๋ฅธ ํƒ€์ž…์ธ์ง€ ํ™•์ธํ•œ๋‹ค.
3.
์ž…๋ ฅ์„ ์˜ฌ๋ฐ”๋ฅธ ํƒ€์ž…์œผ๋กœ ํ˜•๋ณ€ํ™˜ํ•œ๋‹ค.
4.
์ž…๋ ฅ ๊ฐ์ฒด์™€ ์ž๊ธฐ ์ž์‹ ์˜ ๋Œ€์‘๋˜๋Š” โ€˜ํ•ต์‹ฌโ€™ํ•„๋“œ๋“ค์ด ๋ชจ๋‘ ์ผ์น˜ํ•˜๋Š”์ง€ ํ•˜๋‚˜์”ฉ ๊ฒ€์‚ฌํ•œ๋‹ค.
โ€ข
float์™€ double์„ ์ œ์™ธํ•œ ๊ธฐ๋ณธ ํƒ€์ž… ํ•„๋“œ๋Š” ==์—ฐ์‚ฐ์ž๋กœ ๋น„๊ตํ•œ๋‹ค.
โ€ข
์ฐธ์กฐ ํƒ€์ž… ํ•„๋“œ๋Š” ๊ฐ๊ฐ์˜ equals ๋ฉ”์†Œ๋“œ๋กœ, float์™€ double ํ•„๋“œ๋Š” ๊ฐ๊ฐ ์ •์  ๋ฉ”์†Œ๋“œ์ธ Float.compare(float, float)์™€ Double.compare(double, double)๋กœ ๋น„๊ตํ•œ๋‹ค .
โ€ข
๋ฐฐ์—ด ํ•„๋“œ๋Š” ์›์†Œ ๊ฐ๊ฐ์„ ์•ž์„œ์˜ ์ง€์นจ๋Œ€๋กœ ๋น„๊ตํ•œ๋‹ค. ๋ฐฐ์—ด์˜ ๋ชจ๋“  ์›์†Œ๊ฐ€ ํ•ต์‹ฌ ํ•„๋“œ๋ผ๋ฉด Arrays.equals๋ฉ”์†Œ๋“œ๋“ค ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜์ž.
โ€ข
null๋„ ์ •์ƒ ๊ฐ’์œผ๋กœ ์ทจ๊ธ‰ํ•˜๋Š” ์ฐธ์กฐ ํƒ€์ž… ํ•„๋“œ๋ผ๋ฉด, ์ •์  ๋ฉ”์†Œ๋“œ์ธ Objects.equals(Object, Object)๋กœ ๋น„๊ตํ•ด NullPointerException ๋ฐœ์ƒ์„ ์˜ˆ๋ฐฉํ•˜์ž.
โ€ข
๋น„๊ตํ•˜๊ธฐ๊ฐ€ ์•„์ฃผ ๋ณต์žกํ•œ ํ•„๋“œ๋ฅผ ๊ฐ€์ง„ ํด๋ž˜์Šค์ธ ๊ฒฝ์šฐ, ๊ทธ ํ•„๋“œ์˜ ํ‘œ์ค€ํ˜•(canonical form)์„ ์ €์žฅํ•ด๋‘” ํ›„ ํ‘œ์ค€ํ˜•๋ผ๋ฆฌ ๋น„๊ตํ•˜๋ฉด ๊ฒฝ์ œ์ ์ด๋‹ค. โ†’ ํŠนํžˆ ๋ถˆ๋ณ€ ํด๋ž˜์Šค์— ์ œ๊ฒฉ์ด๋‹ค.
โ€ข
ํ•„๋“œ ๋น„๊ต ์„ฑ๋Šฅ์€ equals ์„ฑ๋Šฅ์„ ์ขŒ์šฐํ•œ๋‹ค.
โ—ฆ
๋‹ค๋ฅผ ๊ฐ€๋Šฅ์„ฑ์ด ๋” ํฌ๊ฑฐ๋‚˜, ๋น„๊ตํ•˜๋Š” ๋น„์šฉ์ด ์‹ผ ํ•„๋“œ๋ฅผ ๋จผ์ € ๋น„๊ต
โ—ฆ
ํŒŒ์ƒํ•„๋“œ๊ฐ€ ๊ฐ์ฒด ์ „์ฒด์˜ ์ƒํƒœ๋ฅผ ๋Œ€ํ‘œํ•˜๋Š” ์ƒํ™ฉ์ผ ๊ฒฝ์šฐ, ํŒŒ์ƒ ํ•„๋“œ๋ฅผ ๋น„๊ตํ•˜๋Š” ์ชฝ์ด ๋” ๋น ๋ฅผ ์ˆ˜ ์žˆ๋‹ค.
โ€ข
equals๋ฅผ ๋‹ค ๊ตฌํ˜„ํ–ˆ๋‹ค๋ฉด, ์„ธ ๊ฐ€์ง€๋งŒ ์ž๋ฌธํ•ด๋ณด์ž.
โ—ฆ
๋Œ€์นญ์ ์ธ๊ฐ€?
โ—ฆ
์ถ”์ด์„ฑ์ด ์žˆ๋Š”๊ฐ€?
โ—ฆ
์ผ๊ด€์ ์ธ๊ฐ€?
// ์ฝ”๋“œ 10-6 ์ „ํ˜•์ ์ธ equals ๋ฉ”์„œ๋“œ์˜ ์˜ˆ (64์ชฝ) public final class PhoneNumber { private final short areaCode, prefix, lineNum; public PhoneNumber(int areaCode, int prefix, int lineNum) { this.areaCode = rangeCheck(areaCode, 999, "์ง€์—ญ์ฝ”๋“œ"); this.prefix = rangeCheck(prefix, 999, "ํ”„๋ฆฌํ”ฝ์Šค"); this.lineNum = rangeCheck(lineNum, 9999, "๊ฐ€์ž…์ž ๋ฒˆํ˜ธ"); } private static short rangeCheck(int val, int max, String arg) { if (val < 0 || val > max) throw new IllegalArgumentException(arg + ": " + val); return (short) val; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof PhoneNumber)) return false; PhoneNumber pn = (PhoneNumber)o; return pn.lineNum == lineNum && pn.prefix == prefix && pn.areaCode == areaCode; } // ๋‚˜๋จธ์ง€ ์ฝ”๋“œ๋Š” ์ƒ๋žต - hashCode ๋ฉ”์„œ๋“œ๋Š” ๊ผญ ํ•„์š”ํ•˜๋‹ค(์•„์ดํ…œ 11)! }
Java
๋ณต์‚ฌ
โ€ข
equals ๊ตฌํ˜„ ์‹œ ์ฃผ์˜์‚ฌํ•ญ
โ—ฆ
equals๋ฅผ ์žฌ์ •์˜ ํ•  ๋• hashCode๋„ ๋ฐ˜๋“œ์‹œ ์žฌ์ •์˜ํ•˜์ž.
โ—ฆ
๋„ˆ๋ฌด ๋ณต์žกํ•˜๊ฒŒ ํ•ด๊ฒฐํ•˜๋ ค ๋“ค์ง€ ๋ง์ž.
โ–ช
ํ•„๋“œ๋“ค์˜ ๋™์น˜์„ฑ๋งŒ ๊ฒ€์‚ฌํ•ด๋„ equals ๊ทœ์•ฝ์„ ์–ด๋ ต์ง€ ์•Š๊ฒŒ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
Object ์™ธ์˜ ํƒ€์ž…์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š” equals ๋ฉ”์†Œ๋“œ๋Š” ์„ ์–ธํ•˜์ง€ ๋ง์ž.

equals๋ฅผ ์žฌ์ •์˜ํ•˜๋ ค๊ฑฐ๋“  hashCode๋„ ์žฌ์ •์˜ํ•˜๋ผ

equals๋ฅผ ์žฌ์ •์˜ํ•œ ํด๋ž˜์Šค ๋ชจ๋‘์—์„œ hashCode๋„ ์žฌ์ •์˜ํ•ด์•ผํ•œ๋‹ค.
โ€ข
๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด hashCode ์ผ๋ฐ˜ ๊ทœ์•ฝ์„ ์–ด๊ธฐ๊ฒŒ ๋˜์–ด ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ HashMap์ด๋‚˜ HashSet ๊ฐ™์€ ์ปฌ๋ ‰์…˜์˜ ์›์†Œ๋กœ ์‚ฌ์šฉํ•  ๋•Œ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ๊ฒƒ์ด๋‹ค.
โ€ข
hashCode์—†์ด๋Š” ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค!
โ€ข
Object ๋ช…์„ธ์˜ 3๊ฐ€์ง€ ๊ทœ์•ฝ
โ—ฆ
equals()์— ์‚ฌ์šฉ๋˜๋Š” ์ •๋ณด๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ๊ทธ ๊ฐ์ฒด์˜ hashCode ๋ฉ”์†Œ๋“œ๋Š” ๋ช‡ ๋ฒˆ์„ ํ˜ธ์ถœํ•ด๋„ ์ผ๊ด€๋˜๊ฒŒ ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค. (๋‹จ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋‹ค์‹œ ์‹คํ–‰ํ•œ๋‹ค๋ฉด ์ด ๊ฐ’์ด ๋‹ฌ๋ผ์ ธ๋„ ์ƒ๊ด€์—†๋‹ค.)
โ–ช
hashCode ์žฌ์ •์˜๋ฅผ ์ž˜๋ชปํ–ˆ์„ ๋•Œ, ํฌ๊ฒŒ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ์กฐํ•ญ
โ–ช
๋…ผ๋ฆฌ์ ์œผ๋กœ ๊ฐ™์€ ๊ฐ์ฒด๋Š” ๊ฐ™์€ ํ•ด์‹œ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค!
โ—ฆ
equals(object)๊ฐ€ ๋‘ ๊ฐ์ฒด๋ฅผ ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จํ–ˆ๋‹ค๋ฉด, ๋‘ ๊ฐ์ฒด์˜ hashCode๋Š” ๋˜‘๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์•ผํ•œ๋‹ค.
โ—ฆ
equals(object)๊ฐ€ ๋‘ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฅด๋‹ค๊ณ  ํŒ๋‹จํ–ˆ๋‹ค๋ฉด, ๋‘ ๊ฐ์ฒด์˜ hashCode๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ํ•„์š”๋Š” ์—†๋‹ค. ๋‹จ, ๋‹ค๋ฅธ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ๋Š” ๋‹ค๋ฅธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ด์‹œํ…Œ์ด๋ธ”์˜ ์„ฑ๋Šฅ์ด ์ข‹์•„์ง„๋‹ค.
โ€ข
์ข‹์€ HashCode ์ž‘์„ฑ ๋ฐฉ๋ฒ•
1.
int ๋ณ€์ˆ˜ result๋ฅผ ์„ ์–ธํ•œ ํ›„, ๊ฐ’ c๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค. ์ด ๋•Œ, c๋Š” ํ•ด๋‹น ๊ฐ์ฒด์˜ ์ฒซ๋ฒˆ์งธ ํ•ต์‹ฌ ํ•„๋“œ๋ฅผ ๋‹จ๊ณ„ 2.a ๋ฐฉ์‹์œผ๋กœ ๊ณ„์‚ฐํ•œ ํ•ด์‹œ์ฝ”๋“œ์ด๋‹ค.
2.
ํ•ด๋‹น ๊ฐ์ฒด์˜ ๋‚˜๋จธ์ง€ ํ•ต์‹ฌํ•„๋“œ f ๊ฐ๊ฐ์— ๋Œ€ํ•ด ๋‹ค์Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
a.
ํ•ด๋‹น ํ•„๋“œ์˜ ํ•ด์‹œ์ฝ”๋“œ c๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค.
โ€ข
๊ธฐ๋ณธ ํƒ€์ž… ํ•„๋“œ๋ผ๋ฉด, Type.hashCode(f)๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ Type์€ ํ•ด๋‹น ๊ธฐ๋ณธ ํƒ€์ž…์˜ ๋ฐ•์‹ฑ ํด๋ž˜์Šค๋‹ค.
โ€ข
์ฐธ์กฐ ํƒ€์ž… ํ•„๋“œ๋ฉด์„œ ์ด ํด๋ž˜์Šค์˜ equals ๋ฉ”์†Œ๋“œ๊ฐ€ ์ด ํ•„๋“œ์˜ equals๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•ด ๋น„๊ตํ•œ๋‹ค๋ฉด, ์ด ํ•„๋“œ์˜ hashCode๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•œ๋‹ค. ๊ณ„์‚ฐ์ด ๋ณต์žกํ•ด์งˆ ๊ฒƒ ๊ฐ™์œผ๋ฉด, ์ด ํ•„๋“œ์˜ ํ‘œ์ค€ํ˜•(canonical representation)์„ ๋งŒ๋“ค์–ด ๊ทธ ํ‘œ์ค€ํ˜•์˜ hashCode๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. ํ•„๋“œ์˜ ๊ฐ’์ด null์ด๋ฉด 0์„ ์‚ฌ์šฉํ•œ๋‹ค.
โ€ข
ํ•„๋“œ๊ฐ€ ๋ฐฐ์—ด์ด๋ผ๋ฉด, ํ•ต์‹ฌ ์›์†Œ ๊ฐ๊ฐ์„ ๋ณ„๋„ ํ•„๋“œ์ฒ˜๋Ÿผ ๋‹ค๋ฃฌ๋‹ค. ์ด์ƒ์˜ ๊ทœ์น™์„ ์žฌ๊ท€์ ์œผ๋กœ ์ ์šฉํ•ด ๊ฐ ํ•ต์‹ฌ ์›์†Œ์˜ ํ•ด์‹œ์ฝ”๋“œ๋ฅผ ๊ณ„์‚ฐํ•œ ๋‹ค์Œ, ๋‹จ๊ณ„ 2.b๋ฐฉ์‹์œผ๋กœ ๊ฐฑ์‹ ํ•œ๋‹ค. ๋ฐฐ์—ด์— ํ•ต์‹ฌ ์›์ˆ˜๊ฐ€ ํ•˜๋‚˜๋„ ์—†๋‹ค๋ฉด ๋‹จ์ˆœํžˆ ์ƒ์ˆ˜(0์„ ์ถ”์ฒœํ•œ๋‹ค.)๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๋ชจ๋“  ์›์†Œ๊ฐ€ ํ•ต์‹ฌ ์›์†Œ๋ผ๋ฉด Arrays.hashCode๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
b.
๋‹จ๊ณ„ 2.a์—์„œ ๊ณ„์‚ฐํ•œ ํ•ด์‹œ์ฝ”๋“œ c๋กœ result๋ฅผ ๊ฐฑ์‹ ํ•œ๋‹ค. ์ฝ”๋“œ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
โ€ข
result = 31 * result + c;
3.
result๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
// ์ฝ”๋“œ 11-2 ์ „ํ˜•์ ์ธ hashCode ๋ฉ”์†Œ๋“œ (70์ชฝ) @Override public int hashCode() { int result = Short.hashCode(areaCode); result = 31 * result + Short.hashCode(prefix); result = 31 * result + Short.hashCode(lineNum); return result; } // ์ฝ”๋“œ 11-3 ํ•œ ์ค„์งœ๋ฆฌ hashCode ๋ฉ”์„œ๋“œ - ์„ฑ๋Šฅ์ด ์‚ด์ง ์•„์‰ฝ๋‹ค. (71์ชฝ) @Override public int hashCode() { return Objects.hash(lineNum, prefix, areaCode); } // ํ•ด์‹œ์ฝ”๋“œ๋ฅผ ์ง€์—ฐ ์ดˆ๊ธฐํ™”ํ•˜๋Š” hashCode ๋ฉ”์„œ๋“œ - ์Šค๋ ˆ๋“œ ์•ˆ์ •์„ฑ๊นŒ์ง€ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค. (71์ชฝ) private int hashCode; // ์ž๋™์œผ๋กœ 0์œผ๋กœ ์ดˆ๊ธฐํ™”๋œ๋‹ค. @Override public int hashCode() { int result = hashCode; if (result == 0) { result = Short.hashCode(areaCode); result = 31 * result + Short.hashCode(prefix); result = 31 * result + Short.hashCode(lineNum); hashCode = result; } return result; }
Java
๋ณต์‚ฌ
โ€ข
hashCode ์ž‘์„ฑ ์‹œ ์ฃผ์˜์‚ฌํ•ญ
โ—ฆ
์„ฑ๋Šฅ์„ ๋†’์ธ๋‹ต์‹œ๊ณ  ํ•ด์‹œ์ฝ”๋“œ๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ ํ•ต์‹ฌ ํ•„๋“œ๋ฅผ ์ƒ๋žตํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.
โ—ฆ
hashCode๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์˜ ์ƒ์„ฑ๊ทœ์น™์„ API ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž์„ธํžˆ ๊ณตํ‘œํ•˜์ง€ ๋ง์ž. ๊ทธ๋ž˜์•ผ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด ๊ฐ’์— ์˜์ง€ํ•˜์ง€ ์•Š๊ฒŒ ๋˜๊ณ , ์ถ”ํ›„์— ๊ณ„์‚ฐ ๋ฐฉ์‹์„ ๋ฐ”๊ฟ€ ์ˆ˜๋„ ์žˆ๋‹ค.

Comparable์„ ๊ตฌํ˜„ํ•  ์ง€ ๊ณ ๋ คํ•˜๋ผ

Comparable.compareTo
โ€ข
Comparable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด, ๋‹จ์ˆœ ๋™์น˜์„ฑ ๋น„๊ต์™€ ๋”๋ถˆ์–ด ์ˆœ์„œ๊นŒ์ง€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ œ๋„ค๋ฆญํ•˜๋‹ค.
โ—ฆ
Arrays.sort(a);์™€ ๊ฐ™์ด ์†์‰ฝ๊ฒŒ ์ •๋ ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
๊ฒ€์ƒ‰, ๊ทน๋‹จ๊ฐ’ ๊ณ„์‚ฐ, ์ž๋™ ์ •๋ ฌ๋˜๋Š” ์ปฌ๋ ‰์…˜ ๊ด€๋ฆฌ ๋˜ํ•œ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.
โ€ข
์‚ฌ์‹ค์ƒ ์ž๋ฐ” ํ”Œ๋žซํผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ชจ๋“  ๊ฐ’ ํด๋ž˜์Šค์™€ ์—ด๊ฑฐํƒ€์ž…์ด Comparble์„ ๊ตฌํ˜„ํ–ˆ๋‹ค.
โ€ข
์•ŒํŒŒ๋ฒณ, ์ˆซ์ž, ์—ฐ๋Œ€์™€ ๊ฐ™์ด ์ˆœ์„œ๊ฐ€ ๋ช…ํ™•ํ•œ ๊ฐ’ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ Comparable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์ž.
public interface Comparable<T> { int compareTo(T t); }
Java
๋ณต์‚ฌ
โ€ข
compareTo ๋ฉ”์†Œ๋“œ์˜ ์ผ๋ฐ˜ ๊ทœ์•ฝ
โ—ฆ
์ด ๊ฐ์ฒด์™€ ์ฃผ์–ด์ง„ ๊ฐ์ฒด์˜ ์ˆœ์„œ๋ฅผ ๋น„๊ตํ•œ๋‹ค. ์ด ๊ฐ์ฒด๊ฐ€ ์ฃผ์–ด์ง„ ๊ฐ์ฒด๋ณด๋‹ค ์ž‘์œผ๋ฉด ์Œ์˜ ์ •์ˆ˜๋ฅผ, ๊ฐ™์œผ๋ฉด 0ใ…‡์„, ํฌ๋ฉด ์–‘์˜ ์ •์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด ๊ฐ์ฒด์™€ ๋น„๊ตํ•  ์ˆ˜ ์—†๋Š” ํƒ€์ž…์˜ ๊ฐ์ฒด๊ฐ€ ์ฃผ์–ด์ง€๋ฉด ClassCastException์„ ๋˜์ง„๋‹ค.
โ–ช
Comparable์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋Š” ๋ชจ๋“  x, y์— ๋Œ€ํ•ด sgn(x.compareTo(y)) == -sgn(y.compareTo(x))์—ฌ์•ผ ํ•œ๋‹ค.
โ–ช
Comparable์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋Š” ์ถ”์ด์„ฑ์„ ๋ณด์žฅํ•ด์•ผ ํ•œ๋‹ค. ์ฆ‰, (x.compareTo(y) > 0 && y.compareTo(z) > 0)์ด๋ฉด x.compareTo(z) > 0์ด๋‹ค.
โ–ช
Comparable์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋Š” ๋ชจ๋“  z์— ๋Œ€ํ•ด x.compareTo(y) == 0 ์ด๋ฉด sgn(x.compareTo(z)) == sgn(y.compareTo(z))๋‹ค.
โ–ช
์ด๋ฒˆ ๊ถŒ๊ณ ๊ฐ€ ํ•„์ˆ˜๋Š” ์•„๋‹ˆ์ง€๋งŒ ๊ผญ ์ง€ํ‚ค๋Š”๊ฒŒ ์ข‹๋‹ค. (x.compareTo(y) == 0) == (x.equals(y))์—ฌ์•ผ ํ•œ๋‹ค. Comparable์„ ๊ตฌํ˜„ํ•˜๊ณ  ์ด ๊ถŒ๊ณ ๋ฅผ ์ง€ํ‚ค์ง€ ์•Š๋Š” ๋ชจ๋“  ํด๋ž˜์Šค๋Š” ๊ทธ ์‚ฌ์‹ค์„ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค. ์˜ˆ) ์ฃผ์˜ : ์ด ํด๋ž˜์Šค์˜ ์ˆœ์„œ๋Š” equals ๋ฉ”์†Œ๋“œ์™€ ์ผ๊ด€๋˜์ง€ ์•Š๋‹ค.
โ€ข
compareTo ๋ฉ”์†Œ๋“œ ์ž‘์„ฑ ์š”๋ น
โ—ฆ
Comparable์€ ํƒ€์ž…์„ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š” ์ œ๋„ค๋ฆญ ์ธํ„ฐํŽ˜์ด์Šค์ด๋ฏ€๋กœ compareTo ๋ฉ”์†Œ๋“œ์˜ ์ธ์ˆ˜ ํƒ€์ž…์€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ •ํ•ด์ง„๋‹ค. โ†’ ์ž…๋ ฅ ์ธ์ˆ˜์˜ ํƒ€์ž…์„ ํ™•์ธํ•˜๊ฑฐ๋‚˜, ํ˜•๋ณ€ํ™˜ํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ, ์ธ์ˆ˜ ํƒ€์ž…์ด ์ž˜๋ชป๋˜์—ˆ๋‹ค๋ฉด ์ปดํŒŒ์ผ ์ž์ฒด๊ฐ€ ๋˜์ง€ ์•Š๋Š”๋‹ค.
โ—ฆ
compareTo ๋ฉ”์†Œ๋“œ๋Š” ๊ฐ ํ•„๋“œ๊ฐ€ ๋™์น˜์ธ์ง€๋ฅผ ๋น„๊ตํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ๊ทธ ์ˆœ์„œ๋ฅผ ๋น„๊ตํ•œ๋‹ค.
โ—ฆ
๊ฐ์ฒด ์ฐธ์กฐ ํ•„๋“œ๋ฅผ ๋น„๊ตํ•˜๋ ค๋ฉด compareTo ๋ฉ”์†Œ๋“œ๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•œ๋‹ค.
โ—ฆ
Comparable์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์€ ํ•„๋“œ๋‚˜ ํ‘œ์ค€์ด ์•„๋‹Œ ์ˆœ์„œ๋กœ ๋น„๊ตํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ๋น„๊ต์ž(Comparator)๋ฅผ ๋Œ€์‹  ์‚ฌ์šฉํ•œ๋‹ค. ๋น„๊ต์ž๋Š” ์ง์ ‘ ๋งŒ๋“ค๊ฑฐ๋‚˜ ์ž๋ฐ”๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ค‘์— ๊ณจ๋ผ์“ฐ๋ฉด ๋œ๋‹ค.
โ€ข
๋น„๊ต์ž(Comparator)
โ—ฆ
๊ฐ์ฒด ์ฐธ์กฐ๊ฐ€ ํ•˜๋‚˜๋ฟ์ธ ๋น„๊ต์ž
public final class CaseInsensitiveString implements Comparable<CaseInsensitiveString> { private final String s; // ์ž๋ฐ”๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋น„๊ต์ž๋ฅผ ์‚ฌ์šฉํ•ด ํด๋ž˜์Šค๋ฅผ ๋น„๊ตํ•œ๋‹ค. public int compareTo(CaseInsensitiveString cis) { return String.CASE_INSENSITIVE_ORDER.compare(s, cis.s); } }
Java
๋ณต์‚ฌ
โ—ฆ
๊ธฐ๋ณธ ํƒ€์ž… ํ•„๋“œ๊ฐ€ ์—ฌ๋Ÿฟ์ผ ๋•Œ์˜ ๋น„๊ต์ž
โ–ช
compareTo ๋ฉ”์†Œ๋“œ์—์„œ ๊ด€๊ณ„ ์—ฐ์‚ฐ์ž <์™€ >๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์ „ ๋ฐฉ์‹์€ ์ถ”์ฒœํ•˜์ง€ ์•Š๋Š”๋‹ค.
โ–ช
ํด๋ž˜์Šค์— ํ•ต์‹ฌ ํ•„๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ๋ผ๋ฉด ์–ด๋А ๊ฒƒ์„ ๋จผ์ € ๋น„๊ตํ•˜๋А๋ƒ๊ฐ€ ์ค‘์š”ํ•˜๋‹ค.
โ€ข
๋น„๊ต ๊ฒฐ๊ณผ๊ฐ€ 0์ด ์•„๋‹ˆ๋ผ๋ฉด, (์ˆœ์„œ๊ฐ€ ๊ฒฐ์ •๋˜๋ฉด) ๊ฑฐ๊ธฐ์„œ ๋์ด๋‹ค. ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ณง์žฅ ๋ฐ˜ํ™˜ํ•˜์ž.
โ€ข
๊ฐ€์žฅ ํ•ต์‹ฌ์ด ๋˜๋Š” ํ•„๋“œ๊ฐ€ ๋˜‘๊ฐ™๋‹ค๋ฉด, ๋˜‘๊ฐ™์ง€ ์•Š์€ ํ•„๋“œ๋ฅผ ์ฐพ์„ ๋•Œ๊นŒ์ง€ ๊ทธ๋‹ค์Œ์œผ๋กœ ์ค‘์š”ํ•œ ํ•„๋“œ๋ฅผ ๋น„๊ตํ•ด๋‚˜๊ฐ„๋‹ค.
public int compareTo(PhoneNumber pn) { int result = Short.compare(areaCode, pn.areaCode); if (result == 0) { result = Short.compare(prefix, pn.prefix); if (result == 0) result = Short.compare(lineNum, pn.lineNum); } return result; }
Java
๋ณต์‚ฌ
โ—ฆ
๋น„๊ต์ž ์ƒ์„ฑ ๋ฉ”์†Œ๋“œ๋ฅผ ํ™œ์šฉํ•œ ๋น„๊ต์ž
private static final Comparator<PhoneNumber> COMPARATOR = comparingInt((PhoneNumber pn) -> pn.areaCode) .thenComparingInt(pn -> pn.prefix) .thenComparingInt(pn -> pn.lineNum); public int compareTo(PhoneNumber pn) { return COMPARATOR.compare(this, pn); }
Java
๋ณต์‚ฌ
โ—ฆ
์ •์  compare ๋ฉ”์†Œ๋“œ๋ฅผ ํ™œ์šฉํ•œ ๋น„๊ต์ž
static Comparator<Object> hashCodeOrder = new Comparator<>() { public int compare(Object o1, Object o2) { return Integer.compare(o1.hashCode(), o2.hashCode()); } };
Java
๋ณต์‚ฌ
โ—ฆ
๋น„๊ต์ž ์ƒ์„ฑ ๋ฉ”์†Œ๋“œ๋ฅผ ํ™œ์šฉํ•œ ๋น„๊ต์ž
static Comparator<Object> hashCodeOrder = Comparator.comparingInt(o -> o.hashCode());
Java
๋ณต์‚ฌ

ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค

ํด๋ž˜์Šค์™€ ๋ฉค๋ฒ„์˜ ์ ‘๊ทผ ๊ถŒํ•œ์„ ์ตœ์†Œํ™”ํ•˜๋ผ

โ€ข
์ž˜ ์„ค๊ณ„๋œ ์ปดํฌ๋„ŒํŠธ๋Š” ํด๋ž˜์Šค ๋‚ด๋ถ€ ๊ตฌํ˜„ ์ •๋ณด๋ฅผ ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ๋กœ๋ถ€ํ„ฐ ์™„๋ฒฝํžˆ ์ˆจ๊ธด๋‹ค.
โ†’ ๊ตฌํ˜„๊ณผ API๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•œ๋‹ค.
โ†’ ์˜ค์ง API๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์™€ ์†Œํ†ตํ•˜๋ฉฐ, ์„œ๋กœ์˜ ๋‚ด๋ถ€ ๋™์ž‘ ๋ฐฉ์‹์—๋Š” ์ „ํ˜€ ๊ฐœ์˜์น˜ ์•Š๋Š”๋‹ค. โ‡’ ์ •๋ณด ์€๋‹‰, ์บก์Аํ™”
โ—ฆ
์ •๋ณด ์€๋‹‰์˜ ์žฅ์ 
โ–ช
์‹œ์Šคํ…œ์„ ๊ตฌ์„ฑํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์„œ๋กœ ๋…๋ฆฝ์‹œ์ผœ์„œ ๊ฐœ๋ฐœ, ํ…Œ์ŠคํŠธ, ์ตœ์ ํ™”, ์ ์šฉ, ๋ถ„์„, ์ˆ˜์ •์„ ๊ฐœ๋ณ„์ ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
โ–ช
์‹œ์Šคํ…œ ๊ฐœ๋ฐœ ์†๋„๋ฅผ ๋†’์ธ๋‹ค. ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณ‘๋ ฌ๋กœ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.
โ–ช
์‹œ์Šคํ…œ ๊ด€๋ฆฌ ๋น„์šฉ์„ ๋‚ฎ์ถ˜๋‹ค. ๊ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋” ๋นจ๋ฆฌ ํŒŒ์•…ํ•˜์—ฌ ๋””๋ฒ„๊น… ํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ต์ฒดํ•˜๋Š” ๋ถ€๋‹ด๋„ ์ ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
โ–ช
์ •๋ณด ์€๋‹‰ ์ž์ฒด๊ฐ€ ์„ฑ๋Šฅ์„ ๋†’์—ฌ์ฃผ์ง€๋Š” ์•Š์ง€๋งŒ, ์„ฑ๋Šฅ ์ตœ์ ํ™”์— ๋„์›€์„ ์ค€๋‹ค.
โ€ข
์™„์„ฑ๋œ ์‹œ์Šคํ…œ์„ ํ”„๋กœํŒŒ์ผ๋งํ•ด ์ตœ์ ํ™”ํ•  ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ •ํ•œ ๋‹ค์Œ, ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ  ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋งŒ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
โ–ช
์†Œํ”„ํŠธ์›จ์–ด ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ธ๋‹ค.
โ€ข
์™ธ๋ถ€์— ๊ฑฐ์˜ ์˜์กดํ•˜์ง€ ์•Š๊ณ  ๋…์ž์ ์œผ๋กœ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋ผ๋ฉด, ๊ทธ ์ปดํฌ๋„ŒํŠธ์™€ ํ•จ๊ป˜ ๊ฐœ๋ฐœ๋˜์ง€ ์•Š์€ ๋‚ฏ์„  ํ™˜๊ฒฝ์—์„œ๋„ ์œ ์šฉํ•˜๊ฒŒ ์“ฐ์ผ ๊ฐ€๋Šฅ์„ฑ์ด ํฌ๋‹ค.
โ–ช
ํฐ ์‹œ์Šคํ…œ์„ ์ œ์ž‘ํ•˜๋Š” ๋‚œ์ด๋„๋ฅผ ๋‚ฎ์ถฐ์ค€๋‹ค. ์‹œ์Šคํ…œ ์ „์ฒด๊ฐ€ ์•„์ง ์™„์„ฑ๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ๋„ ๊ฐœ๋ณ„ ์ปดํฌ๋„ŒํŠธ์˜ ๋™์ž‘์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค.
โ€ข
์ž๋ฐ”์—์„œ ์ •๋ณด ์€๋‹‰์˜ ํ•ต์‹ฌ์€ ์ ‘๊ทผ ์ œํ•œ์ž์˜ ํ™œ์šฉ์ด๋‹ค.
โ—ฆ
๋ชจ๋“  ํด๋ž˜์Šค์™€ ๋ฉค๋ฒ„์˜ ์ ‘๊ทผ์„ฑ์„ ๊ฐ€๋Šฅํ•œ ํ•œ ์ขํ˜€์•ผ ํ•œ๋‹ค.
โ—ฆ
์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ์˜ฌ๋ฐ”๋กœ ๋™์ž‘ํ•˜๋Š” ํ•œ, ํ•ญ์ƒ ๊ฐ€์žฅ ๋‚ฎ์€ ์ ‘๊ทผ ์ˆ˜์ค€์„ ๋ถ€์—ฌํ•ด์•ผํ•œ๋‹ค.
โ€ข
๋ฉค๋ฒ„(ํ•„๋“œ, ๋ฉ”์†Œ๋“œ, ์ค‘์ฒฉ ํด๋ž˜์Šค, ์ค‘์ฒฉ ์ธํ„ฐํŽ˜์ด์Šค)์— ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ๋Š” ์ ‘๊ทผ ์ˆ˜์ค€์€ ๋„ค ๊ฐ€์ง€๋‹ค.
โ—ฆ
private : ๋ฉค๋ฒ„๋ฅผ ์„ ์–ธํ•œ ํ†ฑ๋ ˆ๋ฒจ ํด๋ž˜์Šค์—์„œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
package-private : ๋ฉค๋ฒ„๊ฐ€ ์†Œ์†๋œ ํŒจํ‚ค์ง€ ์•ˆ์˜ ๋ชจ๋“  ํด๋ž˜์Šค์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ์ ‘๊ทผ ์ œํ•œ์ž๋ฅผ ๋ช…์‹œํ•˜์ง€ ์•Š์•˜์„ ๋Œ€ ์ ์šฉ๋˜๋Š” ํŒจํ‚ค์ง€ ์ ‘๊ทผ ์ˆ˜์ค€์ด๋‹ค. (๋‹จ, ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉค๋ฒ„๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ public์ด๋‹ค.)
โ—ฆ
protected : package-private์˜ ์ ‘๊ทผ ๋ฒ”์œ„๋ฅผ ํฌํ•จํ•˜์—ฌ, ์ด ๋ฉค๋ฒ„๋ฅผ ์„ ์–ธํ•œ ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ๋„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
public : ๋ชจ๋“  ๊ณณ์—์„œ ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
์ ‘๊ทผ ์ œํ•œ์ž ํ™œ์šฉ์„ ํ†ตํ•œ ์ •๋ณด ์€๋‹‰ (์ ‘๊ทผ ๊ถŒํ•œ ์ตœ์†Œํ™”)
โ€ข
ํด๋ž˜์Šค์˜ ๊ณต๊ฐœ API๋ฅผ ์„ธ์‹ฌํžˆ ์„ค๊ณ„ํ•œ ํ›„, ๊ทธ ์™ธ์˜ ๋ชจ๋“  ๋ฉค๋ฒ„๋Š” private์œผ๋กœ ๋งŒ๋“ค์ž.
โ€ข
์˜ค์ง ๊ฐ™์€ ํŒจํ‚ค์ง€์˜ ๋‹ค๋ฅธ ํด๋ž˜์Šค๊ฐ€ ์ ‘๊ทผํ•ด์•ผ ํ•˜๋Š” ๋ฉค๋ฒ„์— ํ•œํ•˜์—ฌ package-private์œผ๋กœ ํ’€์–ด์ฃผ์ž.
โ€ข
public ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋Š” ๋˜๋„๋ก public์ด ์•„๋‹ˆ์–ด์•ผํ•œ๋‹ค.
โ—ฆ
ํ•ด๋‹น ํ•„๋“œ์™€ ๊ด€๋ จ๋œ ๋ชจ๋“  ๊ฒƒ์€ ๋ถˆ๋ณ€์‹์„ ๋ณด์žฅํ•  ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค.
โ—ฆ
public ๊ฐ€๋ณ€ ํ•„๋“œ๋ฅผ ๊ฐ–๋Š” ํด๋ž˜์Šค๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ thread-safeํ•˜์ง€ ์•Š๋‹ค.
โ€ข
๊ผญ ํ•„์š”ํ•œ ์š”์†Œ๋กœ์„œ์˜ ์ƒ์ˆ˜๋ผ๋ฉด public static field๋กœ ๊ณต๊ฐœํ•œ๋‹ค.
โ€ข
ํด๋ž˜์Šค์—์„œ public static final ๋ฐฐ์—ด ํ•„๋“œ๋ฅผ ๋‘๊ฑฐ๋‚˜, ์ด ํ•„๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ ‘๊ทผ์ž ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. โ†’ ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ฐฐ์—ด์˜ ๋‚ด์šฉ์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.
// ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๋ฐฐ์—ด public static final Thing[] VALUES = { ... };
Java
๋ณต์‚ฌ
โ—ฆ
ํ•ด๊ฒฐ์ฑ…
โ–ช
public ๋ฐฐ์—ด์„ private์œผ๋กœ ๋งŒ๋“ค๊ณ , public ๋ถˆ๋ณ€ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
// public ๋ฐฐ์—ด์„ private์œผ๋กœ ๋งŒ๋“ค๊ณ , public ๋ถˆ๋ณ€ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. private static final Thing[] PRIVATE_VALUES = { ... }; public static final List<Thing> VALUES { Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES))); }
Java
๋ณต์‚ฌ
โ–ช
๋ฐฐ์—ด์„ private๋กœ ๋งŒ๋“ค๊ณ , ๊ทธ ๋ณต์‚ฌ๋ณธ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” public ๋ฉ”์†Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. (๋ฐฉ์–ด์  ๋ณต์‚ฌ)
private static final Thing[] PRIVATE_VALUES = { ... }; public static final Thing[] values() { return PRIVATE_VALUES.clone(); }
Java
๋ณต์‚ฌ

์ƒ์†๋ณด๋‹ค๋Š” ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•˜๋ผ

โ€ข
๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ๊ณผ ๋‹ฌ๋ฆฌ ์ƒ์†์€ ์บก์Аํ™”๋ฅผ ๊นจ๋œจ๋ฆฐ๋‹ค.
โ—ฆ
์ƒ์œ„ ํด๋ž˜์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜๋А๋ƒ์— ๋”ฐ๋ผ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๋™์ž‘์— ์ด์ƒ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
์ƒ์œ„ ํด๋ž˜์Šค๋Š” ๋ฆด๋ฆฌ์Šค๋งˆ๋‹ค ๋‚ด๋ถ€ ๊ตฌํ˜„์ด ๋‹ฌ๋ผ์ง„๋‹ค. โ†’ ์ˆ˜์ •ํ•˜์ง€ ์•Š์€ ํ•˜์œ„ํด๋ž˜์Šค๊ฐ€ ์˜ค๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.
โ€ข
ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ๊นจ์ง€๊ธฐ ์‰ฌ์šด ์ด์œ 
โ—ฆ
์ž์‹ ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์„ ์‚ฌ์šฉํ•˜๋Š” ์ž๊ธฐ ์‚ฌ์šฉ(self-use) ์—ฌ๋ถ€
public class InstrumentedHashSet<E> extends HashSet<E>{ private int addCount = 0; @Override public boolean add(E e){ addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c){ addCount += c.size(); return super.addAll(c); } }
Java
๋ณต์‚ฌ
โ–ช
์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค! ์™œ?
โ€ข
InstrumentedHashSet์˜ addAll ๋ฉ”์†Œ๋“œ๊ฐ€ HashSet(super)์˜ addAll ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๊ตฌํ˜„๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
โ€ข
HashSet์˜ addAll ๋ฉ”์†Œ๋“œ๋Š” ์ด๋ฏธ add ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค. (์ด๋Ÿฌํ•œ ๋‚ด๋ถ€ ๊ตฌํ˜„ ๋ฐฉ์‹์€ HashSet ๋ฌธ์„œ์—๋Š” ์“ฐ์—ฌ์žˆ์ง€ ์•Š๋‹ค.)
โ€ข
HashSet์˜ addAll์€ ๊ฐ ์›์†Œ๋ฅผ add ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ์ถ”๊ฐ€ํ•˜๋Š”๋ฐ, ์ด๋•Œ ๋ถˆ๋ฆฌ๋Š” add๋Š” InstrumentedHashSet์—์„œ ์žฌ์ •์˜ ํ•œ ๋ฉ”์†Œ๋“œ์ด๋ฏ€๋กœ, addCount์— ์ค‘๋ณตํ•ด์„œ ๊ฐ’์ด ๋”ํ•ด์ง€๊ฒŒ ๋œ๋‹ค.
โ—ฆ
๋‹ค์Œ ๋ฆด๋ฆฌ์Šค์—์„œ ์ƒ์œ„ ํด๋ž˜์Šค์— ์ƒˆ๋กœ์šด ๋ฉ”์†Œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋œ ๊ฒฝ์šฐ
โ—ฆ
ํด๋ž˜์Šค๋ฅผ ํ™•์žฅ but ๋ฉ”์†Œ๋“œ ์žฌ์ •์˜ ๋Œ€์‹  ์ƒˆ๋กœ์šด ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€
โ–ช
๋‹ค์Œ ๋ฆด๋ฆฌ์Šค์— ์ƒ์œ„ ํด๋ž˜์Šค์— ์ƒˆ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋Š”๋ฐ, ์šด์ด ์—†๊ฒŒ๋„ ํ•˜์œ„ ํด๋ž˜์Šค์— ์ถ”๊ฐ€ํ•œ ๋ฉ”์†Œ๋“œ์™€ ์‹œ๊ทธ๋‹ˆ์ณ๊ฐ€ ๊ฐ™๊ณ , ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋‹ค๋ฅด๋‹ค๋ฉด? โ†’ ์ปดํŒŒ์ผ ์กฐ์ฐจ ๋ถˆ๊ฐ€๋Šฅํ•จ
โ–ช
๋ฐ˜ํ™˜ ํƒ€์ž… ๋งˆ์ € ๊ฐ™๋‹ค๋ฉด? ์•ž์„œ์˜ ๋ฌธ์ œ์™€ ๋˜‘๊ฐ™์ด ๋ฉ”์†Œ๋“œ ์žฌ์ •์˜ํ•œ ๊ฒƒ๊ณผ ๊ฒฐ๊ณผ๊ฐ€ ๋™์ผ
์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์ƒ์†์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ž.
โ€ข
๊ธฐ์กด ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•˜๋Š” ๋Œ€์‹ , ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  private ํ•„๋“œ๋กœ ๊ธฐ์กด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ ํ•˜์ž.
โ€ข
๊ธฐ์กด ํด๋ž˜์Šค๊ฐ€ ์ƒˆ๋กœ์šด ํด๋ž˜์Šค์˜ ๊ตฌ์„ฑ์š”์†Œ๋กœ ์“ฐ์ธ๋‹ค๋Š” ๋œป์—์„œ, ์ด๋Ÿฌํ•œ ์„ค๊ณ„๋ฅผ ์ปดํฌ์ง€์…˜(composition)์ด๋ผ๊ณ  ํ•œ๋‹ค.
โ€ข
์ „๋‹ฌ(forwarding)
โ—ฆ
์ƒˆ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์†Œ๋“œ๋“ค์€ ๊ธฐ์กด ํด๋ž˜์Šค์˜ ๋Œ€์‘ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
โ—ฆ
์ƒˆ ํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ์ „๋‹ฌ ๋ฉ”์†Œ๋“œ(forwarding method)๋ผ๊ณ  ํ•œ๋‹ค.
โ€ข
์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋Š” ๊ธฐ์กด ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„ ๋ฐฉ์‹์˜ ์˜ํ–ฅ์—์„œ ๋ฒ—์–ด๋‚˜๋ฉฐ, ๊ธฐ์กด ํด๋ž˜์Šค์— ์ƒˆ๋กœ์šด ๋ฉ”์†Œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜๋”๋ผ๋„ ์ „ํ˜€ ์˜ํ–ฅ๋ฐ›์ง€ ์•Š๋Š”๋‹ค!
โ€ข
์•„๋ž˜์™€ ๊ฐ™์ด ๋ž˜ํผ ํด๋ž˜์Šค/์ „๋‹ฌํด๋ž˜์Šค
// ์ฝ”๋“œ 18-2 ๋ž˜ํผ ํด๋ž˜์Šค - ์ƒ์† ๋Œ€์‹  ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ–ˆ๋‹ค. (117-118์ชฝ) // Decorator pattern public class InstrumentedSet<E> extends ForwardingSet<E> { private int addCount = 0; public InstrumentedSet(Set<E> s) { super(s); } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } public static void main(String[] args) { InstrumentedSet<String> s = new InstrumentedSet<>(new HashSet<>()); s.addAll(List.of("ํ‹ฑ", "ํƒํƒ", "ํŽ‘")); System.out.println(s.getAddCount()); } } // ์ฝ”๋“œ 18-3 ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ „๋‹ฌ ํด๋ž˜์Šค (118์ชฝ) public class ForwardingSet<E> implements Set<E> { private final Set<E> s; public ForwardingSet(Set<E> s) { this.s = s; } public void clear() { s.clear(); } public boolean contains(Object o) { return s.contains(o); } public boolean isEmpty() { return s.isEmpty(); } public int size() { return s.size(); } public Iterator<E> iterator() { return s.iterator(); } public boolean add(E e) { return s.add(e); } public boolean remove(Object o) { return s.remove(o); } public boolean containsAll(Collection<?> c) { return s.containsAll(c); } public boolean addAll(Collection<? extends E> c) { return s.addAll(c); } public boolean removeAll(Collection<?> c) { return s.removeAll(c); } public boolean retainAll(Collection<?> c) { return s.retainAll(c); } public Object[] toArray() { return s.toArray(); } public <T> T[] toArray(T[] a) { return s.toArray(a); } @Override public boolean equals(Object o) { return s.equals(o); } @Override public int hashCode() { return s.hashCode(); } @Override public String toString() { return s.toString(); } }
Java
๋ณต์‚ฌ
โ€ข
์ƒ์†์€ ๋ฐ˜๋“œ์‹œ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์ƒ์œ„ ํด๋ž˜์Šค์˜ โ€˜์ง„์งœโ€™ ํ•˜์œ„ ํƒ€์ž…์ธ ์ƒํ™ฉ์—์„œ๋งŒ ์“ฐ์—ฌ์•ผํ•œ๋‹ค.
โ—ฆ
ํด๋ž˜์Šค B๊ฐ€ ํด๋ž˜์Šค A์™€ is-a ๊ด€๊ณ„์ผ ๋•Œ๋งŒ ํด๋ž˜์Šค A๋ฅผ ์ƒ์†ํ•ด์•ผ ํ•œ๋‹ค.

์ถ”์ƒํด๋ž˜์Šค ๋ณด๋‹ค๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์šฐ์„ ํ•˜๋ผ

โ€ข
์ถ”์ƒํด๋ž˜์Šค๊ฐ€ ์ •์˜ํ•œ ํƒ€์ž…์„ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค๋Š” ๋ฐ˜๋“œ์‹œ ์ถ”์ƒํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค.
โ—ฆ
์ž๋ฐ”๋Š” ๋‹จ์ผ ์ƒ์†๋งŒ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ƒˆ๋กœ์šด ํƒ€์ž…์„ ์ •์˜ํ•˜๋Š”๋ฐ ์ปค๋‹ค๋ž€ ์ œ์•ฝ์ด ๋œ๋‹ค.
โ€ข
์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์„ ์–ธํ•œ ๋ฉ”์†Œ๋“œ๋ฅผ ๋ชจ๋‘ ์ •์˜ํ•˜๊ณ  ๊ทธ ์ผ๋ฐ˜ ๊ทœ์•ฝ์„ ์ž˜ ์ง€ํ‚จ ํด๋ž˜์Šค๋ผ๋ฉด ๋‹ค๋ฅธ ์–ด๋–ค ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ–ˆ๋“  ๊ฐ™์€ ํƒ€์ž…์œผ๋กœ ์ทจ๊ธ‰๋œ๋‹ค.
โ€ข
์ธํ„ฐํŽ˜์ด์Šค์˜ ์žฅ์ 
โ—ฆ
๊ธฐ์กด ํด๋ž˜์Šค์—๋„ ์†์‰ฝ๊ฒŒ ์ƒˆ๋กœ์šด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ฏน์Šค์ธ ์ •์˜์— ์•ˆ์„ฑ๋งž์ถค์ด๋‹ค.
โ–ช
๋ฏน์Šค์ธ์ด๋ž€ ํด๋ž˜์Šค๊ฐ€ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์œผ๋กœ, ๋ฏน์Šค์ธ์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์— ์›๋ž˜์˜ โ€˜์ฃผ๋œ ํƒ€์ž…โ€™ ์™ธ์—๋„ ํŠน์ • ์„ ํƒ์  ํ–‰์œ„๋ฅผ ์ œ๊ณตํ•œ๋‹ค๊ณ  ์„ ์–ธํ•˜๋Š” ํšจ๊ณผ๋ฅผ ์ค€๋‹ค.
โ–ช
์ถ”์ƒํด๋ž˜์Šค๋Š” ๊ธฐ์กด ํด๋ž˜์Šค์— ๋ง์”Œ์šธ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ๋ฏน์Šค์ธ์„ ์ •์˜ํ•  ์ˆ˜ ์—†๋‹ค.
โ—ฆ
์ธํ„ฐํŽ˜์ด์Šค๋กœ๋Š” ๊ณ„์ธต๊ตฌ์กฐ๊ฐ€ ์—†๋Š” ํƒ€์ž… ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
์ธํ„ฐํŽ˜์ด์Šค ํ™œ์šฉ
โ€ข
๋ž˜ํผ ํด๋ž˜์Šค์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ธฐ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ์•ˆ์ „ํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ์ˆ˜๋‹จ์ด ๋œ๋‹ค.
โ€ข
์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์„œ๋“œ ์ค‘ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์ด ๋ช…๋ฐฑํ•œ ๊ฒƒ์ด ์žˆ๋‹ค๋ฉด, ๊ทธ ๊ตฌํ˜„์„ ๋””ํดํŠธ ๋ฉ”์†Œ๋“œ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.
โ€ข
์ธํ„ฐํŽ˜์ด์Šค์™€ ์ถ”์ƒ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ํ•จ๊ป˜ ์ œ๊ณตํ•˜์—ฌ, ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ถ”์ƒ ํด๋ž˜์Šค์˜ ์žฅ์ ์„ ๋ชจ๋‘ ์ทจํ•  ์ˆ˜ ์žˆ๋‹ค. โ†’ ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด
โ—ฆ
์ธํ„ฐํŽ˜์ด์Šค๋กœ๋Š” ํƒ€์ž…์„ ์ •์˜, ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋””ํดํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ํ•จ๊ป˜ ์ œ๊ณต
โ—ฆ
๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋Š” ๋‚˜๋จธ์ง€ ๋ฉ”์†Œ๋“œ๋“ค๊นŒ์ง€ ๊ตฌํ˜„
โ–ช
๊ด€๋ก€์ƒ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ด๋ฆ„์ด Interface๋ผ๋ฉด, ๊ทธ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค์˜ ์ด๋ฆ„์€ AbstractInterface๋กœ ์ง“๋Š”๋‹ค.
โ–ช
์ถ”์ƒ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ๊ตฌํ˜„์„ ๋„์™€์ฃผ๋Š” ๋™์‹œ์—, ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ํƒ€์ž…์„ ์ •์˜ํ•  ๋•Œ ๋”ฐ๋ผ์˜ค๋Š” ์‹ฌ๊ฐํ•œ ์ œ์•ฝ์—์„œ๋Š” ์ž์œ ๋กญ๋‹ค.
โ€ข
๊ณจ๊ฒฉ ๊ตฌํ˜„ ์ž‘์„ฑ ๋ฐฉ๋ฒ•
โ—ฆ
๋‹ค๋ฅธ ๋ฉ”์†Œ๋“œ๋“ค์˜ ๊ตฌํ˜„์— ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋ฐ˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์„ ์ •ํ•œ๋‹ค. โ†’ ์ถ”์ƒ๋ฉ”์†Œ๋“œ
โ—ฆ
๊ธฐ๋ฐ˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ์‚ฌ์šฉํ•ด ์ง์ ‘ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์†Œ๋“œ๋“ค์„ ๋ชจ๋‘ ๋””ํดํŠธ ๋ฉ”์†Œ๋“œ๋กœ ์ œ๊ณตํ•œ๋‹ค.
// ์ฝ”๋“œ 20-1 ๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ์‚ฌ์šฉํ•ด ์™„์„ฑํ•œ ๊ตฌ์ฒด ํด๋ž˜์Šค (133์ชฝ) public class IntArrays { 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; } }; } } // ์ฝ”๋“œ 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(); } }
Java
๋ณต์‚ฌ

๋ฉค๋ฒ„ ํด๋ž˜์Šค๋Š” ๋˜๋„๋ก static์œผ๋กœ ๋งŒ๋“ค๋ผ

์ค‘์ฒฉ ํด๋ž˜์Šค๋ž€? ๋‹ค๋ฅธ ํด๋ž˜์Šค ์•ˆ์— ์ •์˜๋œ ํด๋ž˜์Šค๋ฅผ ๋งํ•œ๋‹ค.
โ€ข
์ •์  ๋ฉค๋ฒ„ ํด๋ž˜์Šค
โ—ฆ
๋ฐ”๊นฅ ํด๋ž˜์Šค์™€ ํ•จ๊ป˜ ์“ฐ์ผ ๋•Œ๋งŒ ์œ ์šฉํ•œ public ๋„์šฐ๋ฏธ ํด๋ž˜์Šค๋กœ ์“ฐ์ธ๋‹ค.
โ€ข
๋น„์ •์  ๋ฉค๋ฒ„ ํด๋ž˜์Šค
โ—ฆ
๋น„์ •์  ๋ฉค๋ฒ„ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋Š” ๋ฐ”๊นฅ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์™€ ์•”๋ฌต์ ์œผ๋กœ ์—ฐ๊ฒฐ๋œ๋‹ค.
โ—ฆ
๋น„์ •์  ๋งด๋ฒ„ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์†Œ๋“œ์—์„œ ์ •๊ทœํ™”๋œ this๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ”๊นฅ ์ธ์Šคํ„ด์Šค์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜, ๋ฐ”๊นฅ ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
โ–ช
์ •๊ทœํ™”๋œ this๋ž€ ํด๋ž˜์Šค๋ช….this ํ˜•ํƒœ๋กœ ๋ฐ”๊นฅ ํด๋ž˜์Šค์˜ ์ด๋ฆ„์„ ๋ช…์‹œํ•˜๋Š” ์šฉ๋ฒ•์„ ๋งํ•œ๋‹ค.
โ—ฆ
์ค‘์ฒฉ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฐ”๊นฅ ์ธ์Šคํ„ด์Šค์™€ ๋…๋ฆฝ์ ์œผ๋กœ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ์ •์  ๋ฉค๋ฒ„ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์–ด์•ผํ•œ๋‹ค. โ†’ ๋น„์ •์  ๋ฉค๋ฒ„ ํด๋ž˜์Šค๋Š” ๋ฐ”๊นฅ ์ธ์Šคํ„ด์Šค ์—†์ด๋Š” ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋‹ค.
โ—ฆ
๋น„์ •์  ๋ฉค๋ฒ„ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์™€ ๋ฐ”๊นฅ ์ธ์Šคํ„ด์Šค ์‚ฌ์ด์˜ ๊ด€๊ณ„๋Š” ๋ฉค๋ฒ„ ํด๋ž˜์Šค๊ฐ€ ์ธ์Šคํ„ด์Šคํ™”๋  ๋•Œ ํ™•๋ฆฝ๋˜๋ฉฐ, ๋” ์ด์ƒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.
โ—ฆ
์–ด๋Œ‘ํ„ฐ๋ฅผ ์ •์˜ํ•  ๋•Œ ์ž์ฃผ ์“ฐ์ธ๋‹ค.
โ–ช
์–ด๋–ค ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ์‹ธ ๋งˆ์น˜ ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ํ•˜๋Š” ๋ทฐ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
public class MySet<E> extends AbstractSet<E> { ... @Override public Iterator<E> iterator() { return new MyIterator(); } private class MyIterator implements Iterator<E> { ... } }
Java
๋ณต์‚ฌ
๋ฉค๋ฒ„ ํด๋ž˜์Šค์—์„œ ๋ฐ”๊นฅ ์ธ์Šคํ„ด์Šค์— ์ ‘๊ทผํ•  ์ผ์ด ์—†๋‹ค๋ฉด, ๋ฌด์กฐ๊ฑด static์„ ๋ถ™์—ฌ์„œ ์ •์  ๋ฉค๋ฒ„ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์ž. static์„ ์ƒ๋žตํ•˜๋ฉด ๋ฐ”๊นฅ ์ธ์Šคํ„ด์Šค๋กœ์˜ ์ˆจ์€ ์™ธ๋ถ€ ์ฐธ์กฐ๋ฅผ ๊ฐ–๊ฒŒ๋œ๋‹ค.
โ€ข
์ต๋ช… ํด๋ž˜์Šค
โ—ฆ
์ค‘์ฒฉ ํด๋ž˜์Šค๊ฐ€ ํ•œ ๋ฉ”์†Œ๋“œ ์•ˆ์—์„œ๋งŒ ์“ฐ์ด๋ฉด์„œ, ๊ทธ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ง€์ ์ด ๋‹จ ํ•œ ๊ณณ์ด๊ณ  ํ•ด๋‹น ํƒ€์ž…์œผ๋กœ ์“ฐ๊ธฐ์— ์ ํ•ฉํ•œ ํด๋ž˜์Šค๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ด๋ฏธ ์žˆ๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ
โ€ข
์ง€์—ญ ํด๋ž˜์Šค
โ—ฆ
๊ฐ€์žฅ ๋“œ๋ฌผ๊ฒŒ ์‚ฌ์šฉ

์ œ๋„ค๋ฆญ

๋กœ์šฐ ํƒ€์ž…์€ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ

โ€ข
ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค ์„ ์–ธ์— ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜(type parameter)๊ฐ€ ์“ฐ์ด๋ฉด, ์ด๋ฅผ ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค ํ˜น์€ ์ œ๋„ค๋ฆญ ์ธํ„ฐํŽ˜์ด์Šค๋ผ๊ณ  ํ•œ๋‹ค. โ†’ ์ œ๋„ค๋ฆญ ํƒ€์ž…(Generic Type)
โ—ฆ
List<E>
โ€ข
๊ฐ๊ฐ์˜ ์ œ๋„ค๋ฆญ ํƒ€์ž…์€ ์ผ๋ จ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…(parameterized type)์„ ์ •์˜ํ•œ๋‹ค.
โ—ฆ
List<String> : ์›์†Œ์˜ ํƒ€์ž…์ด String์ธ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋œปํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์ด๋‹ค. ์—ฌ๊ธฐ์„œ String์ด ์ •๊ทœํ™”(formal) ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ E์— ํ•ด๋‹นํ•˜๋Š” ์‹ค์ œ(actual) ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์ด๋‹ค.
โ€ข
์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ํ•˜๋‚˜ ์ •์˜ํ•˜๋ฉด, ๊ทธ์— ๋”ธ๋ฆฐ ๋กœ์šฐ ํƒ€์ž…(raw type)๋„ ํ•จ๊ป˜ ์ •์˜๋œ๋‹ค.
โ—ฆ
List<E>์˜ ๋กœ์šฐํƒ€์ž…์€ List์ด๋‹ค.
โ—ฆ
ํƒ€์ž… ์„ ์–ธ์—์„œ ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ •๋ณด๊ฐ€ ์ „๋ถ€ ์ง€์›Œ์ง„ ๊ฒƒ์ฒ˜๋Ÿผ ๋™์ž‘ํ•œ๋‹ค.
โ€ข
๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋œ ์ปฌ๋ ‰์…˜ ํƒ€์ž…์€ ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
private final Collection stamps = ...; ๐Ÿ™…โ€โ™€๏ธ
โ–ช
complie์€ ๋˜์ง€๋งŒ, ๋Ÿฐํƒ€์ž„์— ์น˜๋ช…์ ์ธ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
โ—ฆ
private final Collection<Stamp> stamps = ...; ๐Ÿ™†โ€โ™€๏ธ
๋กœ์šฐ ํƒ€์ž…์€ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ๋ผ
โ€ข
์ œ๋„ค๋ฆญ์ด ์•ˆ๊ฒจ์ฃผ๋Š” ์•ˆ์ •์„ฑ๊ณผ ํ‘œํ˜„๋ ฅ์„ ๋ชจ๋‘ ์žƒ๊ฒŒ ๋œ๋‹ค.
โ€ข
List๊ฐ™์€ ๋กœ์šฐ ํƒ€์ž…์€ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ๋˜๋‚˜, List<Object>์ฒ˜๋Ÿผ ์ž„์˜ ๊ฐ์ฒด๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์€ ๊ดœ์ฐฎ๋‹ค.
โ—ฆ
List๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์—์„œ ์™„์ „ํžˆ ๋ฐœ์„ ๋บ€ ๊ฒƒ์ด๊ณ , List<Object>๋Š” ๋ชจ๋“  ํƒ€์ž…์„ ํ—ˆ์šฉํ•œ๋‹ค๋Š” ์˜์‚ฌ๋ฅผ ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ๋ช…ํ™•ํžˆ ์ „๋‹ฌํ•œ ๊ฒƒ์ด๋‹ค.
โ€ข
๋น„ํ•œ์ •์  ์™€์ผ๋“œ ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ผ.
โ—ฆ
ํƒ€์ž… ์•ˆ์ „ํ•˜๋ฉฐ ์œ ์—ฐํ•˜๋‹ค.
โ—ฆ
์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์“ฐ๊ณ  ์‹ถ์ง€๋งŒ, ์‹ค์ œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์‹ ๊ฒฝ ์“ฐ๊ณ  ์‹ถ์ง€ ์•Š์„ ๋•Œ
โ—ฆ
static int numElementsInCommon(Set<?> s1, Set<?> s2) { ... }
โ—ฆ
๋น„ํ•œ์ •์  ์™€์ผ๋“œ ์นด๋“œ ํƒ€์ž…์ธ Set<?>์™€ ๋กœ์šฐ ํƒ€์ž… Set์˜ ์ฐจ์ด๋Š” ๋ฌด์—‡์ผ๊นŒ?
โ–ช
์™€์ผ๋“œ ํƒ€์ž…์€ ์•ˆ์ „ํ•˜๊ณ , ๋กœ์šฐํƒ€์ž…์€ ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค.
โ–ช
๋กœ์šฐ ํƒ€์ž… ์ปฌ๋ ‰์…˜์—๋Š” ์•„๋ฌด ์›์†Œ๋‚˜ ๋„ฃ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ํƒ€์ž… ๋ถˆ๋ณ€์‹์„ ํ›ผ์†ํ•˜๊ธฐ ์‰ฝ๋‹ค.
โ–ช
Collection<?>์—๋Š” (null ์ด์™ธ์—๋Š”) ์–ด๋–ค ์›์†Œ๋„ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค.
โ€ข
๋กœ์šฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ
โ—ฆ
class ๋ฆฌํ„ฐ๋Ÿด์—๋Š” ๋กœ์šฐ ํƒ€์ž…์„ ์จ์•ผํ•œ๋‹ค.
โ–ช
List.class, String[].class, int.class๋Š” ํ—ˆ์šฉํ•˜๊ณ , List<String>.class์™€ List<?>.class๋Š” ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
โ—ฆ
๋Ÿฐํƒ€์ž„์—๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… ์ •๋ณด๊ฐ€ ์ง€์›Œ์ง€๋ฏ€๋กœ, instanceof ์—ฐ์‚ฐ์ž๋Š” ๋น„ํ•œ์ •์  ์™€์ผ๋“œ์นด์ž… ์ด์™ธ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์—๋Š” ์ ์šฉํ•  ์ˆ˜์—†๋‹ค.
โ—ฆ
๋กœ์šฐ ํƒ€์ž…์ด๋“ , ๋น„ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์ด๋“  instanceof๋Š” ์™„์ „ํžˆ ๋˜‘๊ฐ™์ด ๋™์ž‘ํ•œ๋‹ค. โ†’ ๊ทธ๋Ÿฌ๋ฏ€๋กœ ํ•„์š”์—†๋Š” <?>๋Š” ์“ฐ์ง€๋ง์ž.
โ—ฆ
if (o instanceof Set) { Set<?> s = (Set<?>) o; }

๋ฐฐ์—ด๋ณด๋‹ค๋Š” ๋ฆฌ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ

โ€ข
๋ฐฐ์—ด๊ณผ ์ œ๋„ค๋ฆญ์˜ ์ฐจ์ด
โ—ฆ
๋ฐฐ์—ด์€ ๊ณต๋ณ€์ด์ง€๋งŒ ์ œ๋„ค๋ฆญ์€ ๋ถˆ๊ณต๋ณ€์ด๋‹ค.
โ–ช
Sub๊ฐ€ Super์˜ ํ•˜์œ„ ํƒ€์ž…์ด๋ผ๋ฉด ๋ฐฐ์—ด Sub[]๋Š” ๋ฐฐ์—ด Super[]์˜ ํ•˜์œ„ ํƒ€์ž…์ด ๋œ๋‹ค.
โ–ช
ํƒ€์ž… ๋ถˆ์ผ์น˜์‹œ ๋Ÿฐํƒ€์ž„์— ์‹คํŒจ(๋ฐฐ์—ด) vs ์ปดํŒŒ์ผํ•  ๋•Œ ์‹คํŒจ(์ œ๋„ค๋ฆญ)
โ—ฆ
๋ฐฐ์—ด์€ ์‹ค์ฒดํ™” ๋œ๋‹ค.
โ–ช
๋ฐฐ์—ด์€ ๋Ÿฐํƒ€์ž„์—๋„ ์ž์‹ ์ด ๋‹ด๊ธฐ๋กœ ํ•œ ์›์†Œ์˜ ํƒ€์ž…์„ ์ธ์ง€ํ•˜๊ณ  ํ™•์ธํ•œ๋‹ค.
โ€ข
๋Ÿฐํƒ€์ž„์—๋Š” type-safeํ•˜๋‹ค.
โ–ช
์ œ๋„ค๋ฆญ์€ ํƒ€์ž… ์ •๋ณด๊ฐ€ ๋Ÿฐํƒ€์ž„์—๋Š” ์†Œ๊ฑฐ๋œ๋‹ค.
โ€ข
๋Ÿฐํƒ€์ž„์—๋Š” type-safeํ•˜์ง€ ์•Š์ง€๋งŒ, ์ปดํŒŒ์ผ ์‹œ type check๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
โ—ฆ
๋ฐฐ์—ด์€ ์ œ๋„ค๋ฆญ ํƒ€์ž…, ๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…, ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
โ—ฆ
์ œ๋„ค๋ฆญ์€ type-safeํ•˜๋‹ค. (์ปดํŒŒ์ผ ํƒ€์ž„์— ์—๋Ÿฌ๋ฅผ ์žก์„ ์ˆ˜ ์žˆ๋‹ค.)
// ์ฝ”๋“œ 28-6 ๋ฆฌ์ŠคํŠธ ๊ธฐ๋ฐ˜ Chooser - ํƒ€์ž… ์•ˆ์ „์„ฑ ํ™•๋ณด! (168์ชฝ) public class Chooser<T> { private final List<T> choiceList; public Chooser(Collection<T> choices) { choiceList = new ArrayList<>(choices); } public T choose() { Random rnd = ThreadLocalRandom.current(); return choiceList.get(rnd.nextInt(choiceList.size())); }
Java
๋ณต์‚ฌ

์—ด๊ฑฐํƒ€์ž…๊ณผ ์• ๋„ˆํ…Œ์ด์…˜

int ์ƒ์ˆ˜ ๋Œ€์‹  ์—ด๊ฑฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ผ

โ€ข
์ •์ˆ˜ ์—ด๊ฑฐ ํŒจํ„ด์€ ์ƒ๋‹นํžˆ ์ทจ์•ฝํ•˜๊ณ , ๋‹จ์ ์ด ๋งŽ๋‹ค.
โ—ฆ
ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ๋ณด์žฅํ•  ๋ฐฉ๋ฒ•์ด ์—†๋‹ค.
โ—ฆ
ํ‘œํ˜„๋ ฅ์ด ์ข‹์ง€ ์•Š๋‹ค.
โ—ฆ
๋™๋“ฑ ์—ฐ์‚ฐ์ž๋กœ ๋น„๊ตํ•˜๋”๋ผ๋„ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์•Œ์•„์ฑ„์ง€ ๋ชปํ•œ๋‹ค.
์—ด๊ฑฐ ํƒ€์ž…
โ€ข
์ž๋ฐ”์˜ ์—ด๊ฑฐ ํƒ€์ž…์€ ์™„์ „ํ•œ ํ˜•ํƒœ์˜ ํด๋ž˜์Šค์ด๋‹ค.
โ€ข
์ƒ์ˆ˜ ํ•˜๋‚˜๋‹น ์ž์‹ ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ํ•˜๋‚˜์”ฉ ๋งŒ๋“ค์–ด public static final ํ•„๋“œ๋กœ ๊ณต๊ฐœํ•œ๋‹ค.
โ€ข
๋ฐ–์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์‚ฌ์‹ค์ƒ final์ด๋‹ค.
โ€ข
ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ธ์Šคํ„ด์Šค๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ํ™•์žฅํ•  ์ˆ˜ ์—†์œผ๋‹ˆ, ์—ด๊ฑฐ ํƒ€์ž… ์„ ์–ธ์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ ์ธ์Šคํ„ด์Šค๋“ค์€ ๋”ฑ ํ•˜๋‚˜์”ฉ๋งŒ ์กด์žฌํ•จ์ด ๋ณด์žฅ๋œ๋‹ค.
โ€ข
์ปดํŒŒ์ผํƒ€์ž„ ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.
โ€ข
๋ฉ”์†Œ๋“œ์™€ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
โ€ข
ํ™œ์šฉ
โ—ฆ
์ƒ์ˆ˜๋ณ„ ๋ฉ”์†Œ๋“œ ๊ตฌํ˜„์„ ํ™œ์šฉํ•œ ์—ด๊ฑฐ ํƒ€์ž…
โ–ช
์ƒ์ˆ˜๋ณ„๋กœ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์—ด๊ฑฐ ํƒ€์ž…์— ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๋ฅผ ์„ ์–ธํ•˜๊ณ , ๊ฐ ์ƒ์ˆ˜๋ณ„ ํด๋ž˜์Šค ๋ชธ์ฒด, ์ฆ‰ ๊ฐ ์ƒ์ˆ˜์—์„œ ์ž์‹ ์— ๋งž๊ฒŒ ์žฌ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
โ–ช
์—ด๊ฑฐ ํƒ€์ž… ์ƒ์ˆ˜๋ผ๋ฆฌ ์ฝ”๋“œ๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.
// ์ฝ”๋“œ 34-6 ์ƒ์ˆ˜๋ณ„ ํด๋ž˜์Šค ๋ชธ์ฒด(class body)์™€ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ ์—ด๊ฑฐ ํƒ€์ž… (215-216์ชฝ) public enum Operation { PLUS("+") { public double apply(double x, double y) { return x + y; } }, MINUS("-") { public double apply(double x, double y) { return x - y; } }, TIMES("*") { public double apply(double x, double y) { return x * y; } }, DIVIDE("/") { public double apply(double x, double y) { return x / y; } }; private final String symbol; Operation(String symbol) { this.symbol = symbol; } @Override public String toString() { return symbol; } public abstract double apply(double x, double y); // ์ฝ”๋“œ 34-7 ์—ด๊ฑฐ ํƒ€์ž…์šฉ fromString ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ํ•˜๊ธฐ (216์ชฝ) private static final Map<String, Operation> stringToEnum = Stream.of(values()).collect( toMap(Object::toString, e -> e)); // ์ง€์ •ํ•œ ๋ฌธ์ž์—ด์— ํ•ด๋‹นํ•˜๋Š” Operation์„ (์กด์žฌํ•œ๋‹ค๋ฉด) ๋ฐ˜ํ™˜ํ•œ๋‹ค. public static Optional<Operation> fromString(String symbol) { return Optional.ofNullable(stringToEnum.get(symbol)); }
Java
๋ณต์‚ฌ
โ—ฆ
์ „๋žต ์—ด๊ฑฐ ํƒ€์ž… ํŒจํ„ด
โ–ช
์—ด๊ฑฐ ํƒ€์ž… ์ƒ์ˆ˜ ์ผ๋ถ€๊ฐ€ ๊ฐ™์€ ๋™์ž‘์„ ๊ณต์œ ํ•˜๋Š” ๊ฒฝ์šฐ
// ์ฝ”๋“œ 34-9 ์ „๋žต ์—ด๊ฑฐ ํƒ€์ž… ํŒจํ„ด (218-219์ชฝ) enum PayrollDay { MONDAY(WEEKDAY), TUESDAY(WEEKDAY), WEDNESDAY(WEEKDAY), THURSDAY(WEEKDAY), FRIDAY(WEEKDAY), SATURDAY(WEEKEND), SUNDAY(WEEKEND); private final PayType payType; // ์ƒˆ๋กœ์šด ์ƒ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ, ์ž”์—…์ˆ˜๋‹น '์ „๋žต'์„ ์„ ํƒํ•˜๋„๋ก ํ•œ๋‹ค. PayrollDay(PayType payType) { this.payType = payType; } int pay(int minutesWorked, int payRate) { return payType.pay(minutesWorked, payRate); } // ์ „๋žต ์—ด๊ฑฐ ํƒ€์ž… // ์ „๋žต์— ๋”ฐ๋ฅธ ์ž”์—… ์ˆ˜๋‹น ๊ณ„์‚ฐ -> ์ค‘์ฒฉ ์—ด๊ฑฐ ํƒ€์ž…์— ์œ„์ž„ enum PayType { WEEKDAY { int overtimePay(int minsWorked, int payRate) { return minsWorked <= MINS_PER_SHIFT ? 0 : (minsWorked - MINS_PER_SHIFT) * payRate / 2; } }, WEEKEND { int overtimePay(int minsWorked, int payRate) { return minsWorked * payRate / 2; } }; abstract int overtimePay(int mins, int payRate); private static final int MINS_PER_SHIFT = 8 * 60; int pay(int minsWorked, int payRate) { int basePay = minsWorked * payRate; return basePay + overtimePay(minsWorked, payRate); } } public static void main(String[] args) { for (PayrollDay day : values()) System.out.printf("%-10s%d%n", day, day.pay(8 * 60, 1)); } }
Java
๋ณต์‚ฌ
ํ•„์š”ํ•œ ์›์†Œ๋ฅผ ์ปดํŒŒ์ผ ํƒ€์ž„์— ๋‹ค ์•Œ ์ˆ˜ ์žˆ๋Š” ์ƒ์ˆ˜ ์ง‘ํ•ฉ์ด๋ผ๋ฉด ํ•ญ์ƒ ์—ด๊ฑฐํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์ž. ์—ด๊ฑฐ ํƒ€์ž…์— ์ •์˜๋œ ์ƒ์ˆ˜ ๊ฐœ์ˆ˜๊ฐ€ ์˜์›ํžˆ ๊ณ ์ • ๋ถˆ๋ณ€์ผ ํ•„์š”๋Š” ์—†๋‹ค.

ordinal ์ธ๋ฑ์‹ฑ ๋Œ€์‹  EnumMap์„ ์‚ฌ์šฉํ•˜๋ผ

EnumMap
โ€ข
์—ด๊ฑฐ ํƒ€์ž…์„ Key๋กœ ์‚ฌ์šฉํ•˜๋Š” Map
class Plant { enum LifeCycle { ANNUAL, PERENNIAL, BIENNIAL } final String name; final LifeCycle lifeCycle; Plant(String name, LifeCycle lifeCycle) { this.name = name; this.lifeCycle = lifeCycle; } @Override public String toString() { return name; } public static void main(String[] args) { Plant[] garden = { new Plant("๋ฐ”์งˆ", LifeCycle.ANNUAL), new Plant("์บ๋Ÿฌ์›จ์ด", LifeCycle.BIENNIAL), new Plant("๋”œ", LifeCycle.ANNUAL), new Plant("๋ผ๋ฒค๋”", LifeCycle.PERENNIAL), new Plant("ํŒŒ์Šฌ๋ฆฌ", LifeCycle.BIENNIAL), new Plant("๋กœ์ฆˆ๋งˆ๋ฆฌ", LifeCycle.PERENNIAL) }; // ์ฝ”๋“œ 37-1 ordinal()์„ ๋ฐฐ์—ด ์ธ๋ฑ์Šค๋กœ ์‚ฌ์šฉ - ๋”ฐ๋ผ ํ•˜์ง€ ๋ง ๊ฒƒ! (226์ชฝ) Set<Plant>[] plantsByLifeCycleArr = (Set<Plant>[]) new Set[Plant.LifeCycle.values().length]; for (int i = 0; i < plantsByLifeCycleArr.length; i++) plantsByLifeCycleArr[i] = new HashSet<>(); for (Plant p : garden) plantsByLifeCycleArr[p.lifeCycle.ordinal()].add(p); // ๊ฒฐ๊ณผ ์ถœ๋ ฅ for (int i = 0; i < plantsByLifeCycleArr.length; i++) { System.out.printf("%s: %s%n", Plant.LifeCycle.values()[i], plantsByLifeCycleArr[i]); } // ์ฝ”๋“œ 37-2 EnumMap์„ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ์™€ ์—ด๊ฑฐ ํƒ€์ž…์„ ๋งคํ•‘ํ•œ๋‹ค. (227์ชฝ) Map<Plant.LifeCycle, Set<Plant>> plantsByLifeCycle = new EnumMap<>(Plant.LifeCycle.class); for (Plant.LifeCycle lc : Plant.LifeCycle.values()) plantsByLifeCycle.put(lc, new HashSet<>()); for (Plant p : garden) plantsByLifeCycle.get(p.lifeCycle).add(p); System.out.println(plantsByLifeCycle); // ์ฝ”๋“œ 37-3 ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ 1 - EnumMap์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค! (228์ชฝ) System.out.println(Arrays.stream(garden) .collect(groupingBy(p -> p.lifeCycle))); // ์ฝ”๋“œ 37-4 ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ 2 - EnumMap์„ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ์™€ ์—ด๊ฑฐ ํƒ€์ž…์„ ๋งคํ•‘ํ–ˆ๋‹ค. (228์ชฝ) System.out.println(Arrays.stream(garden) .collect(groupingBy(p -> p.lifeCycle, () -> new EnumMap<>(LifeCycle.class), toSet()))); } }
Java
๋ณต์‚ฌ

๋žŒ๋‹ค์™€ ์ŠคํŠธ๋ฆผ

์ต๋ช… ํด๋ž˜์Šค ๋ณด๋‹ค๋Š” ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•˜๋ผ

โ€ข
์ต๋ช… ํด๋ž˜์Šค ๋ฐฉ์‹์€ ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ๊ธธ๊ธฐ ๋•Œ๋ฌธ์—, ์ž๋ฐ”๋Š” ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ์ ํ•ฉํ•˜์ง€ ์•Š์•˜๋‹ค.
โ—ฆ
์ต๋ช… ํด๋ž˜์Šค๋Š” (ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์•„๋‹Œ) ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜๋ผ.
โ€ข
์ž๋ฐ” 8์— ์™€์„œ, ์ถ”์ƒ ๋ฉ”์†Œ๋“œ ํ•˜๋‚˜์งœ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋“ค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋žŒ๋‹ค์‹์„ ์‚ฌ์šฉํ•ด ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.
โ€ข
๋žŒ๋‹ค๋Š” ํ•จ์ˆ˜๋‚˜ ์ต๋ช… ํด๋ž˜์Šค์™€ ๊ฐœ๋…์€ ๋น„์Šทํ•˜์ง€๋งŒ ์ฝ”๋“œ๋Š” ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•˜๋‹ค.
โ—ฆ
์–ด๋–ค ๋™์ž‘์„ ํ•˜๋Š”์ง€๊ฐ€ ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚œ๋‹ค.
โ—ฆ
ํƒ€์ž…์„ ๋ช…์‹œํ•ด์•ผ ์ฝ”๋“œ๊ฐ€ ๋” ๋ช…ํ™•ํ•  ๋•Œ๋ฅผ ์ œ์™ธํ•˜๊ณ , ๋žŒ๋‹ค์˜ ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์€ ์ƒ๋žตํ•˜์ž.
// ํ•จ์ˆ˜ ๊ฐ์ฒด๋กœ ์ •๋ ฌํ•˜๊ธฐ (254-255์ชฝ) public class SortFourWays { public static void main(String[] args) { List<String> words = Arrays.asList(args); // ์ฝ”๋“œ 42-1 ์ต๋ช… ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ํ•จ์ˆ˜ ๊ฐ์ฒด๋กœ ์‚ฌ์šฉ - ๋‚ก์€ ๊ธฐ๋ฒ•์ด๋‹ค! (254์ชฝ) Collections.sort(words, new Comparator<String>() { public int compare(String s1, String s2) { return Integer.compare(s1.length(), s2.length()); } }); System.out.println(words); Collections.shuffle(words); // ์ฝ”๋“œ 42-2 ๋žŒ๋‹ค์‹์„ ํ•จ์ˆ˜ ๊ฐ์ฒด๋กœ ์‚ฌ์šฉ - ์ต๋ช… ํด๋ž˜์Šค ๋Œ€์ฒด (255์ชฝ) Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length())); System.out.println(words); Collections.shuffle(words); // ๋žŒ๋‹ค ์ž๋ฆฌ์— ๋น„๊ต์ž ์ƒ์„ฑ ๋ฉ”์„œ๋“œ(๋ฉ”์„œ๋“œ ์ฐธ์กฐ์™€ ํ•จ๊ป˜)๋ฅผ ์‚ฌ์šฉ (255์ชฝ) Collections.sort(words, comparingInt(String::length)); System.out.println(words); Collections.shuffle(words); // ๋น„๊ต์ž ์ƒ์„ฑ ๋ฉ”์„œ๋“œ์™€ List.sort๋ฅผ ์‚ฌ์šฉ (255์ชฝ) words.sort(comparingInt(String::length)); System.out.println(words); } }
Java
๋ณต์‚ฌ
โ€ข
๋žŒ๋‹ค๋ฅผ ์ด์šฉํ•˜๋ฉด ์—ด๊ฑฐ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ, ์ƒ์ˆ˜๋ณ„๋กœ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
๋‹จ์ˆœํžˆ ๊ฐ ์—ด๊ฑฐ ํƒ€์ž… ์ƒ์ˆ˜์˜ ๋™์ž‘์„ ๋žŒ๋‹ค๋กœ ๊ตฌํ˜„ํ•ด ์ƒ์„ฑ์ž์— ๋„˜๊ธฐ๊ณ , ์ƒ์„ฑ์ž๋Š” ์ด ๋žŒ๋‹ค๋ฅผ ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋กœ ์ €์žฅํ•ด๋‘”๋‹ค.
โ—ฆ
๊ทธ๋Ÿฐ ๋‹ค์Œ, apply ๋ฉ”์†Œ๋“œ์—์„œ ํ•„๋“œ์— ์ €์žฅ๋œ ๋žŒ๋‹ค๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.
// ์ฝ”๋“œ 42-4 ํ•จ์ˆ˜ ๊ฐ์ฒด(๋žŒ๋‹ค)๋ฅผ ์ธ์Šคํ„ด์Šค ํ•„๋“œ์— ์ €์žฅํ•ด ์ƒ์ˆ˜๋ณ„ ๋™์ž‘์„ ๊ตฌํ˜„ํ•œ ์—ด๊ฑฐ ํƒ€์ž… (256-257์ชฝ) public enum Operation { PLUS ("+", (x, y) -> x + y), MINUS ("-", (x, y) -> x - y), TIMES ("*", (x, y) -> x * y), DIVIDE("/", (x, y) -> x / y); private final String symbol; private final DoubleBinaryOperator op; Operation(String symbol, DoubleBinaryOperator op) { this.symbol = symbol; this.op = op; } @Override public String toString() { return symbol; } public double apply(double x, double y) { return op.applyAsDouble(x, y); } }
Java
๋ณต์‚ฌ
โ€ข
๋žŒ๋‹ค๋Š” ์ด๋ฆ„์ด ์—†๊ณ , ๋ฌธ์„œํ™”๋„ ํ•  ์ˆ˜ ์—†๋‹ค.
โ—ฆ
๋”ฐ๋ผ์„œ ์ฝ”๋“œ ์ž์ฒด๋กœ ๋™์ž‘์ด ๋ช…ํ™•ํžˆ ์„ค๋ช…๋˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ฝ”๋“œ ์ค„ ์ˆ˜๊ฐ€ ๋งŽ์•„์ง€๋ฉด ๋žŒ๋‹ค๋ฅผ ์“ฐ์ง€ ๋ง์•„์•ผ ํ•œ๋‹ค.

๋žŒ๋‹ค๋ณด๋‹ค๋Š” ๋ฉ”์†Œ๋“œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ

๋ฉ”์„œ๋“œ ์ฐธ์กฐ ์œ ํ˜•
์˜ˆ
๊ฐ™์€ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ๋žŒ๋‹ค
์ •์ 
Integer::parseInt
str โ†’ Integer.parseInt(str)
ํ•œ์ •์  (์ธ์Šคํ„ด์Šค)
Instant.now()::isAfter
Instant then = Instant.now(); t โ†’ then.isAfter(t)
๋น„ํ•œ์ •์  (์ธ์Šคํ„ด์Šค)
String::toLowerCase
str โ†’ str.toLowerCase()
ํด๋ž˜์Šค ์ƒ์„ฑ์ž
Tree<Map<K, V>::new
() โ†’ new TreeMap<K, V>()
๋ฐฐ์—ด ์ƒ์„ฑ์ž
int[]::new
len โ†’ new int[len]
โ€ข
๋ฉ”์†Œ๋“œ ์ฐธ์กฐ๋Š” ๋žŒ๋‹ค์˜ ๊ฐ„๋‹จ๋ช…๋ฃŒํ•œ ๋Œ€์•ˆ์ด ๋  ์ˆ˜ ์žˆ๋‹ค. ๋ฉ”์†Œ๋“œ ์ฐธ์กฐ ์ชฝ์ด ์งง๊ณ  ๋ช…ํ™•ํ•˜๋‹ค๋ฉด ๋ฉ”์†Œ๋“œ ์ฐธ์กฐ๋ฅผ ์“ฐ๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์„ ๋•Œ๋งŒ ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•˜๋ผ.

ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ผ

โ€ข
ํ•„์š”ํ•œ ์šฉ๋„์— ๋งž๋Š” ๊ฒŒ ์žˆ๋‹ค๋ฉด, ์ง์ ‘ ๊ตฌํ˜„ํ•˜์ง€ ๋ง๊ณ  ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜๋ผ
โ—ฆ
java.util.function
โ—ฆ
ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ๋Œ€๋ถ€๋ถ„์€ ๊ธฐ๋ณธ ํƒ€์ž…๋งŒ ์ œ๊ณตํ•œ๋‹ค.
โ–ช
๊ธฐ๋ณธ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์— ๋ฐ•์‹ฑ๋œ ๊ธฐ๋ณธ ํƒ€์ž…์„ ๋„ฃ์–ด ์‚ฌ์šฉํ•˜์ง€๋Š” ๋ง์ž.
๊ธฐ๋ณธ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค
์ธํ„ฐํŽ˜์ด์Šค
ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜
์˜ˆ
UnaryOperator<T>
T apply(T t)
String::toLowerCase
BinaryOperator<T>
T apply(T t1, T t2)
BigInteger::add
Predicate<T>
boolean test(T t)
Collection::isEmpty
Function<T, R>
R apply(T t)
Arrays::asList
Supplier<T>
T get()
Instant::now
Consumer<T>
void accept(T t)
System.out::println
โ€ข
์ „์šฉ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค
โ—ฆ
์•„๋ž˜๋ฅผ ํ•˜๋‚˜ ์ด์ƒ ๋งŒ์กฑํ•œ๋‹ค๋ฉด ์ „์šฉ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผํ•˜๋Š” ๊ฑด ์•„๋‹Œ์ง€ ๊ณ ๋ฏผํ•ด๋ณด์ž.
โ–ช
์ž์ฃผ ์“ฐ์ด๋ฉฐ, ์ด๋ฆ„ ์ž์ฒด๊ฐ€ ์šฉ๋„๋ฅผ ๋ช…ํ™•ํžˆ ์„ค๋ช…ํ•ด์ค€๋‹ค.
โ–ช
๋ฐ˜๋“œ์‹œ ๋”ฐ๋ผ์•ผํ•˜๋Š” ๊ทœ์•ฝ์ด ์žˆ๋‹ค.
โ–ช
์œ ์šฉํ•œ ๋””ํดํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
์ง์ ‘ ๋งŒ๋“  ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์—๋Š” ํ•ญ์ƒ @FunctionalInterface ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ผ.

์ŠคํŠธ๋ฆผ์—์„œ๋Š” ๋ถ€์ž‘์šฉ ์—†๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ผ

โ€ข
๊ณ„์‚ฐ์„ ์ผ๋ จ์˜ ๋ณ€ํ™˜(transformation)์œผ๋กœ ์žฌ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ
โ—ฆ
๊ฐ ๋ณ€ํ™˜ ๋‹จ๊ณ„๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ์ด์ „ ๋‹จ๊ณ„์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ˆœ์ˆ˜ ํ•จ์ˆ˜
โ–ช
์ˆœ์ˆ˜ ํ•จ์ˆ˜๋ž€? ์˜ค์ง ์ž…๋ ฅ๋งŒ์ด ๊ฒฐ๊ณผ์— ์˜ํ–ฅ์„ ์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งํ•œ๋‹ค.
โ–ช
๋‹ค๋ฅธ ๊ฐ€๋ณ€ ์ƒํƒœ๋ฅผ ์ฐธ์กฐํ•˜์ง€ ์•Š๊ณ , ํ•จ์ˆ˜ ์Šค์Šค๋กœ๋„ ๋‹ค๋ฅธ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค.
โ—ฆ
์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ์— ๊ฑด๋„ค๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด๋Š” ๋ชจ๋‘ ๋ถ€์ž‘์šฉ์ด ์—†์–ด์•ผํ•œ๋‹ค.
โ—ฆ
๋žŒ๋‹ค๊ฐ€ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.
// ๋นˆ๋„ํ‘œ ์ดˆ๊ธฐํ™”์— ์ŠคํŠธ๋ฆผ์„ ์ ์ ˆํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ํ˜น์€ ์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ (277-279์ชฝ) public class Freq { public static void main(String[] args) throws FileNotFoundException { File file = new File(args[0]); // ์ฝ”๋“œ 46-1 ์ŠคํŠธ๋ฆผ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•œ ์ฑ„ API๋งŒ ์‚ฌ์šฉํ–ˆ๋‹ค - ๋”ฐ๋ผ ํ•˜์ง€ ๋ง ๊ฒƒ! (277์ชฝ) Map<String, Long> freq = new HashMap<>(); try (Stream<String> words = new Scanner(file).tokens()) { words.forEach(word -> { freq.merge(word.toLowerCase(), 1L, Long::sum); }); } // ์ฝ”๋“œ 46-2 ์ŠคํŠธ๋ฆผ์„ ์ œ๋Œ€๋กœ ํ™œ์šฉํ•ด ๋นˆ๋„ํ‘œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค. (278์ชฝ) Map<String, Long> freq; try (Stream<String> words = new Scanner(file).tokens()) { freq = words .collect(groupingBy(String::toLowerCase, counting())); } // ์ฝ”๋“œ 46-3 ๋นˆ๋„ํ‘œ์—์„œ ๊ฐ€์žฅ ํ”ํ•œ ๋‹จ์–ด 10๊ฐœ๋ฅผ ๋ฝ‘์•„๋‚ด๋Š” ํŒŒ์ดํ”„๋ผ์ธ (279์ชฝ) List<String> topTen = freq.keySet().stream() .sorted(comparing(freq::get).reversed()) .limit(10) .collect(toList()); } }
Java
๋ณต์‚ฌ
โ€ข
ForEach ์—ฐ์‚ฐ์€ ์ŠคํŠธ๋ฆผ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ•  ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜๊ณ , ๊ณ„์‚ฐํ•˜๋Š” ๋ฐ๋Š” ์‚ฌ์šฉํ•˜์ง€ ๋ง์ž.
โ€ข
์ŠคํŠธ๋ฆผ์„ ์˜ฌ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ˆ˜์ง‘๊ธฐ๋ฅผ ์ž˜ ์•Œ์•„๋‘ฌ์•ผํ•œ๋‹ค.
โ—ฆ
toList
โ—ฆ
toSet
โ—ฆ
toMap
โ—ฆ
groupingBy
โ—ฆ
joining

๋ฉ”์„œ๋“œ

๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์œ ํšจํ•œ์ง€ ๊ฒ€์‚ฌํ•˜๋ผ

โ€ข
์˜ค๋ฅ˜๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ๋นจ๋ฆฌ ๋ฐœ์ƒํ•œ ๊ณณ์—์„œ ์žก์•„์•ผํ•œ๋‹ค.
โ—ฆ
์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒํ•œ ์ฆ‰์‹œ ์žก์ง€ ๋ชปํ•˜๋ฉด ํ•ด๋‹น ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง€๊ณ , ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์ง€์ ์„ ์ฐพ๊ธฐ ์–ด๋ ค์›Œ์ง„๋‹ค.
โ€ข
๋ฉ”์†Œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋˜ํ•œ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค. ๋ฉ”์†Œ๋“œ ๋ชธ์ฒด๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•œ๋‹ค๋ฉด ์ž˜๋ชป๋œ ๊ฐ’์ด ๋„˜์–ด์™”์„ ๋•Œ ์ฆ‰๊ฐ์ ์ด๊ณ  ๊น”๋”ํ•œ ๋ฐฉ์‹์œผ๋กœ ์˜ˆ์™ธ๋ฅผ ๋˜์งˆ ์ˆ˜ ์žˆ๋‹ค.
โ€ข
๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฒ€์‚ฌ๋ฅผ ์ œ๋Œ€๋กœ ํ•˜์ง€ ๋ชปํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ
โ—ฆ
๋ฉ”์†Œ๋“œ๊ฐ€ ์ˆ˜ํ–‰๋˜๋Š” ์ค‘๊ฐ„์— ๋ชจํ˜ธํ•œ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋ฉฐ ์‹คํŒจํ•  ์ˆ˜ ์žˆ๋‹ค.
โ—ฆ
๋ฉ”์†Œ๋“œ๊ฐ€ ์ž˜ ์ˆ˜ํ–‰๋˜์ง€๋งŒ ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ
โ—ฆ
๋ฉ”์†Œ๋“œ๋Š” ๋ฌธ์ œ์—†์ด ์ˆ˜ํ–‰๋์ง€๋งŒ, ์–ด๋– ํ•œ ๊ฐ์ฒด๋ฅผ ์ด์ƒํ•œ ์ƒํƒœ๋กœ ๋งŒ๋“ค์–ด๋†“์•„์„œ ๋ฏธ๋ž˜์˜ ์•Œ ์ˆ˜ ์—†๋Š” ์‹œ์ ์— ์ด ๋ฉ”์†Œ๋“œ์™€๋Š” ๊ด€๋ จ์—†๋Š” ์˜ค๋ฅ˜๋ฅผ ๋‚ผ ๋•Œ โ†’ ์‹คํŒจ ์›์ž์„ฑ์„ ์–ด๊ธฐ๋Š” ๊ฒฐ๊ณผ ๋ฐœ์ƒ
โ€ข
public๊ณผ protected ๋ฉ”์†Œ๋“œ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์ด ์ž˜๋ชป๋์„ ๋•Œ ๋˜์ง€๋Š” ์˜ˆ์™ธ๋ฅผ ๋ฌธ์„œํ™”ํ•ด์•ผํ•œ๋‹ค.
โ—ฆ
@throws ์ž๋ฐ”๋… ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
โ—ฆ
๋ณดํ†ต์€ IllegalArgumentException, IndexOutOfBoundsException, NullPointerException ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค.
โ—ฆ
๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ œ์•ฝ์„ ๋ฌธ์„œํ™”ํ•œ๋‹ค๋ฉด, ๊ทธ ์ œ์•ฝ์„ ์–ด๊ฒผ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋„ ํ•จ๊ป˜ ๊ธฐ์ˆ ํ•ด์•ผํ•œ๋‹ค.
/** * (ํ˜„์žฌ ๊ฐ’ mod m) ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” * ํ•ญ์ƒ ์Œ์ด ์•„๋‹Œ BigInteger๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ์ ์—์„œ remainder ๋ฉ”์„œ๋“œ์™€ ๋‹ค๋ฅด๋‹ค. * * @param m ๊ณ„์ˆ˜(์–‘์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค.) * @return ํ˜„์žฌ ๊ฐ’ mod m * @throws ArithmeticException m์ด 0๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์œผ๋ฉด ๋ฐœ์ƒํ•œ๋‹ค. */ public BigInteger mod(BigInteger m) { if (m.signum() <= 0) throw new ArithmeticException("๊ณ„์ˆ˜(m)์€ ์–‘์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. " + m); ... // ๊ณ„์‚ฐ ์ˆ˜ํ–‰ }
Java
๋ณต์‚ฌ
โ—ฆ
๋ชจ๋“  public ๋ฉ”์„œ๋“œ์— ์ ์šฉ๋˜๋Š” ์˜ˆ์™ธ์ธ ๊ฒฝ์šฐ, ํด๋ž˜์Šค ๋ ˆ๋ฒจ ์ฃผ์„์„ ๊ธฐ์ˆ ํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๊น”๋”ํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค.
โ—ฆ
์œ„์˜ ์˜ˆ์ œ์—์„œ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ null์ธ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•˜๋Š” NullPointerException์— ๋Œ€ํ•œ ์„ค๋ช…์€ BigInteger ํด๋ž˜์Šค ๋ ˆ๋ฒจ์— ๊ธฐ์ˆ ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ„ ๋ฉ”์†Œ๋“œ์—๋Š” ํ•ด๋‹น ๋‚ด์šฉ์ด ๊ธฐ์ˆ ๋˜์–ด์žˆ์ง€ ์•Š๋‹ค.
โ€ข
requireNonNull ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•œ Null ๊ฒ€์‚ฌ (Java7~)
โ—ฆ
java.util.Objects.requireNonNull
โ—ฆ
null ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜๋™์œผ๋กœ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
โ—ฆ
์›ํ•˜๋Š” ์˜ˆ์™ธ๋ฉ”์„ธ์ง€๋„ ์ง€์ • ๊ฐ€๋Šฅํ•˜๋‹ค.
โ—ฆ
์ž…๋ ฅ์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” ๋™์‹œ์— null ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
this.strategy = Objects.requireNonNull(strategy, "์ „๋žต");
Java
๋ณต์‚ฌ
โ€ข
๋ฉ”์†Œ๋“œ ์‹คํ–‰ ์ „ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฒ€์‚ฌ ์˜ˆ์™ธ ์ผ€์ด์Šค
โ—ฆ
์œ ํ˜€์„ฑ ๊ฒ€์‚ฌ์˜ ๋น„์šฉ์ด ์ง€๋‚˜์น˜๊ฒŒ ๋†’๊ฑฐ๋‚˜, ์‹ค์šฉ์ ์ด์ง€ ์•Š์„ ๋•Œ
โ—ฆ
๊ณ„์‚ฐ ๊ด€์ •์—์„œ ์•”๋ฌต์ ์œผ๋กœ ๊ฒ€์‚ฌ๊ฐ€ ์ˆ˜ํ–‰๋˜๋Š” ๊ฒฝ์šฐ
โ–ช
Collection.sort(List)๋Š” ๋‘ ์›์†Œ๋ฅผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์ธ์ง€ ์ •๋ ฌ ๊ณผ์ •์—์„œ ๋น„๊ตํ•œ๋‹ค. ๋น„๊ตํ•  ์ˆ˜ ์—†๋Š” ํƒ€์ž…์ด๋ผ๋ฉด ClassCastException์ด ๋ฐœ์ƒํ•œ๋‹ค.
โ–ช
์ •๋ ฌ์— ์•ž์„œ ์›์†Œ๋“ค์ด ์ƒํ˜ธ ๋น„๊ต๋  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์ธ์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋Š” ์‹ค์ต์ด ์—†๋‹ค.

์ ์‹œ์— ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค๋ผ

โ€ข
ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ถˆ๋ณ€์‹์„ ๊นจ๋œจ๋ฆฌ๋ ค ํ˜ˆ์•ˆ์ด ๋˜์–ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ๋ฐฉ์–ด์ ์œผ๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ•ด์•ผ ํ•œ๋‹ค.
โ—ฆ
ํด๋ž˜์Šค์˜ ์™ธ๋ถ€์—์„œ ๋‚ด๋ถ€๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์„ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋ผ.
โ€ข
๋ถˆ๋ณ€์‹์„ ์ง€ํ‚ค์ง€ ๋ชปํ•œ ์˜ˆ
// ์š”๊ตฌ์‚ฌํ•ญ : ๊ธฐ๊ฐ„์„ ํ‘œํ˜„ํ•˜๋Š” ๋‹ค์Œ ํด๋ž˜์Šค๋Š” ํ•œ๋ฒˆ ๊ฐ’์ด ์ •ํ•ด์ง€๋ฉด ๋ณ€ํ•˜์ง€ ์•Š๋„๋ก ํ•  ์ƒ๊ฐ์ด์—ˆ๋‹ค. // ์ฝ”๋“œ 50-1 ๊ธฐ๊ฐ„์„ ํ‘œํ˜„ํ•˜๋Š” ํด๋ž˜์Šค - ๋ถˆ๋ณ€์‹์„ ์ง€ํ‚ค์ง€ ๋ชปํ–ˆ๋‹ค. (302-305์ชฝ) public final class Period { private final Date start; private final Date end; /** * @param start ์‹œ์ž‘ ์‹œ๊ฐ * @param end ์ข…๋ฃŒ ์‹œ๊ฐ. ์‹œ์ž‘ ์‹œ๊ฐ๋ณด๋‹ค ๋’ค์—ฌ์•ผ ํ•œ๋‹ค. * @throws IllegalArgumentException ์‹œ์ž‘ ์‹œ๊ฐ์ด ์ข…๋ฃŒ ์‹œ๊ฐ๋ณด๋‹ค ๋Šฆ์„ ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค. * @throws NullPointerException start๋‚˜ end๊ฐ€ null์ด๋ฉด ๋ฐœ์ƒํ•œ๋‹ค. */ public Period(Date start, Date end) { if (start.compareTo(end) > 0) throw new IllegalArgumentException( start + "๊ฐ€ " + end + "๋ณด๋‹ค ๋Šฆ๋‹ค."); this.start = start; this.end = end; } public Date start() { return start; } public Date end() { return end; } public String toString() { return start + " - " + end; } }
Java
๋ณต์‚ฌ
โ—ฆ
Date๊ฐ€ ๊ฐ€๋ณ€์ด๊ธฐ ๋•Œ๋ฌธ์— Period ์ธ์Šคํ„ด์Šค์˜ ๋‚ด๋ถ€๋ฅผ ๊ณต๊ฒฉํ•  ์ˆ˜ ์žˆ๋‹ค.
Date start = new Date(); Date end = new Date(); Period p = new Period(start, end); end.setYear(78); // p์˜ ๋‚ด๋ถ€๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค!!
Java
๋ณต์‚ฌ
โ—ฆ
์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋Š” Java8 ์ดํ›„๋กœ๋Š” ์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.
โ–ช
Date ๋Œ€์‹  ๋ถˆ๋ณ€์ธ Instant๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. (ํ˜น์€ LocalDateTime์ด๋‚˜, ZonedDateTime์„ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค.)
โ–ช
Date๋Š” ๋‚ก์€ API์ด๋‹ˆ ์ƒˆ๋กœ์šด ์ฝ”๋“œ๋ฅผ ์ž˜์„ฑํ•  ๋•Œ๋Š” ๋”์ด์ƒ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
โ€ข
์™ธ๋ถ€ ๊ณต๊ฒฉ์œผ๋กœ๋ถ€ํ„ฐ ์ธ์Šคํ„ด์Šค์˜ ๋‚ด๋ถ€๋ฅผ ๋ณดํ˜ธํ•˜๋ ค๋ฉด, ์ƒ์„ฑ์ž์—์„œ ๋ฐ›์€ ๊ฐ€๋ณ€ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ๊ฐ์„ ๋ฐฉ์–ด์ ์œผ๋กœ ๋ณต์‚ฌํ•ด์•ผํ•œ๋‹ค.
โ—ฆ
Period ์ธ์Šคํ„ด์Šค ์•ˆ์—์„œ๋Š” ์›๋ณธ์ด ์•„๋‹Œ ๋ณต์‚ฌ๋ณธ์„ ์‚ฌ์šฉํ•œ๋‹ค.
// ์ฝ”๋“œ 50-3 ์ˆ˜์ •ํ•œ ์ƒ์„ฑ์ž - ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ ๋‹ค. (304์ชฝ) public Period(Date start, Date end) { this.start = new Date(start.getTime()); this.end = new Date(end.getTime()); if (this.start.compareTo(this.end) > 0) throw new IllegalArgumentException( this.start + "๊ฐ€ " + this.end + "๋ณด๋‹ค ๋Šฆ๋‹ค."); }
Java
๋ณต์‚ฌ
โ—ฆ
๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•˜๊ธฐ ์ „์— ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค๊ณ , ์ด ๋ณต์‚ฌ๋ณธ์œผ๋กœ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•œ ์ ์— ์ฃผ๋ชฉํ•˜์ž.
โ—ฆ
Date.clone() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€์ ์„ ์ฃผ๋ชฉํ•˜์ž.
โ–ช
Date๋Š” final์ด ์•„๋‹ˆ๋ฏ€๋กœ clone์ด Date๊ฐ€ ์ •์˜ํ•œ ๊ฒŒ ์•„๋‹ ์ˆ˜ ์žˆ๋‹ค.
โ–ช
๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์ œ3์ž์— ์˜ํ•ด ํ™•์žฅ๋  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์ด๋ผ๋ฉด ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค ๋•Œ clone์„ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค.
โ—ฆ
์ ‘๊ทผ์ž ๋ฉ”์†Œ๋“œ๊ฐ€ ๋‚ด๋ถ€์˜ ๊ฐ€๋ณ€ ์ •๋ณด๋ฅผ ์ง์ ‘์ ์œผ๋กœ ๋“œ๋Ÿฌ๋‚ธ๋‹ค.
โ–ช
์ ‘๊ทผ์ž๊ฐ€ ๊ฐ€๋ณ€ ํ•„๋“œ์˜ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ณธ์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•œ๋‹ค.
// ์ฝ”๋“œ 50-5 ์ˆ˜์ •ํ•œ ์ ‘๊ทผ์ž - ํ•„๋“œ์˜ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ณธ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. (305์ชฝ) public Date start() { return new Date(start.getTime()); } public Date end() { return new Date(end.getTime()); }
Java
๋ณต์‚ฌ
โ€ข
๋ชจ๋“  ์ž‘์—…์—์„œ ๋˜๋„๋ก ๋ถˆ๋ณ€ ๊ฐ์ฒด๋“ค์„ ์กฐํ•ฉํ•ด ๊ฐ์ฒด๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ํ•  ์ผ์ด ์ค„์–ด๋“ ๋‹ค.
โ€ข
๋ณต์‚ฌ ๋น„์šฉ์ด ๋„ˆ๋ฌด ํฌ๊ฑฐ๋‚˜, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ทธ ์š”์†Œ๋ฅผ ์ž˜๋ชป ์ˆ˜์ •ํ•  ์ผ์ด ์—†์Œ์„ ์‹ ๋ขฐํ•œ๋‹ค๋ฉด ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋Œ€์‹  ํ•ด๋‹น ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ์ˆ˜์ •ํ–ˆ์„ ๋•Œ์˜ ์ฑ…์ž„์ด ํด๋ผ์ด์–ธํŠธ์— ์žˆ์Œ์„ ๋ฌธ์„œ์— ๋ช…์‹œํ•˜์ž.

null์ด ์•„๋‹Œ, ๋นˆ ์ปฌ๋ ‰์…˜์ด๋‚˜ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋ผ

์˜ต์…”๋„ ๋ฐ˜ํ™˜์€ ์‹ ์ค‘ํ•˜๊ฒŒ ํ•˜๋ผ

์ผ๋ฐ˜์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์›์น™

... ์ž‘์„ฑ์ค‘ @2/7/2022