๋ฌธ์ 1) ๊ฐ์ฒด์ ๋ณ์๊ฐ public
์ธ ๊ฒฝ์ฐ
๋ฌธ์ : ์ธ๋ถ์์ ๊ฐ์ ๋ณ๊ฒฝํด๋ฒ๋ฆด ์ ์๋ค.
- ๋ณ๊ฒฝ ์ ์ฝ๋
public class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class ImmutableMain {
public static void main(String[] args) {
Person person = new Person("๊ธธ๋์ด", 20);
person.age = 21;
}
}
ํด๊ฒฐ 1) private
์ ๊ทผ์๋ก ๋ฐ๊พธ์.
์ธ๋ถ์์ ๋ณ์์ ๋ฐ๋ก ์ ๊ทผํ ์ ์์ด์ง๋ค.
- ๋ณ๊ฒฝ ํ ์ฝ๋
public class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class ImmutableMain {
public static void main(String[] args) {
Person person = new Person("๊ธธ๋์ด", 20);
person.age = 21;
}
}
๋ฌธ์ 2) setter
๊ฐ ์๋ ๊ฒฝ์ฐ
๋ณ๊ฒฝ์ ์ฃผ์ฒด๋ ๊ฐ์ฒด ์์ ์๊ฒ ์์ง๋ง, ์ฌ์ ํ setter ๋ฉ์๋๋ฅผ ํตํด ๊ฐ์ด ๋ณ๊ฒฝ๋๋ค.
- ๋ณ๊ฒฝ ์ ์ฝ๋
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setAge(int age) {
this.age = age;
}
}
public class ImmutableMain {
public static void main(String[] args) {
Person person = new Person("๊ธธ๋์ด", 20);
person.setAge(21); // ์ธ๋ถ์์ ๊ฐ ๋ณ๊ฒฝ ๋ฉ์๋ ํธ์ถ
}
}
ํด๊ฒฐ 2) final
์ ์ถ๊ฐํ์.
์ด๊ธฐํ ์ดํ๋ก๋ ๋ณ์๋ฅผ ์ฌํ ๋นํ ์ ์๊ฒ ๋๋ค.
final์ ํตํด ๊ธฐ๋ํ ์ ์๋ ๋ถ๋ถ
- ์์ฑ์ ์ด๊ธฐํ๋ฅผ ๊ฐ์ ํ๋ค.
- setter ๋ฑ ์ฌํ ๋นํ ์ ์์ด์ง๋ค.
- ๋ณ๊ฒฝ ํ ์ฝ๋
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
/*
public void setAge(int age) {
this.age = age; // error ~!
}
*/
}
๋ฌธ์ 3) ์ฐธ์กฐ๋ณ์๊ฐ ์๋ ๊ฒฝ์ฐ: ๊ฐ์ฒด
์ฐธ์กฐํ์ ์ ๊ฒฝ์ฐ ์ฌํ ๋น๋ ์๋ ์์ง๋ง ํด๋น ๊ฐ์ฒด์ ์ํ๋ ๋ณํ ์ ์๋ค.
- ๋ณ๊ฒฝ ์ ์ฝ๋
Person
๊ฐ์ฒด: getter
๋ง ์ ๊ณตํ๋ค.
public class Person {
private final String name;
private final int age;
private final Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
public Address getAddress() {
return address;
}
}
Address
๊ฐ์ฒด: update ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
public class Address {
private String county;
private String state;
private String city;
private String zipCode;
public Address(final String county, final String state, final String city, final String zipCode) {
this.county = county;
this.state = state;
this.city = city;
this.zipCode = zipCode;
}
public void update(final String county, final String state, final String city, final String zipCode) {
this.county = county;
this.state = state;
this.city = city;
this.zipCode = zipCode;
}
@Override
public String toString() {
return String.format("%s %s %s %s", county, state, city, zipCode);
}
}
- ํ
์คํธ ์ฝ๋
๊ฐ์ ์ฐธ์กฐ๊ฐ์ ๋ฐ๋ผ๋ณด๊ณ ์์ด์ ๊ฐ์ด ๋ณํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
@Test
void ํ์์ฐธ์กฐ๋ณ์_๋ณ๊ฒฝ_์_๊ฐ๋ณ() {
// when
Address address = new Address("county", "state", "city", "zipCode");
Person person = new Person("์ด๋ฆ", 20, address);
// given
address.update("county-1", "state-1", "city-1", "zipCode-1");
//then
assertEquals(person.getAddress(), address);
}
ํด๊ฒฐ 3) ๋ถ๋ณ๊ฐ์ฒด์ ์ฐธ์กฐ๋ณ์๋ ๋ถ๋ณ์ผ๋ก ๋ง๋ค์.
Address ๋ณ์๋ final ์ผ๋ก ๋ถ๋ณํํ๋ค.
- ํด๊ฒฐ ํ ์ฝ๋
public class Address {
private final String county;
private final String state;
private final String city;
private final String zipCode;
public Address(final String county, final String state, final String city, final String zipCode) {
this.county = county;
this.state = state;
this.city = city;
this.zipCode = zipCode;
}
@Override
public String toString() {
return String.format("%s %s %s %s", county, state, city, zipCode);
}
}
๋ฌธ์ 4) ์ฐธ์กฐ๋ณ์๊ฐ ์๋ ๊ฒฝ์ฐ: ์ปฌ๋ ์
์ปฌ๋ ์ ์ฐธ์กฐ๋ณ์์ ๊ฒฝ์ฐ๋ฅผ ์์๋ณด์.
- ๋ณ๊ฒฝ ์ ์ฝ๋
Person
๊ฐ์ฒด:containsHobby()
๋ก ํ์ธํ๋ ค๋Hobby
๋ฅผ ํฌํจ ์ฌ๋ถ๋ง ๋ฆฌํดํด์ค๋ค.
public class Person {
private final String name;
private final int age;
private final Address address;
private final List<Hobby> hobbies;
public Person(String name, int age, Address address, List<Hobby> hobbies) {
this.name = name;
this.age = age;
this.address = address;
this.hobbies = hobbies;
}
public boolean containsHobby(Hobby hobby) {
return hobbies.contains(hobby);
}
}
- ํ ์คํธ ์ฝ๋
@Test
void ์ปฌ๋ ์
์ฐธ์กฐ๋ณ์์_์์์ถ๊ฐํ๋ฉด_๊ฐ๋ณ() {
// when
Address address = new Address("county", "state", "city", "zipCode");
List<Hobby> hobbies = new ArrayList<>();
hobbies.add(new Hobby("ํด๋ผ์ด๋ฐ"));
hobbies.add(new Hobby("๋
์"));
Person person = new Person("์ด๋ฆ", 20, address, hobbies);
// given
Hobby requestHobby = new Hobby("์ฝ๋ฉ");
hobbies.add(requestHobby);
// then
assertTrue(person.containsHobby(requestHobby));
}
- ๋ฐ์์ ์ปฌ๋ ์ ์ ์์๋ฅผ ์ถ๊ฐํ๋ฉด ํด๋น ๊ฐ์ ์ฐธ์กฐํ๋ ๋ถ๋ณํ๋ ค๋๊ฐ์ฒด์ ์ปฌ๋ ์ ์์๋ ๊ฐ๋ณ์ด๋ค.
ํด๊ฒฐ 4-1) new ArrayList<>(target)
๋ก ์์ฑ
- ๋ณ๊ฒฝ ํ ์ฝ๋
public Person(String name, int age, Address address, List<Hobby> hobbies) {
this.name = name;
this.age = age;
this.address = address;
this.hobbies = new ArrayList<>(hobbies); // ์๋กญ๊ฒ ์์ฑ
}
์์ ํ ์คํธ๋ฅผ ๋ค์ ์คํํ๋ฉด ๊ธฐ๋ํ๋๋ก ์คํจํ๋ค.
ํด๊ฒฐ 4-2) getter
์ฌ์ฉํ๋ ๊ฒฝ์ฐ, Collections.unmodifiableList()
ํ์ฉํ์.
4-1
์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋๋ผ๋ getter
๋ก ์ปฌ๋ ์
์ ๋ฐํํ๋ฉด ์ฌ์ ํ ๋ถ๋ณ์ด ์ง์ผ์ง์ง ์๋๋ค. getter
๋ก ์ปฌ๋ ์
์ ๋ฐํํ ๋ Collections.unmodifiableList()
๋ฅผ ํ์ฉํ์.
public List<Hobby> getHobbies() {
return Collections.unmodifiableList(hobbies);
}
ํด๊ฒฐ 4-3) (์๋ฐ10 ๋ถํฐ ๊ฐ๋ฅ) List.copyOf(tatget)
์ผ๋ก ๋ถ๋ณ์ปฌ๋ ์
์์ฑ
์๋ฐ10
๋ถํฐ๋ ์์ฑํ ๋ ๋ถํฐ ๋ณต์ฌ์์ฑ ํ ๋ ๋ถํฐ ๋ถ๋ณ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ฃผ๋ ๋ฉ์๋๊ฐ ์ถ๊ฐ๋์๋ค. ์๋ฐ8 ์ดํ์ LTS
์ธ ์๋ฐ11, ์๋ฐ17์ ์ฌ์ฉํ๋ฉด ํด๋น ๋ฉ์๋๋ฅผ ํ์ฉํ ์ ์๊ฒ ๋ค.
- ๋ณ๊ฒฝ ํ ์ฝ๋
public Person(String name, int age, Address address, List<Hobby> hobbies) {
this.name = name;
this.age = age;
this.address = address;
this.hobbies = List.copyOf(hobbies); // List.copyOf() ํ์ฉ
}
- List.copyOf() ์ฝ๋
static <E> List<E> copyOf(Collection<? extends E> coll) {
return ImmutableCollections.listCopy(coll);
}
List
์ copyOf()
๋ ์์ ์ด ๋ถ๊ฐํ ์ปฌ๋ ์
์ ๋ฐํํ๋ค.
'Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[cache] LRU ์๊ณ ๋ฆฌ์ฆ with LinkedHashMap (0) | 2022.08.22 |
---|---|
์ ๋ค๋ฆญ์ ํ์ฉํ์ฌ ๋ฒ์๋ฅผ ๊ตฌํ๋ 'Range' util class ๋ง๋ค๊ธฐ (0) | 2022.08.03 |
์ ๋๋ค์์ ์ง์ญ๋ณ์๋ฅผ ๋ณ๊ฒฝํ ์ ์์๊น? (0) | 2022.01.16 |