10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์
equals๋ฅผ ์ฌ์ ์ํ๋ ๊ฒฝ์ฐ๋ ...
๐ ๋ ๊ฐ์ฒด๊ฐ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๊ฐ์์ง(๊ฐ์ฒด ์๋ณ์ฑ)๊ฐ ์๋๋ผ ๋ ผ๋ฆฌ์ ๋์น์ฑ์ ํ์ธํด์ผ ํ๋๋ฐ, ์์ ํด๋์ค์ equals๊ฐ ๋ ผ๋ฆฌ์ ๋์น์ฑ์ ๋น๊ตํ๋๋ก ์ฌ์ ์๋์ง ์์ ๋
โณ๏ธ ์ผ๋ฐ ๊ท์ฝ
- ๋์นญ์ฑ : x.equals(y)๊ฐ true์ด๋ฉด, y.equals(x)๋ true
- ์ถ์ด์ฑ : x.equals(y)๊ฐ true์ด๊ณ , y.equals(z)๋ true์ด๋ฉด, x.equals(z)๋ true
- ์ผ๊ด์ฑ : x.equals(y)๋ฅผ ๋ฐ๋ณตํด์ ํธ์ถํ๋ฉด ํญ์ true ๋๋ false ๋ฐํ
โณ๏ธ equals ๋ฉ์๋ ๊ตฌํ ๋ฐฉ๋ฒ
- == ์ฐ์ฐ์ ์ฌ์ฉํด ์ ๋ ฅ์ด ์๊ธฐ ์์ ์ ์ฐธ์กฐ์ธ์ง ํ์ธ ๐ ์๊ธฐ ์์ ์ด๋ฉด true ๋ฐํ
- instanceof ์ฐ์ฐ์๋ก ์ ๋ ฅ์ด ์ฌ๋ฐ๋ฅธ ํ์ ์ธ์ง ํ์ธ
- ์ ๋ ฅ์ ์ฌ๋ฐ๋ฅธ ํ์ ์ผ๋ก ํ๋ณํ
- ์ ๋ ฅ ๊ฐ์ฒด์ ์๊ธฐ ์์ ์ ๋์๋๋ ํต์ฌ ํ๋๋ค์ด ๋ชจ๋ ์ผ์นํ๋์ง ํ๋์ฉ ๊ฒ์ฌ
- Object ์ธ์ ํ์ ์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๋ equals ๋ฉ์๋ ์ ์ธ X ๐@Override ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํด ์ค์ ์๋ฐฉ
public 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)) { // instanceof๋ก ํ์
ํ์ธ
return false;
}
PhoneNumber pn = (PhoneNumber) o; // ํ๋ณํ
// ํต์ฌ ํ๋ ์ผ์นํ๋์ง ํ์ธ
return pn.lineNum == lineNum && pn.prefix == prefix
&& pn.areaCode == areaCode;
}
}
โจ ๊ผญ ํ์ํ ๊ฒฝ์ฐ๊ฐ ์๋๋ฉด equals ์ฌ์ ์ X
โจ AutoValue ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํด ํด๋์ค์ ์ด๋ ธํ ์ด์ ํ๋๋ง ์ถ๊ฐํ์ฌ equals ์์ฑํ๊ณ ํ ์คํธํ๋ ์ผ ↓
11. equals๋ฅผ ์ฌ์ ์ํ ๋, ๋ฐ๋์ hashCode๋ ํจ๊ป ์ฌ์ ์
HashMap, HashSet๊ณผ ๊ฐ์ ์ปฌ๋ ์ ์์ ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๋๋ก ํ๊ธฐ ์ํจ
โจ HashCode๋ ?
๐ ๊ฐ์ฒด๋ฅผ ์๋ณํ๋ ํ๋์ ์ ์๊ฐ์ผ๋ก, Object์ hashCode() ๋ฉ์๋๋ ๊ฐ์ฒด์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ์ด์ฉํด์ ํด์ ์ฝ๋๋ฅผ ๋ง๋ค์ด ๋ฐํํ๋ฏ๋ก ๊ฐ์ฒด๋ง๋ค ๊ณ ์ ์ ๊ฐ์ ๊ฐ์ง๊ณ ์์
โณ๏ธ Object์์์ HashCode ๊ด๋ จ ๊ท์ฝ
- equals ๋น๊ต์ ์ฌ์ฉ๋๋ ์ ๋ณด๊ฐ ๋ณ๊ฒฝ๋์ง ์์๋ค๋ฉด, ๊ทธ ๊ฐ์ฒด์ hashCode ๋ฉ์๋๋ ์ผ๊ด๋๊ฒ ํญ์ ๊ฐ์ ๊ฐ ๋ฐํ
- equals(Object)๊ฐ ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ค๊ณ ํ๋จํ๋ค๋ฉด, ๋ ๊ฐ์ฒด์ hashCode๋ ๋๊ฐ์ ๊ฐ ๋ฐํ
- equals(Object)๊ฐ ๋ ๊ฐ์ฒด๋ฅผ ๋ค๋ฅด๋ค๋ก ํ๋จํ๋ค๋ฉด, ๋ ๊ฐ์ฒด์ hashCode๊ฐ ์๋ก ๋ค๋ฅธ ๊ฐ์ ๋ฐํํ ํ์ X ๐ ๋จ, ๋ค๋ฅธ ๊ฐ์ ๋ฐํํด์ผ ํด์ํ ์ด๋ธ ์ฑ๋ฅ์ด ์ข์์ง
โณ๏ธ ์ข์ hashCode ์์ฑํ๊ธฐ
// ์ ํ์ ์ธ ๋ฉ์๋
@Override
public int hashCode() {
int result = Integer.hashCode(areaCode);
result = 31 * result + Integer.hashCode(prefix);
result = 31 * result + Integer.hashCode(lineNum);
return result;
}
// ํ ์ค์ง๋ฆฌ ๋ฉ์๋ -> ์ฑ๋ฅ ๐
@Override
public int hashCode() {
return Objects.hash(lineNum,prefix,areaCode);
}
๐ ์ ๋ ฅ ์ธ์๋ฅผ ๋ด๊ธฐ ์ํ ๋ฐฐ์ด์ด ๋ง๋ค์ด์ง๊ณ , ์ ๋ ฅ ์ค ๊ธฐ๋ณธ ํ์ ์ด ์๋ค๋ฉด ๋ฐ์ฑ๊ณผ ์ธ๋ฐ์ฑ์ ๊ฑฐ์ณ์ผํ๋ฏ๋ก ์๋ ๋๋ฆผ
// ํด์์ฝ๋๋ฅผ ์ง์ฐ ์ด๊ธฐํํ๋ ๋ฉ์๋ - ์ค๋ ๋ ์์ ์ฑ๊น์ง ๊ณ ๋ คํด์ผ ํจ
private int hashCode; //์๋์ผ๋ก 0์ผ๋ก ์ด๊ธฐํ
@Override
public int hashCode() {
int result = hashCode;
if(result == 0) {
int result = Integer.hashCode(areaCode);
result = 31 * result + Integer.hashCode(areaCode);
result = 31 * result + Integer.hashCode(areaCode);
hashCode = result;
}
return result;
}
โจ ์ง์ฐ ์ด๊ธฐํ๋ ?
๐ ํ์ํ ๋๊น์ง ๊ฐ์ฒด๋ ๊ฐ์ ์ด๊ธฐํ๋ฅผ ๋ฏธ๋ฃธ์ผ๋ก์จ ์ฑ๋ฅ ์ต์ ํ ๋ฐ ์์ ์ ์ฝ
// ์ง์ฐ ์ด๊ธฐํ X ๊ฐ์ฒด ์์ฑ public class DataLoader { private HeavyResource resource = new HeavyResource(); // ๊ฐ์ฒด ์์ฑ ์ ์ฆ์ ์ด๊ธฐํ public void loadData() { // ๋ฌด๊ฑฐ์ด ์์ ์ ์ํํ๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉ resource.doSomething(); } }
// ์ง์ฐ ์ด๊ธฐํ ์ ์ฉ public class DataLoader { private HeavyResource resource; // ์์ง ์ด๊ธฐํํ์ง ์์ public void loadData() { if (resource == null) { // ์ฒ์์ผ๋ก ์ฌ์ฉ๋ ๋๋ง ์ด๊ธฐํ resource = new HeavyResource(); } resource.doSomething(); } }
12. toString ํญ์ ์ฌ์ ์ ํ์
๊ฐ๊ฒฐํ๋ฉด์ ์ฌ๋์ด ์ฝ๊ธฐ ์ฌ์ด ํํ์ ์ ์ตํ ์ ๋ณด ๋ฐํ
๐ ๋ชจ๋ ํ์ ํด๋์ค์์ ์ฌ์ ์ ! (์์ ํด๋์ค์์ ์ด๋ฏธ ์ฌ์ ์ํ ๊ฒฝ์ฐ๋ ์์ธ)
- ์ปฌ๋ ์ ์ฒ๋ผ ์ธ์คํด์ค๋ฅผ ํฌํจํ๋ ๊ฐ์ฒด์์ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋จ
- ๊ฐ์ฒด๊ฐ ๊ฐ์ง ์ฃผ์ ์ ๋ณด ๋ชจ๋๋ฅผ ๋ฐํํ๋ ๊ฒ์ด ์ข์ (๊ฑฐ๋ํ๊ฑฐ๋ ๋ฌธ์์ด๋ก ํํํ๊ธฐ ์ ํฉํ์ง ์๋ค๋ฉด ์์ฝ์ ๋ณด ๋ด๊ธฐ)
- ํ์ ํด๋์ค๋ค์ด ๊ณต์ ํด์ผํ ๋ฌธ์์ด ํํ์ด ์๋ ์ถ์ ํด๋์ค๋ผ๋ฉด ์ฌ์ ์ ํ์ !
- ๋ฐํ๊ฐ์ ํฌ๋งท์ ๋ฌธ์ํํ ์ง ๊ฒฐ์ (์ ํ๋ฒํธ๋ ํ๋ ฌ ๊ฐ์ ๊ฐ)
โด๏ธ ํฌ๋งท ๋ช ์ํ ๊ฒฝ์ฐ
/**
* ์ด ์ ํ๋ฒํธ์ ๋ฌธ์์ด ํํ์ ๋ฐํํ๋ค.
* ์ด ๋ฌธ์์ด์ "XXX-YYY-ZZZZ" ํํ์ 12๊ธ์๋ก ๊ตฌ์ฑ๋๋ค.
* XXX๋ ์ง์ญ์ฝ๋, YYY๋ ํ๋ฆฌํฝ์ค, ZZZZ๋ ๊ฐ์
์ ๋ฒํธ๋ค.
* ๊ฐ๊ฐ์ ๋๋ฌธ์๋ 10์ง์ ์ซ์ ํ๋๋ฅผ ๋ํ๋ธ๋ค.
*
* ์ ํ๋ฒํธ์ ๊ฐ ๋ถ๋ถ์ ๊ฐ์ด ๋๋ฌด ์์์ ์๋ฆฟ์๋ฅผ ์ฑ์ธ ์ ์๋ค๋ฉด,
* ์์์๋ถํฐ 0์ผ๋ก ์ฑ์๋๊ฐ๋ค. ์์ปจ๋ฐ ๊ฐ์
์ ๋ฒํธ๊ฐ 123์ด๋ผ๋ฉด
* ์ ํ๋ฒํธ์ ๋ง์ง๋ง ๋ค ๋ฌธ์๋ "0123"์ด ๋๋ค.
*/
@Override
public String toString() {
return String.format("%03d-%03d-%04d", areaCode, prefix, lineNum);
}
โด๏ธ ํฌ๋งท ๋ช ์ํ์ง ์์ ๊ฒฝ์ฐ
/**
* ์ด ์ฝ๋ฌผ์ ๊ดํ ๋๋ต์ ์ธ ์ค๋ช
์ ๋ฐํํ๋ค.
* ๋ค์์ ์ด ์ค๋ช
์ ์ผ๋ฐ์ ์ธ ํํ์ด๋,
* ์์ธ ํ์์ ์ ํด์ง์ง ์์์ผ๋ฉฐ ํฅํ ๋ณ๊ฒฝ๋ ์ ์๋ค.
*
* "[์ฝ๋ฌผ #9: ์ ํ-์ฌ๋, ๋์=ํ
๋ฌ๋น์ , ๊ฒ๋ชจ์ต=๋จน๋ฌผ]"
*/
@Override
public String toString() { ... }
'Java > ๐ Effective Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[๐ Effective Java] ํด๋์ค์ ์ธํฐํ์ด์ค ไธญ (2) | 2024.10.05 |
---|---|
[๐ Effective Java] ํด๋์ค์ ์ธํฐํ์ด์ค ไธ (1) | 2024.09.25 |
[๐ Effective Java] ๋ชจ๋ ๊ฐ์ฒด์ ๊ณตํต ๋ฉ์๋ ไธ (0) | 2024.09.22 |
[๐ Effective Java] ๊ฐ์ฒด ์์ฑ๊ณผ ํ๊ดด ไธ (0) | 2024.09.20 |
[๐ Effective Java] ๊ฐ์ฒด ์์ฑ๊ณผ ํ๊ดด ไธ (1) | 2024.09.16 |