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



