ν΄λΌμ΄μΈνΈκ° μ°λ¦¬μ λΆλ³μμ κΉ¨λ¨λ¦¬λ € νμμ΄ λμ΄ μλ€κ³ κ°μ νκ³ λ°©μ΄μ μΌλ‘ νλ‘κ·Έλλ°ν΄μΌ νλ€ !
λΆλ³μ (λΆλ³μμ±) : μ΄λ€ κ°μ²΄μ μνκ° νλ‘κ·Έλλ¨Έμ μλμ λ§κ² μ μ μλμ΄ μλ€κ³ νλ¨ν μ μλ κΈ°μ€μ μ 곡νλ μμ±
λΆλ³μμ κΉ¨λ¨λ¦¬λ κ²½μ° 1) κ°μ²΄μ νλ½μμ΄ μΈλΆμμ μμ±μλ‘ κ°μ²΄ λ΄λΆμ κ°μ λ³κ²½νλ κ²½μ°
public final class Period {
private final Date start;
private final Date end;
public Period(Date start, Date end) {
if (start.compareTo(end) > 0) {
throw new IllegalStateException(start + "κ° " + end + " λ³΄λ€ λ¦μ μ μμ΅λλ€.");
}
this.start = start;
this.end = end;
}
public Date getStart() {
return start;
}
public Date getEnd() {
return end;
}
}
- λΆλ³ ν΄λμ€λ₯Ό μν΄ final ν΄λμ€λ‘ λ§λ€κ³ ,
- λͺ¨λ νλλ₯Ό final λ‘ λ§λ€μλ€.
- κ·Έλ¦¬κ³ μμ μκ°μ΄ λ μκ°λ³΄λ€ μ΅κ·ΌμΈ κ²½μ°λ μμΈλ‘ λ§λλ€.
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
Date start = new Date();
Date end = new Date();
Period p = new Period(start, end);
end.setTime(1000000000);
System.out.println("μμμκ° : " + dateFormat.format(p.getStart()) + "\nλμκ° : " + dateFormat.format(p.getEnd()));
- νμ§λ§ Date ν΄λμ€κ° κ°λ³ν΄λμ€λΌλ μ΄μ λ‘, μμ λΆλ³μμ μ½κ² κΉ¨μ§λ€.
- λ μ§λ₯Ό ννν λ JAVA 8 λ²μ μ μκΈ΄ Instant λΆλ³ ν΄λμ€λ₯Ό μ¬μ©νλ©΄ ν΄κ²°ν μ μλ€.
- μΈμλ LocalDateTime, ZoneDateTime μ μ¬μ©ν μ μλ€.
Date ν΄λμ€λ λ‘μ API μ΄λ μ¬μ©νμ§ λ§μ.
public class Date {...}
public final class Instant {...}
public final class LocalDateTime {...}
public final class ZonedDateTime {...}
λΆλ³μμ κΉ¨λ¨λ¦¬λ κ²½μ° 2) κ°μ²΄μ νλ½μμ΄ μΈλΆμμ setter λ‘ κ°μ²΄ λ΄λΆμ κ°μ λ³κ²½νλ κ²½μ°
Date start = new Date();
Date end = new Date();
Period p1 = new Period(start, end);
p1.end().setYear(78);
μ΄λ―Έ κ°λ°λ ꡬνμ Date κ°μ ν΄λμ€λ₯Ό μ°κ³ μλ€λ©΄? - 맀κ°λ³μμμ λ°μ κ°λ³ 맀κ°λ³μ κ°κ°μ λ°©μ΄μ 볡μ¬νλΌ.
// μμ±μ
public DefensiveCopiedPeriod(Date start, Date end) {
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
if (start.compareTo(end) > 0) {
throw new IllegalStateException(start + "κ° " + end + " λ³΄λ€ λ¦μ μ μμ΅λλ€.");
}
}
Date start = new Date();
Date end = new Date();
Period p1 = new Period(start, end);
DefensiveCopiedPeriod p2 = new DefensiveCopiedPeriod(start, end);
end.setTime(1000000000);
System.out.println("<λ°©μ΄μ λ³΅μ¬ μν¨>\n" + "μμμκ° : " + dateFormat.format(p1.getStart()) + "\nλμκ° : " + dateFormat.format(p1.getEnd()));
System.out.println("<λ°©μ΄μ λ³΅μ¬ ν¨>\n" + "μμμκ° : " + dateFormat.format(p2.getStart()) + "\nλμκ° : " + dateFormat.format(p2.getEnd()));
- λ°©μ΄μ 볡μ¬λ₯Ό νλ©΄ μμ±μλ‘ λκΈ°λ κ°λ³κ°μ²΄λ₯Ό μ¬μ©νμ¬ μΈμ€ν΄μ€λ₯Ό λ§λ€μ§ μκ³ μλ‘μ΄ κ°μ²΄λ₯Ό λ§λλ―λ‘ μμ 곡격μμ μμ νλ€.
- λ©ν° μ€λ λ νκ²½μμ, μλ³Έ κ°μ²΄μ μ ν¨μ±μ κ²μ¬νλ μ°°λμ λ€λ₯Έ μ€λ λκ° μλ³Έ κ°μ²΄λ₯Ό λ³κ²½ν μνμ΄ μλ€.
- λ°λμ λ°©μ΄μ λ³΅μ¬ ν, μ ν¨μ± κ²μ¬νλ μμλ‘ μμ±ν΄μΌ νλ€.
- Time-Of-Check/Time-Of-Use 곡격 (TOCTOU 곡격)
- μμ±μμμ μλ‘μ΄ κ°μ²΄λ‘ 볡μ¬κ° μλ clone() μ μλλ€.
public DefensiveCopiedPeriod(Date start, Date end) {
this.start = (Date) start.clone();
this.end = (Date) end.clone();
if (start.compareTo(end) > 0) {
throw new IllegalStateException(start + "κ° " + end + " λ³΄λ€ λ¦μ μ μμ΅λλ€.");
}
}
- Date λ κ°λ³ ν΄λμ€κΈ° λλ¬Έμ, μ΄λ₯Ό μμνλ ν΄λμ€λ₯Ό λ§λ€ μ μμ΅λλ€.
- μ μμ μΈ λ¦¬μ€νΈλ₯Ό λ§λ€κ³ , clone λ©μλλ₯Ό μ€λ²λΌμ΄λ©νμ¬ κ°μ²΄ μ°Έμ‘°λ₯Ό 보κ΄ν©λλ€.
public class SubDate extends Date implements Cloneable {
private List<Date> hackersList = new ArrayList<>();
public List<Date> getHackersList() {
return hackersList;
}
@Override
public Object clone() {
Date badDate = (Date) super.clone();
hackersList.add(badDate);
return badDate;
}
}
- μλμ κ°μ΄ μ μμ μΌλ‘ λ§λ νμ ν΄λμ€λ₯Ό SubDate λ₯Ό λ£μ΄μ κ°μ²΄ μ°Έμ‘°λ₯Ό μ»μ΄μ¬ μ μμ΅λλ€.
- μ΄λ κ² λλ©΄ μ»μ΄μ¨ μ°Έμ‘°λ‘ λΆλ³μμ κΉ¨λ¨λ¦΄ μ μμ΅λλ€.
Date start2 = new SubDate();
Date end2 = new SubDate();
DefensiveCopiedPeriod period = new DefensiveCopiedPeriod(start2, end2);
List<Date> hackersList = ((SubDate) (period.getEnd())).getHackersList();
hackersList.get(0).setTime(100000);
System.out.println("<λ°©μ΄μ λ³΅μ¬ ν¨>\n" + "μμμκ° : " + dateFormat.format(period.getStart()) + "\nλμκ° : " + dateFormat.format(period.getEnd()));
맀κ°λ³μ (μ΄λ² μμμλ Date) κ° λ€λ₯Έ μ¬λμ μν΄ νμ₯λ μ μλ νμ μ΄λ©΄, clone() μΌλ‘ λ°©μ΄μ 볡μ¬λ₯Ό νλ©΄ μλλ€ !
- Period κ° κ°μ§ Date κ° μμ±μμμ λ€μ΄μμ new Date() λ‘ λ§λ λ€.
- λ°λΌμ νμ₯λ νμ μ΄ μλ Date μμ΄ νμ€νκΈ° λλ¬Έμ΄λ€.
λ°©μ΄μ 볡μ¬μ λ€λ₯Έ λͺ©μ - κ°μ²΄κ° μ΄ν λ³κ²½λμμ λ, νλ‘κ·Έλ¨μ΄ λ¬Έμ κ° μκΈΈ μ μλμ§ κ²ν νλΌ !
- μλ₯Ό λ€μ΄ κ°μ²΄κ° λ€λ₯Έ κ³³μμ Map μ Key κ°μΌλ‘ μ°μ΄κ³ μμλ€λ©΄,
- κ°μ²΄κ° λ³κ²½λμμλ κ·Έ Map μ λΆλ³μμ΄ κΉ¨μ§κ³ , λ¬Έμ κ° μκΈ΄λ€.
λ³΅μ¬ λΉμ©μ΄ λ무 ν¬κ±°λ, ν΄λΌμ΄μΈνΈκ° κ·Έ μμλ₯Ό μμ ν μΌμ΄ μλ€λ κ²μ΄ νμ€νλ€λ©΄ ?
- λ°©μ΄μ 볡μ¬λ₯Ό μλ΅νλ€.
- λ¬Έμνμμ μ± μμ΄ ν΄λΌμ΄μΈνΈμ μμμ λͺ μνλ€.