{% hint style="info" %} λΆλ³ ν΄λμ€λ κ°λ³ ν΄λμ€λ³΄λ€ μ€κ³νκ³ κ΅¬ννκ³ μ¬μ©νκΈ° μ¬μ°λ©°, μ€λ₯κ° μκΈΈ μ¬μ§λ μ κ³ ν¨μ¬ μμ νλ€. {% endhint %}
μΈμ€ν΄μ€μ λ΄λΆ κ°μ μμ ν μ μλ ν΄λμ€λ€. λΆλ³ μΈμ€ν΄μ€μ κ°μ§λ μ 보λ κ³ μ λμ΄ κ°μ²΄κ° νκ΄΄λλ μκ°κΉμ§ μ λ λ¬λΌμ§μ§ μλλ€.
νμ§λ§ λΆλ³ κ°μ²΄μ μ€μμ±μ΄ λλλλ©° setter μ¬μ©μ μ§μνλ νλ¦μΌλ‘ λ³νλμλ€.
Date ν΄λμ€λ λ€μκ³Ό κ°μ λ§μ λ³κ²½ λ©μλλ€μ΄ μμλλ°...
νμ§λ§ λ³κ²½ν μ μκ³ , λ©ν° μ€λ λμμλ μμ ν λ μ§ & μκ° κ΄λ ¨ ν΄λμ€κ° νμνλ€.
κ·Έλμ λ±μ₯ν LocalDate
ν΄λμ€λ setter λ₯Ό μ 곡νμ§ μλ λΆλ³ ν΄λμ€ μ
π§ λ§μ½ κ°μ²΄μ μνλ₯Ό λ³κ²½νλ λ©μλλ₯Ό μ 곡νλ€λ©΄?
public class Person {
private String name;
public Person(final String name) {
this.name = name;
}
public String name() {
return name;
}
/* λ³κ²½μ */
public void setName(final String name) {
this.name = name;
}
}
λ°κΉ₯μμ κ°μ²΄μ μνλ₯Ό λ³κ²½ν μ μμ
public class Main {
public static void main(String[] args) {
Person boki = new Person("boki ");
System.out.println(boki .name());
boki.setName("lotto");
System.out.println(boki.name()); // lotto
}
}
ν΄λμ€λ₯Ό λΆλ³μΌλ‘ λ§λ€ μ μμ
νμ ν΄λμ€μμ λΆμ£Όμνκ² νΉμ λμ μλλ‘ κ°μ²΄μ μνλ₯Ό λ³νκ² λ§λλ μ¬νλ₯Ό λ§μμ€λ€. μμμ λ§λ λνμ μΈ λ°©λ²μ ν΄λμ€λ₯Ό final
λ‘ μ μΈνλ κ²μ΄λ€.
μμμ λ°©λ²μ λ§λ λ°©λ² 2κ°μ§
- ν΄λμ€λ₯Ό finalλ‘ μ€μ νλ κ²
ν΄λμ€λ₯Ό μμλ°μ μ μλ€λ©΄, ν΄λΉ ν΄λμ€λ κ°μ΄ λ³κ²½λ μ μμμ μλ―Ένλλ°, μ΄κ² μ΄λ»κ² κ°λ₯ν κΉλ₯Ό finalλ‘ νμ§ μμμ λλ₯Ό 보면!
public class Animal {
private String type;
public Animal(final String type) {
this.type = type;
}
public String type() {
return type; // type() λ©μλλ₯Ό ν΅ν΄ type νλμ κ°μ λ°ν
}
}
setterλ₯Ό μ κ±°ν¨μΌλ‘μ¨ κ°μ²΄μ μνλ₯Ό λ³κ²½νλ λ©μλ μ 곡 νμ§ μλλ‘ μμ
{% hint style="success" %} κ·Έλ λ€λ©΄ κ°μ λ°κΎΈλ €λ©΄? privateλ‘ λ΄λΆ κ° λ°κΏ μλ μμΌλ λ°λ κ²μ²λΌ μ¬μ© κ°λ₯ {% endhint %}
Dog
ν΄λμ€ (Animalμ μμ):
public class Dog extends Animal {
private String type;
// type νλλ₯Ό privateμΌλ‘ μ μΈνκ³ , μμ±μλ₯Ό ν΅ν΄ μ΄κΈ°ν
public Dog(final String type) {
super(type);
this.type = "Unknown Type " + type; // μμ±μμμ this.typeμ "Unknown Type " λ¬Έμμ΄μ λΆμ¬ μ΄κΈ°ν
}
@Override
public String type() {
return "Dog Type: " + this.type;
}
}
Main
ν΄λμ€:
public class Main {
// animal.type()μ νΈμΆνλ©΄ Dog ν΄λμ€μμ μ€λ²λΌμ΄λ©λ type() λ©μλκ° νΈμΆ
public static void main(String[] args) {
Animal animal = new Dog("Bulldog");
System.out.println(animal.type());
}
}
Dog Type: Unknown Type Bulldog
- μμμ ν΅ν λμ λ³κ²½:
Dog
ν΄λμ€λAnimal
ν΄λμ€λ₯Ό μμλ°μtype()
λ©μλλ₯Ό μ€λ²λΌμ΄λ©νκ³ μλ€. μ΄λ₯Ό ν΅ν΄ λΆλͺ¨ ν΄λμ€μ λμμ μμ ν΄λμ€μμ λ³κ²½ν μ μμμ 보μ¬μ€λ€. - νλ μ¨κΉ(Field Hiding):
Dog
ν΄λμ€μμtype
νλλ₯Ό λ€μ μ μΈν¨μΌλ‘μ¨, λΆλͺ¨ ν΄λμ€μtype
νλλ₯Ό κ°λ¦¬κ³ μλ€. μ΄λ μ’μ μ€κ³κ° μλλ©°, νΌλμ μ΄λν μ μλ€. - λΆλ³μ± μλ° κ°λ₯μ±:
Animal
ν΄λμ€λ μμ μ νλλ₯Όprivate
μΌλ‘ μ μΈνκ³ μμ§λ§, μμμ ν΅ν΄ μμ ν΄λμ€μμ λμμ΄ λ³κ²½λ μ μλ€. λ°λΌμ λΆλ³μ±μ 보μ₯νκΈ° μν΄μλ ν΄λμ€μ μμμ λ§κ±°λ(final ν΄λμ€), νλλ₯Όfinal
λ‘ μ μΈνλ λ±μ μ‘°μΉκ° νμνλ€.
- ν΄λμ€λ₯Ό
final
λ‘ μ μΈνμ¬ μμμ κΈμ§
public final class Animal {
// ν΄λμ€ λ΄μ©
}
- νλλ₯Ό
private final
λ‘ μ μΈνμ¬ νλκ° ν λ² μ΄κΈ°νλ ν λ³κ²½λμ§ μλλ‘ νλ€.
private final String type;
- λ©μλλ₯Ό
final
λ‘ μ μΈνμ¬ μ€λ²λΌμ΄λ©μ λ°©μ§νλ€.
public final String type() {
return type;
}
public final class Animal {
private final String type;
public Animal(final String type) {
this.type = type;
}
public String getType() {
return type;
}
}
μ΄λ κ² μμ νλ©΄ Animal
ν΄λμ€λ₯Ό μμν μ μμΌλ©°, νλλ λ³κ²½ν μ μκ² λμ΄ λΆλ³μ±μ΄ μ μ§λλ€.
{% hint style="warning" %} μ¬κΈ°μ μλ¬Έ : μ΄λ κ²νλ©΄ν΄λΌμ΄μΈνΈκ° κ²°κ΅ μμ λ λͺ»ν΄μ λΆλ³ ν΄λμ€λ μ€νλ € μμ’μκ² μλκ°? {% endhint %}
λ΅λ³ : λΆλ³ ν΄λμ€λ₯Ό μ¬μ©νλ©΄ ν΄λΌμ΄μΈνΈκ° κ°μ²΄μ μνλ₯Ό μ§μ μμ ν μ μκΈ° λλ¬Έμ λΆνΈνλ€κ³ λλ μ μμ΅λλ€. νμ§λ§ λΆλ³ ν΄λμ€λ μ¬λ¬ κ°μ§ μ₯μ μ μ 곡νλ©°, μ΄λ¬ν μ΄μ μ ν΅ν΄ μ½λμ μμ μ±κ³Ό μ λ’°μ±μ λμΌ μ μμ΅λλ€.
λΆλ³ ν΄λμ€μμλ κ°μ²΄μ μνλ₯Ό μ§μ λ³κ²½ν μ μμ§λ§, λ³κ²½λ κ°μ κ°μ§ μλ‘μ΄ κ°μ²΄λ₯Ό μμ±νμ¬ λ°ννλ λ°©λ²μ μ¬μ©ν μ μμ΅λλ€. μ΄λ ν¨μν νλ‘κ·Έλλ°μμ νν μ¬μ©νλ ν¨ν΄μΌλ‘, κ°μ²΄μ λΆλ³μ±μ μ μ§νλ©΄μ νμν λ³κ²½μ κ°λ₯νκ² ν©λλ€.
μμ: Animal
ν΄λμ€μ λ³κ²½ λ©μλ μΆκ°
public final class Animal {
private final String type;
public Animal(final String type) {
this.type = type;
}
public String getType() {
return type;
}
// μλ‘μ΄ νμ
μ Animal κ°μ²΄λ₯Ό μμ±νμ¬ λ°ννλ λ©μλ
public Animal withType(String newType) {
return new Animal(newType);
}
}
μ¬μ© λ°©λ²
public class Main {
public static void main(String[] args) {
Animal animal = new Animal("Cat");
// κΈ°μ‘΄ κ°μ²΄λ₯Ό μμ νλ κ²μ΄ μλλΌ μλ‘μ΄ κ°μ²΄λ₯Ό μμ±
Animal newAnimal = animal.withType("Dog");
System.out.println(animal.getType()); // μΆλ ₯: Cat
System.out.println(newAnimal.getType()); // μΆλ ₯: Dog
}
}
μ μμμμ animal
κ°μ²΄λ μ¬μ ν "Cat"
νμ
μ μ μ§νλ©°, newAnimal
μ "Dog"
νμ
μ κ°λ μλ‘μ΄ κ°μ²΄μ
λλ€. μ΄μ²λΌ λΆλ³ κ°μ²΄λ₯Ό μ¬μ©νλ©΄ μλ³Έ κ°μ²΄μ μνλ₯Ό λ³κ²½νμ§ μμΌλ©΄μλ μνλ κ°μ κ°μ§ κ°μ²΄λ₯Ό μμ±ν μ μμ΅λλ€.
λΆλ³ ν΄λμ€λ λ€μκ³Ό κ°μ μ΄μ λ‘ μ μ©ν©λλ€:
- μμ νκ³ μ λ’°ν μ μλ μ½λ μμ±: μν λ³κ²½μ λ°λ₯Έ μκΈ°μΉ μμ λ²κ·Έλ₯Ό μ€μΌ μ μμ΅λλ€.
- λ©ν°μ€λ λ νκ²½μμμ μμ μ± ν보: λκΈ°ν μμ΄λ μ€λ λ μμ μ±μ 보μ₯ν©λλ€.
- μ μ§λ³΄μ μ©μ΄μ±: κ°μ²΄μ μνκ° λ³νμ§ μμΌλ―λ‘ μ½λμ 볡μ‘μ±μ΄ κ°μν©λλ€.
{% hint style="danger" %} κ²°κ΅ μ¬λ¬κ°μ κ°μ²΄λ₯Ό μμ±νλ 건 λ©λͺ¨λ¦¬λ₯Ό λ§μ΄ μ°¨μ§νλ κ²κ³Όλ μ°κ΄μ΄ μλκ±° μλκ°? {% endhint %}
λ΅λ³ : λ§μ΅λλ€. λΆλ³ κ°μ²΄λ₯Ό μ¬μ©ν λ λ³κ²½ν λλ§λ€ μλ‘μ΄ κ°μ²΄λ₯Ό μμ±νλ―λ‘, λ©λͺ¨λ¦¬ μ¬μ©λμ΄ μ¦κ°ν μ μλ€λ μ°λ €κ° μμ΅λλ€. μ΄λ λΆλ³ ν΄λμ€μ λ¨μ μ€ νλλ‘ μΈκΈλκΈ°λ ν©λλ€. νμ§λ§ μ€μ λ‘λ μ΄λ¬ν λ©λͺ¨λ¦¬ μ¬μ© μ¦κ°κ° μ¬κ°ν λ¬Έμ λ₯Ό μΌμΌν€λ κ²½μ°λ λλ λλ€.
- λΆλ³ κ°μ²΄ μ¬μ©μΌλ‘ μΈν λ©λͺ¨λ¦¬ μ¬μ© μ¦κ°λ μ‘΄μ¬νμ§λ§, νλ JVMμ μ΅μ νμ νλ‘κ·Έλλ° κΈ°λ²μ ν΅ν΄ κ·Έ μν₯μ μ΅μνν μ μμ΅λλ€.
- λΆλ³ ν΄λμ€μ μ₯μ μΈ μμ μ±, μ€λ λ μμ μ±, μ μ§λ³΄μμ± ν₯μμ λ©λͺ¨λ¦¬ μ¬μ©λ μ¦κ°λ‘ μΈν λ¨μ μ μμνκ³ λ λ¨μ΅λλ€.
- μ€μ κ°λ°μμλ λΆλ³ κ°μ²΄λ₯Ό μ°μ μ μΌλ‘ μ¬μ©νκ³ , λ©λͺ¨λ¦¬ μ¬μ©μ΄ λ¬Έμ κ° λλ λΆλΆμ νν΄ μ΅μ ν κΈ°λ²μ μ μ©νλ κ²μ΄ μ’μ΅λλ€.
- public μ μ ν©ν°λ¦¬ λ©μλλ₯Ό μ 곡νλ λ°©λ²
λͺ¨λ μμ±μλ₯Ό private νΉμ package-private(default)λ‘ λ§λ€ ν, public μ μ ν©ν°λ¦¬ λ©μλλ₯Ό μ 곡νλ λ°©λ²
public final class Animal {
private final String type;
// private μμ±μ: μΈλΆμμ μ§μ μΈμ€ν΄μ€ μμ± λΆκ°
private Animal(final String type) {
this.type = type;
}
// public μ μ ν©ν 리 λ©μλ
public static Animal of(String type) {
return new Animal(type);
}
public String getType() {
return type;
}
}
package μΈλΆμμλ μ¬μ€μ final ν΄λμ€μ λμΌνκ² λμν λΏλλ¬, λ΄λΆμμλ ν΄λΉ ν΄λμ€λ₯Ό μμνμ¬ μ¬λ¬ ν΄λμ€λ₯Ό μμ±ν μ μκΈ° λλ¬Έμ ν¨μ¬ μ μ°ν λ°©λ²
public class Main {
public static void main(String[] args) {
Animal cat = Animal.of("Cat");
Animal dog = Animal.of("Dog");
System.out.println(cat.getType()); // μΆλ ₯: Cat
System.out.println(dog.getType()); // μΆλ ₯: Dog
}
}
μ μ ν©ν 리 λ©μλλ₯Ό μ¬μ©νλ©΄ μΊμ±μ ν΅ν΄ λμΌν κ°μ κ°μ§ κ°μ²΄μ μ€λ³΅ μμ±μ λ°©μ§ν μ μλ€.
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public final class Animal {
private static final Map<String, Animal> CACHE = new ConcurrentHashMap<>();
private final String type;
private Animal(final String type) {
this.type = type;
}
public static Animal of(String type) {
// μ΄λ―Έ ν΄λΉ νμ
μ κ°μ²΄κ° μ‘΄μ¬νλ©΄ μ¬μ¬μ©
return CACHE.computeIfAbsent(type, t -> new Animal(t));
}
public String getType() {
return type;
}
}
μ€λͺ
CACHE
맡:ConcurrentHashMap
μ μ¬μ©νμ¬ μ€λ λ μμ νκ² μΊμ±μ ꡬννλ€.- ν€λ
type
λ¬Έμμ΄μ΄κ³ , κ°μ ν΄λΉAnimal
κ°μ²΄μ΄λ€.
computeIfAbsent
λ©μλ:CACHE
μ ν΄λΉtype
μ κ°μ²΄κ° μμ κ²½μ°μλ§ μλ‘μ΄ κ°μ²΄λ₯Ό μμ±νκ³ , μ΄λ―Έ μ‘΄μ¬νλ©΄ κ·Έ κ°μ²΄λ₯Ό λ°ννλ€.
- λ©λͺ¨λ¦¬ μ¬μ©λ κ°μ:
- λμΌν
type
μ κ°μ§ κ°μ²΄λ₯Ό μ¬μ¬μ©νλ―λ‘ λΆνμν κ°μ²΄ μμ±μ μ€μ¬ λ©λͺ¨λ¦¬ ν¨μ¨μ λμΌ μ μλ€.
- λμΌν
public class Main {
public static void main(String[] args) {
Animal animal1 = Animal.of("Dog");
Animal animal2 = Animal.of("Dog");
System.out.println(animal1 == animal2); // μΆλ ₯: true (κ°μ μΈμ€ν΄μ€)
}
}
animal1
κ³Όanimal2
λ λμΌν μΈμ€ν΄μ€λ₯Ό μ°Έμ‘°νλ―λ‘==
μ°μ° κ²°κ³Όκ°true
μ΄λ€.- μ΄λ λ©λͺ¨λ¦¬ μ¬μ©λμ μ€μ΄κ³ κ°μ²΄ λΉκ΅ μ ν¨μ¨μ±μ λμΈλ€.
{% hint style="danger" %} κ·Έλμ LocalDate ν΄λμ€λ final ν΄λμ€λ‘ μ μΈνμ¬ μμμ λ°©μ§νκ³ μλ€. {% endhint %}
3) λͺ¨λ νλλ₯Ό finalλ‘ μ μΈνλ€. μμ€ν μ΄ κ°μ νλ μλ¨μ μ΄μ©ν΄ μ€κ³μ μ μλλ₯Ό λͺ νν λλ¬λ΄λ λ°©λ²μ΄λ€.
μλ° μΈμ΄μμ finalμ μ¬μ©νλ©΄ κ°μ λ°κΏ μ μκΈ° λλ¬Έμ, λͺ
μμ μΌλ‘ κ°μ λΆλ³
μΌλ‘ λ§λ€ μ μλ€.
μλ‘ μμ±λ μΈμ€ν΄μ€λ₯Ό λκΈ°ν μμ΄ λ€λ₯Έ μ€λ λμ μ λ¬νλλΌλ λ¬Έμ μμ΄ λμνκ²λ λμνλ λ°μλ νμνλ€.
λ©ν° μ€λ λμμλ μμ νλ€κ³ ν¨
Date ν΄λμ€ λ΄λΆμ μΌλ‘ CalendarDate
λΌλ ν΄λμ€κ° μ¬μ©λλλ°..
CalendarDate ν΄λμ€μ κ²½μ° λͺ¨λ νλκ° λ³κ²½ κ°λ₯ν νλμΈλ° λ°ν΄, LocalDate
λ λͺ¨λ final μ΄ λΆμ΄μλ€.
νλκ° μ°Έμ‘°νλ κ°λ³ κ°μ²΄λ₯Ό ν΄λΌμ΄μΈνΈμμ μ§μ μ κ·Όν΄ μμ νλ μΌμ λ§μμ€λ€. κΈ°μ μ μΌλ‘λ κΈ°λ³Έ νμ
νλ λ λΆλ³ κ°μ²΄λ₯Ό μ°Έμ‘°νλ νλλ₯Ό public final
λ‘λ§ μ μΈν΄λ λΆλ³ κ°μ²΄κ° λμ§λ§, μ΄λ κ² νλ©΄ λ€μ 릴리μ€μμ λ΄λΆ ννμ λ°κΎΈμ§ λͺ»νλ―λ‘ κΆνμ§λ μλλ€κ³ ν¨
ν΄λμ€μ κ°λ³ κ°μ²΄λ₯Ό μ°Έμ‘°νλ νλκ° νλλΌλ μλ€λ©΄ ν΄λΌμ΄μΈνΈμμ κ·Έ κ°μ²΄μ μ°Έμ‘°λ₯Ό μ»μ μ μλλ‘ ν΄μΌ νλ€.
μ΄λ° νλλ μ λ ν΄λΌμ΄μΈνΈκ° μ 곡ν κ° μ²΄ μ°Έμ‘°λ₯Ό κ°λ¦¬ν€κ² ν΄μλ μ λλ©°, μ κ·Όμ λ©μλκ° κ·Έ νλλ₯Ό κ·Έλλ‘ λ°νν΄μλ μ λλ€. μμ±μ, μ κ·Όμ, readObject λ©μλ λͺ¨λμμ λ°©μ΄μ 볡μ¬λ₯Ό μνν΄μΌ νλ€.
// Date.setDate λ©μλ
public void setDate(int date) {
getCalendarDate().setDayOfMonth(date);
}
// CalendarDate.setDayOfMonth λ©μλ
public CalendarDate setDayOfMonth(int date) {
if (dayOfMonth != date) {
dayOfMonth = date;
normalized = false;
}
return this;
}
// ---------------------------------------------------------------------------
// LocalDate.plusDays λ©μλ
public LocalDate plusDays(long daysToAdd) {
if (daysToAdd == 0) {
return this;
}
long dom = day + daysToAdd;
if (dom > 0) {
if (dom <= 28) {
return new LocalDate(year, month, (int) dom);
} else if (dom <= 59) { // 59th Jan is 28th Feb, 59th Feb is 31st Mar
long monthLen = lengthOfMonth();
if (dom <= monthLen) {
return new LocalDate(year, month, (int) dom);
} else if (month < 12) {
return new LocalDate(year, month + 1, (int) (dom - monthLen));
} else {
YEAR.checkValidValue(year + 1);
return new LocalDate(year + 1, 1, (int) (dom - monthLen));
}
}
}
long mjDay = Math.addExact(toEpochDay(), daysToAdd);
return LocalDate.ofEpochDay(mjDay);
}
// LocalDate.ofEpochDay λ©μλ
public static LocalDate ofEpochDay(long epochDay) {
... μλ΅
return new LocalDate(year, month, dom);
}
Date ν΄λμ€λ λ΄λΆ μΊλ¦°λ κ°μ²΄μ λ μ§ νλλ₯Ό λ³κ²½νλ λ©μλλ₯Ό νΈμΆνλ€.
λ°λ©΄μ LocalDate μ κ²½μ°μλ return λ¬Έμμ νμ μλ‘μ΄ κ°μ²΄λ₯Ό μμ±νμ¬ λ°ννλ€.
import java.util.Date;
public final class Person {
// 1) λͺ¨λ νλλ₯Ό private finalλ‘ μ μΈ
private final String name;
private final Date birthDate; // Dateλ κ°λ³ κ°μ²΄μ΄λ―λ‘ λ°©μ΄μ λ³΅μ¬ νμ
// 2) μμ±μλ₯Ό ν΅ν΄ νλλ₯Ό μ΄κΈ°ννκ³ , κ°λ³ κ°μ²΄λ λ°©μ΄μ λ³΅μ¬ μν
public Person(String name, Date birthDate) {
this.name = name;
// λ°©μ΄μ λ³΅μ¬ (μΈλΆμμ μ λ¬λ birthDateμ μ°Έμ‘°λ₯Ό μ§μ μ¬μ©νμ§ μμ)
this.birthDate = new Date(birthDate.getTime());
}
// 3) getter λ©μλλ κ°λ³ κ°μ²΄μ λν΄ λ°©μ΄μ 볡μ¬λ₯Ό μν
public String getName() {
return name; // Stringμ λΆλ³ κ°μ²΄λΌ λ°©μ΄μ λ³΅μ¬ νμ μμ
}
public Date getBirthDate() {
// λ°©μ΄μ λ³΅μ¬ (λ΄λΆμ Date κ°μ²΄λ₯Ό μΈλΆμ κ·Έλλ‘ λ°ννμ§ μμ)
return new Date(birthDate.getTime());
}
// 4) setter λ©μλ μ 곡νμ§ μμ (κ°μ²΄ μν λ³κ²½ λΆκ°)
// μ΄ ν΄λμ€μλ μνλ₯Ό λ³κ²½νλ λ©μλκ° μμ
// 5) μ΄ ν΄λμ€λ μμν μ μλλ‘ finalλ‘ μ μΈλ¨
}
1) λͺ¨λ νλλ₯Ό private final
λ‘ μ μΈ
- νλ μ κ·Όμ
private
λ‘ μ ννμ¬ μΈλΆμμ μ§μ μ κ·Όνμ§ λͺ»νκ² νκ³ ,final
λ‘ μ μΈν΄ μ΄κΈ°ν ν νλμ κ°μ λ³κ²½ν μ μλλ‘ νλ€.
2) μμ±μμμ λ°©μ΄μ λ³΅μ¬ μν
- μμ±μμμ μΈλΆμμ μ λ¬λ
Date
κ°μ²΄κ° μλ³Έ κ·Έλλ‘ μ μ₯λμ§ μλλ‘ λ³΅μ¬λ³Έμ λ§λ€μ΄ μ μ₯νλ€. μ΄λ κ² νλ©΄ μΈλΆμμ μ λ¬νDate
κ°μ²΄λ₯Ό μμ νλλΌλPerson
κ°μ²΄μbirthDate
νλμ μν₯μ μ€ μ μλ€.
3) getter
λ©μλμμ λ°©μ΄μ λ³΅μ¬ μν
getBirthDate
λ©μλμμλ μλ³ΈbirthDate
κ°μ²΄ λμ 볡μ¬λ³Έμ λ°ννλ€. μ΄λ₯Ό ν΅ν΄ μΈλΆ μ½λμμ λ°νλDate
κ°μ²΄λ₯Ό λ³κ²½νλλΌλ,Person
κ°μ²΄μ νλμλ μν₯μ μ£Όμ§ μλλ€.
4) setter λ©μλλ₯Ό μ 곡νμ§ μμ
- λ³κ²½μ(setter) λ©μλλ₯Ό μ 곡νμ§ μμμ, κ°μ²΄κ° μμ±λ ν νλ κ°μ λ³κ²½ν μ μλλ‘ νλ€.
5) μμ λΆκ° (final
ν΄λμ€)
- μ΄ ν΄λμ€λ
final
λ‘ μ μΈλμ΄ μμ΄, μμμ ν΅ν΄ νμ₯ν μ μλλ‘ νλ€. μ΄λ₯Ό ν΅ν΄ νμ ν΄λμ€κ° λΆλͺ¨ ν΄λμ€μ λΆλ³μ±μ ν΄μΉκ±°λ μνλ₯Ό λ³κ²½νλ κ²μ λ°©μ§νλ€.
- μ€λ λ μμ μ±: λΆλ³ κ°μ²΄λ μ€λ λ κ°μ μμ νκ² κ³΅μ λ μ μμΌλ―λ‘ λκΈ°ν μμ μμ΄λ μμ νκ² μ¬μ©ν μ μλ€.
- μμ μ±: λΆλ³ κ°μ²΄λ μνκ° λ³νμ§ μμΌλ―λ‘ μμ μ μ΄κ³ μμΈ‘ κ°λ₯ν λμμ ν©λλ€. ν¨μν νλ‘κ·Έλλ°μμ μμ£Ό μ¬μ©νλ ν¨ν΄μ΄λ€.
- μΊμ± λ° μ¬μ¬μ© κ°λ₯μ±: λΆλ³ κ°μ²΄λ 곡μ λ° μ¬μ¬μ©μ΄ κ°λ₯νλ€. μλ₯Ό λ€μ΄
ZERO
,ONE
,I
μ κ°μ μμλ₯Ό μ¬μ¬μ©νμ¬ λ©λͺ¨λ¦¬ μ¬μ©μ μ΅μ νν μ μλ€.
- κ° λ³κ²½ μ μ κ°μ²΄ μμ±: λΆλ³ κ°μ²΄λ κ°μ λ³κ²½νλ €λ©΄ νμ μλ‘μ΄ κ°μ²΄λ₯Ό μμ±ν΄μΌ νλ€. μ΄λ‘ μΈν΄ μ±λ₯ μ νλ λ©λͺ¨λ¦¬ μ¬μ© μ¦κ°κ° λ°μν μ μλ€.
- μλ₯Ό λ€μ΄,
Complex
κ°μ²΄μμ λ§μ μ΄λ λΊμ μ μνν λλ§λ€ μλ‘μ΄Complex
κ°μ²΄κ° μμ±λλ©°, μλ κ°μ²΄λ κ·Έλλ‘ λ¨λλ€. - ν° κ°μ²΄λ λ€λ¨κ³ μ°μ°μ μνν λλ λΆλ³ κ°μ²΄μ μ±λ₯ λ¬Έμ κ° λλλ¬μ§ μ μλ€. μ΄λ° κ²½μ° κ°λ³ λλ° ν΄λμ€λ₯Ό μ¬μ©νκ±°λ λ€λ¨κ³ μ°μ°μ μν μ΅μ νλ₯Ό μ μ©ν μ μλ€.
- μλ₯Ό λ€μ΄,
- λΆλ³ κ°μ²΄λ λ¨μν¨
- λ©ν° μ€λ λ νκ²½μμλ λκΈ°νν νμκ° μμ
- μμμ±μ μ 곡
- κ°μ΄ λ¬λΌμ§λ©΄, λ³λμ κ°μ²΄λ₯Ό λ§λ€μ΄μΌ νλ€λ κ²
- μ μ ν©ν 리 λ©μλλ₯Ό ν΅ν μΈμ€ν΄μ€ μΊμ±
λΆλ³ κ°μ²΄λ μμ±λ μμ μ μνλ₯Ό νκ΄΄λ λκΉμ§ κ·Έλλ‘ κ°μ§νλ€.
λͺ¨λ μμ±μκ° ν΄λμ€ λΆλ³μ 보μ₯νλ€λ©΄ κ·Έ ν΄λμ€λ₯Ό μ¬μ©νλ νλ‘κ·Έλλ¨Έκ° λ€λ₯Έ λ
Έλ ₯μ λ€μ΄μ§ μλλΌλ μμν λΆλ³μΌλ‘ λ¨λλ€. λ°λ©΄ κ°λ³ κ°μ²΄
λ μμμ 볡μ‘ν μν μ λμΌ μ μλ€. λ³κ²½μ λ©μλκ° μΌμΌν€λ μν μ μ΄λ₯Ό μ λ°νκ² λ¬Έμλ‘ λ¨κ²¨λμ§ μμ κ°λ³ ν΄λμ€λ λ―Ώκ³ μ¬μ©νκΈ° μ΄λ €μΈ μλ μλ€.
λΆλ³ κ°μ²΄λ κ°μ΄ λ³κ²½λλ©΄ μλ‘μ΄ κ°μ²΄λ‘ λ°ννκΈ° λλ¬Έμ λ©ν° μ€λ λ νκ²½μμλ μμ νλ€.
κ°λ³ κ°μ²΄(private int x;)μ κ²½μ°μλ λ©ν° μ€λ λ νκ²½μμ getter, setter μμ race condition 1μ΄ λ°μν μ μλ€.
λ°λ©΄μ λΆλ³κ°μ²΄(private final int x;) μ κ²½μ°μλ setter μμ νμ λ€λ₯Έ κ°μ²΄λ₯Ό λ°ννλ€.
κ·Έλμ λ©ν° μ€λ λ νκ²½μμλ μμ νκ² κ°μ²΄λ₯Ό λ€λ£° μ μλ€.
λΆλ³κ°μ²΄λ setter μ μν΄ μνκ° λ³κ²½λλ©΄, μλ‘μ΄ κ°μ²΄λ₯Ό μμ±ν΄μ λ°ννλ€.
{% hint style="danger" %} μλ‘μ΄ κ°μ²΄ μμ±μ λΉμ©μ λ¨μ {% endhint %}
-
κ°μ΄ λ³κ²½λ λλ§λ€ μλ‘μ΄ κ°μ²΄λ₯Ό μμ±ν΄μΌ νλ―λ‘ λ©λͺ¨λ¦¬μ μ±λ₯ λΉμ©μ΄ μ¦κ°ν μ μλ€.
-
μλ₯Ό λ€μ΄, ν°
BigInteger
μμ λΉνΈ νλλ₯Ό λ°κΎΈλ©΄ μ 체λ₯Ό 볡μ¬ν΄μΌ νλ€.BigInteger moby = ...; moby = moby.flipBit(0);
{% hint style="success" %} μ±λ₯ λ¬Έμ ν΄κ²° λ°©μ {% endhint %}
- λ€λ¨κ³ μ°μ°μ κΈ°λ³Έ κΈ°λ₯μΌλ‘ μ 곡νμ¬ μ€κ°μ λΆνμν κ°μ²΄ μμ±μ μ€μΈλ€.
- κ°λ³ λλ° ν΄λμ€λ₯Ό μ 곡νμ¬ μ±λ₯μ ν₯μμν¬ μ μλ€.
- μ: String ββ StringBuilder, StringBuffer BigInteger ββ MutableBigInteger
BigInteger μ λ΄λΆ μ°μ° κ³Όμ μμ κ°μ΄ μ΄λ €λ² λ°λλ κ²½μ°κ° μλ€.
μ΄λ° κ²½μ°μ MutableBigInteger λ₯Ό μ΄μ©ν΄μ μλ‘μ΄ κ°μ²΄λ₯Ό μμ±νμ§ μκ³ κ°μ λ³κ²½ν λ€μ
μ΅μ’ κ²°κ³Όλ₯Ό λ€μ BigInteger λ‘ λ³ννμ¬ λ°ννκΈ°λ νλ€.
- μ μ ν©ν 리 λ©μλλ₯Ό ν΅ν μΈμ€ν΄μ€ μΊμ±:
-
λΆλ³ ν΄λμ€λ μμ£Ό μ¬μ©λλ μΈμ€ν΄μ€λ₯Ό μΊμ±νμ¬ μ€λ³΅ μμ±μ λ°©μ§νκ³ λ©λͺ¨λ¦¬ μ¬μ©λκ³Ό κ°λΉμ§ 컬λ μ λΉμ©μ μ€μΌ μ μλ€.
-
μ μ ν©ν 리 λ©μλλ₯Ό μ¬μ©νλ©΄ ν΄λΌμ΄μΈνΈλ₯Ό μμ νμ§ μκ³ λ μΊμ± κΈ°λ₯μ μΆκ°ν μ μμ΄ μ±λ₯ ν₯μμ λμμ΄ λλ€.
-
μμ:
public class Complex { private final double re; private final double im; private Complex(double re, double im) { this.re = re; this.im = im; } public static Complex valueOf(double re, double im) { return new Complex(re, im); } // λλ¨Έμ§ μ½λ μλ΅ }
- λ°©μ΄μ λ³΅μ¬ λΆνμ:
- λΆλ³ κ°μ²΄λ μνκ° λ³κ²½λμ§ μμΌλ―λ‘ μμ λ‘κ² κ³΅μ ν μ μμΌλ©°, λ°©μ΄μ 볡μ¬κ° νμ μλ€.
- λ°λΌμ
clone
λ©μλλ λ³΅μ¬ μμ±μλ₯Ό μ 곡νμ§ μλ κ²μ΄ μ’λ€.
- λ΄λΆ λ°μ΄ν°μ 곡μ κ°λ₯:
- λΆλ³ κ°μ²΄λ λ΄λΆμ μΌλ‘ κ°λ³ κ°μ²΄λ₯Ό 곡μ ν μ μλ€.
- μλ₯Ό λ€μ΄,
BigInteger
μnegate
λ©μλλ λ΄λΆ λ°°μ΄μ 볡μ¬νμ§ μκ³ μλ³Έκ³Ό 곡μ νμ¬ μλ‘μ΄ μΈμ€ν΄μ€λ₯Ό μμ±νλ€.
- 볡μ‘ν κ°μ²΄μ λΆλ³μ μ μ§ μ©μ΄:
- λ€λ₯Έ λΆλ³ κ°μ²΄λ₯Ό κ΅¬μ± μμλ‘ μ¬μ©νλ©΄ 볡μ‘ν κ°μ²΄μ λΆλ³μμ μ μ§νκΈ° μ½λ€.
- λΆλ³ κ°μ²΄λ 맡μ ν€λ μ§ν©(Set)μ μμλ‘ μ¬μ©νκΈ°μ μ ν©νλ€.
- μ€ν¨ μμμ± μ 곡:
- λΆλ³ κ°μ²΄λ μνκ° λ³νμ§ μμΌλ―λ‘ μμΈ λ°μ μμλ κ°μ²΄μ μ ν¨ν μνκ° μ μ§λλ€.
- μμμ κΈμ§νλ λ°©λ²:
- ν΄λμ€λ₯Ό
final
λ‘ μ μΈνμ¬ μμμ λ§μ μ μμ§λ§, λ μ μ°ν λ°©λ²μ μμ±μλ₯Όprivate
λλ ν¨ν€μ§ μ μ©μΌλ‘ λ§λ€κ³public
μ μ ν©ν 리 λ©μλλ₯Ό μ 곡νλ κ²μ΄λ€. - μ΄λ κ² νλ©΄ μΈλΆμμλ ν΄λμ€λ₯Ό νμ₯ν μ μμΌλ©°, λ΄λΆμ μΌλ‘λ μ¬λ¬ ꡬν ν΄λμ€λ₯Ό νμ©ν μ μλ€.
- ν΄λμ€λ₯Ό
- κ°μ²΄ μΊμ±κ³Ό μ±λ₯ ν₯μ:
- μ μ ν©ν 리 λ©μλλ₯Ό μ¬μ©νλ©΄ λμ€μ κ°μ²΄ μΊμ± κΈ°λ₯μ μΆκ°νμ¬ μ±λ₯μ ν₯μμν¬ μ μλ€.
- λμΌν κ°μ κ°λ λΆλ³ κ°μ²΄λ₯Ό μΊμ±νμ¬ λ©λͺ¨λ¦¬ μ¬μ©λμ μ€μΌ μ μλ€.
- νλμ
final
μ¬λΆ:- μ±λ₯μ μν΄ λͺ¨λ νλλ₯Ό
final
λ‘ μ μΈνμ§ μκ³ , μΈλΆμ 보μ΄λ μνλ§ λΆλ³μΌλ‘ μ μ§ν μ μλ€. - λ΄λΆμ μΌλ‘ κ³μ° λΉμ©μ΄ ν° κ°μ μ§μ° μ΄κΈ°ννμ¬ μΊμ±ν λ μ¬μ©νλ€.
- μ±λ₯μ μν΄ λͺ¨λ νλλ₯Ό
μ£Όμμ¬ν
- μ§λ ¬ν μ μ£Όμμ :
-
Serializable
μ ꡬννλ λΆλ³ ν΄λμ€μμ κ°λ³ κ°μ²΄λ₯Ό μ°Έμ‘°νλ νλκ° μλ€λ©΄readObject
λreadResolve
λ©μλλ₯Ό μ 곡ν΄μΌ νλ€. -
readObject
λ©μλμμ λ°©μ΄μ 볡μ¬μ μ ν¨μ± κ²μ¬ μν:private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); // κ°λ³ νλμ λν΄ λ°©μ΄μ λ³΅μ¬ μν Date startCopy = new Date(start.getTime()); Date endCopy = new Date(end.getTime()); // μ ν¨μ± κ²μ¬ if (startCopy.compareTo(endCopy) > 0) throw new InvalidObjectException("μμ λ μ§κ° μ’ λ£ λ μ§λ³΄λ€ μ΄νμ λλ€."); // νλμ 볡μ¬λ³Έ μ μ₯ this.start = startCopy; this.end = endCopy; }
- λ°©μ΄μ 볡μ¬λ₯Ό ν΅ν΄ μΈλΆμμ μ λ¬λ κ°λ³ κ°μ²΄μ μ°Έμ‘°λ₯Ό λκ³ , λ΄λΆμμλ§ μ¬μ©νλ 볡μ¬λ³Έμ λ§λλλ€.
- μ ν¨μ± κ²μ¬λ₯Ό λ€μ μννμ¬ κ°μ²΄μ μΌκ΄μ±μ νμΈνλ€.
-
readResolve
λ©μλλ₯Ό μ¬μ©νμ¬ λΆλ³μ± μ μ§:private Object readResolve() { // μλ‘κ² μμ±λ μμ ν κ°μ²΄λ₯Ό λ°ν return new Period(start, end); }
- μμ§λ ¬νλ κ°μ²΄λ₯Ό μλ‘ μμ±λ κ°μ²΄λ‘ λ체νμ¬ λΆλ³μ±μ μ μ§νλ€.
- λΆλ³ κ°μ²΄λ₯Ό μ¬μ©:
Date
λμ λΆλ³ ν΄λμ€μΈInstant
λλLocalDateTime
λ±μ μ¬μ©νλ€.
import java.time.Instant; public final class Period implements Serializable { private final Instant start; private final Instant end; public Period(Instant start, Instant end) { if (start.compareTo(end) > 0) throw new IllegalArgumentException("μμ μκ°μ΄ μ’ λ£ μκ°λ³΄λ€ μ΄νμ λλ€."); this.start = start; this.end = end; } public Instant getStart() { return start; } public Instant getEnd() { return end; } }
{% hint style="danger" %} κ·Έλ μ§ μμΌλ©΄ 보μ λ¬Έμ κ° λ°μν μ μλ€. {% endhint %}
보μ λ¬Έμ μ ν΅μ¬μ μμ§λ ¬ν κ³Όμ μμ λΆλ³ ν΄λμ€μ λΆλ³μ±μ΄ κΉ¨μ§ μ μλ€λ μ μ΄λ€. μ΄λ‘ μΈν΄ μμμΉ λͺ»ν κ°μ²΄ μν λ³κ²½μ΄λ μ μμ μΈ κ°μ²΄ μ£Όμ μ΄ κ°λ₯ν΄μ Έ νλ‘κ·Έλ¨μ 보μκ³Ό μμ μ±μ΄ μνλ°μ μ μλ€.
보μ λ¬Έμ κ° λ°μνλ μ΄μ :
- μμ§λ ¬ν μ μμ±μ λ―ΈνΈμΆ:
- μλ°μ μ§λ ¬ν κ³Όμ μμ κ°μ²΄λ₯Ό μμ§λ ¬νν λ μμ±μκ° νΈμΆλμ§ μμ΅λλ€.
- λ°λΌμ μμ±μμμ μννλ λ°©μ΄μ 볡μ¬λ μ ν¨μ± κ²μ¬κ° 무μλ©λλ€.
- μ΄λ‘ μΈν΄ μΈλΆμμ μ‘°μλ λ°μ΄ν°κ° κ°μ²΄μ λ΄λΆλ‘ μ£Όμ λ μ μλ€.
- κ°λ³ κ°μ²΄μ μ§μ μ°Έμ‘° λ
ΈμΆ:
- λΆλ³ ν΄λμ€ λ΄λΆμμ κ°λ³ κ°μ²΄λ₯Ό μ°Έμ‘°νκ³ μμΌλ©΄, μμ§λ ¬ν μ κ°λ³ κ°μ²΄μ λν μ§μ μ°Έμ‘°κ° μΈλΆμ λ ΈμΆλ μ μλ€.
- 곡격μλ μ΄ κ°λ³ κ°μ²΄λ₯Ό μμ νμ¬ λΆλ³ ν΄λμ€μ λ΄λΆ μνλ₯Ό λ³κ²½ν μ μλ€.
- μμ§λ ¬ν 곡격(Deserialization Attack):
- 곡격μλ μ§λ ¬νλ λ°μ΄ν°λ₯Ό μ‘°μνμ¬ μ μμ μΈ κ°μ²΄λ λ°μ΄ν°λ₯Ό μ£Όμ ν μ μλ€.
- μ΄λ₯Ό ν΅ν΄ ν΄λμ€μ λΆλ³μ±μ κΉ¨λ¨λ¦¬κ³ , νλ‘κ·Έλ¨μ λμμ λ³κ²½νκ±°λ 보μ μ·¨μ½μ μ λ ΈμΆμν¬ μ μλ€.
PhoneNumberμ Complex κ°μ λ¨μν κ° κ°μ²΄λ νμ λΆλ³μΌλ‘ λ§λ€μοΌμλ° νλ«νΌμμλ μ λλ λΆλ³μ΄μ΄μΌ νμ§λ§ κ·Έλ μ§ μκ² λ§λ€μ΄μ§ κ°μ²΄κ° λͺ κ° μλ€. java.util. Dateμ java.awt.Pointκ° κ·Έλ λ€οΌStringκ³Ό Bigintegerμ² λΌ λ¬΄κ±°μ΄ κ° κ°μ²΄λ λΆλ³μΌλ‘ λ§λ€ μ μλμ§ κ³ μ¬ν΄μΌ νλ€.
- Getterκ° μλ€κ³ ν΄μ 무쑰건 Setterλ₯Ό λ§λ€μ§ λ§μ. ν΄λμ€κ° κΌ νμν κ²½μ°κ° μλλΌλ©΄ λΆλ³μμ 보μ₯νλ κ²μ΄ μ€κ³μ κ΄μ μμ λ°λμ§νλ€.
- λͺ¨λ ν΄λμ€λ₯Ό λΆλ³μΌλ‘ λ§λ€ μ μλ€. νμ§λ§ κ°λ³ ν΄λμ€λλΌλ λ³κ²½ν μ μλ λΆλΆμ μ΅μνμΌλ‘ μ€μ΄μ. κ·Έλ κ² λλ©΄ κ°μ²΄λ₯Ό μμΈ‘νκΈ° μ¬μμ§κ³ μ€λ₯ λ°μ κ°λ₯μ±μ΄ μ€μ΄λ λ€.(λ³κ²½μ΄ μκ² λ§λ ν λͺ¨λ
final
μ μΈμ νκ³ , νΉλ³ν μ΄μ κ° μλ€λ©΄ λͺ¨λ private final μ μΈμ νμ.) - μμ±μλ λΆλ³μ μ€μ μ΄ λͺ¨λ μλ£λ μνμ κ°μ²΄λ₯Ό μμ±ν΄μΌ νλ€. μ¦, νμ€ν μ΄μ κ° μλ€λ©΄ μμ±μμ μ μ ν©ν°λ¦¬ μΈμλ κ·Έ μ΄λ€ μ΄κΈ°ν λ©μλλ publicμΌλ‘ μ 곡ν΄μλ μλλ€. κ°μ²΄λ₯Ό μ¬μ¬μ©ν λͺ©μ μΌλ‘ μνλ₯Ό λ€μ μ΄κΈ°ννλ λ©μλλ μ¬λ°λ₯΄μ§ μλ€.
- μ±λ₯μμ μ΄μ λ‘ λΆλ³ ν΄λμ€λ₯Ό μ¬μ©ν μ μλ€λ©΄, λΆλ³ ν΄λμ€μ μμ μ΄λ£¨λ κ°λ³ λλ° ν΄λμ€λ₯Ό μ 곡νλ κ²μ κ³ λ €ν΄λΌ.
μ΄λ―Έμ§ μΆμ² : https://jwkim96.tistory.com/302
Footnotes
-
λ μ΄μ€ 컨λμ (Race Condition)μ΄λ 무μμΈκ°μ?
λ μ΄μ€ 컨λμ μ λ©ν°μ€λ λ λλ λ©ν°νλ‘μΈμ€ νκ²½μμ λ κ° μ΄μμ μ€λ λλ νλ‘μΈμ€κ° λμμ 곡μ μμμ μ κ·Όνκ±°λ μ‘°μνλ €κ³ ν λ λ°μνλ λ¬Έμ λ₯Ό λ§ν©λλ€. μ΄λ‘ μΈν΄ νλ‘κ·Έλ¨μ μ€ν κ²°κ³Όκ° μλμΉ μκ² λ¬λΌμ§κ±°λ μκΈ°μΉ μμ λ²κ·Έκ° λ°μν μ μμ΅λλ€.
μ λ°μνλμ?
- λκΈ°ν λΆμ‘±: 곡μ μμμ λν μ κ·Όμ΄ μ μ ν λκΈ°νλμ§ μμΌλ©΄, μ¬λ¬ μ€λ λκ° λμμ μμμ μ κ·Όνμ¬ μνλ₯Ό λ³κ²½ν μ μμ΅λλ€.
- λΉκ²°μ μ μ€ν μμ: μ€λ λμ μ€ν μμλ μ΄μ체μ μ μ€μΌμ€λ§μ λ°λΌ κ²°μ λλ©°, μμΈ‘ν μ μμ΅λλ€. μ΄λ‘ μΈν΄ μ€ν κ²°κ³Όκ° λ§€λ² λ¬λΌμ§ μ μμ΅λλ€.