2023. 1. 26. 16:54ใJAVA/Effective JAVA
item10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์ํ๋ผ.
[์ดํํฐ๋ธ ์๋ฐ] Item10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์ํ๋ผ. (๋์นญ์ฑ, ๋ฐ์ฌ์ฑ, ์ถ์ด์ฑ)
item10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์ํ๋ผ. equals ๋ฉ์๋๋ฅผ ์ฌ์ ์ํ ๋๋ ๋ฐ๋์ ์ผ๋ฐ ๊ท์ฝ์ ๋ฐ๋ผ์ผ ํ๋ค. equals ๊ท์ฝ 1๏ธโฃ ๋ฐ์ฌ์ฑ reflexivity : null ์ด ์๋ ๋ชจ๋ ์ฐธ์กฐ ๊ฐ x์ ๋ํด x.equals(x) == true
hyejin.tistory.com
[์ดํํฐ๋ธ ์๋ฐ] Item10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์ํ๋ผ. (์ถ์ด์ฑ, ์ผ๊ด์ฑ, null-์๋)
item10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์ํ๋ผ. equals ๋ฉ์๋๋ฅผ ์ฌ์ ์ํ ๋๋ ๋ฐ๋์ ์ผ๋ฐ ๊ท์ฝ์ ๋ฐ๋ผ์ผ ํ๋ค. [์ดํํฐ๋ธ ์๋ฐ] Item10. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์ํ๋ผ. (๋์นญ์ฑ, ๋ฐ์ฌ์ฑ, ์ถ์ด
hyejin.tistory.com
์์์ equals ์ผ๋ฐ ๊ท์ฝ์ ๋ํด์ ํ์ตํ๊ณ , equals ๋ฉ์๋ ๊ตฌํ ๋ฐฉ๋ฒ์ ๋จ๊ณ๋ณ๋ก ์ ๋ฆฌํ๋ค.
equals ๊ตฌํ๋ฐฉ๋ฒ
1๏ธโฃ == ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด ์ ๋ ฅ์ด ์๊ธฐ ์์ ์ ์ฐธ์กฐ์ธ์ง ํ์ธํ๋ค.
if (this == obj) {
return true;
}
์๊ธฐ ์์ ์ด๋ฉด true๋ฅผ ๋ฐํํ๋ค.
-> ์ด๋ ๋จ์ํ ์ฑ๋ฅ ์ต์ ํ์ฉ์ผ๋ก, ๋น๊ต ์์ ์ด ๋ณต์กํ ์ํฉ์ผ ๋ ๊ฐ์ด์น๋ฅผ ํ ๊ฒ์ด๋ค.
2๏ธโฃ instanceof ์ฐ์ฐ์๋ก ์ ๋ ฅ์ด ์ฌ๋ฐ๋ฅธ ํ์ ์ธ์ง ํ์ธํ๋ค.
if (!(obj instanceof Point)) {
return false;
}
-> ์ฌ๋ฐ๋ฅธ ํ์ ์ด ์๋๋ผ๋ฉด false๋ฅผ ๋ฐํํ๋ค.
3๏ธโฃ ์ ๋ ฅ์ ์ฌ๋ฐ๋ฅธ ํ์ ์ผ๋ก ํ๋ณํํ๋ค.
Point p = (Point) obj;
-> 2๋จ๊ณ์์ instanceof ๊ฒ์ฌ๋ฅผ ํ๊ธฐ ๋๋ฌธ์ ์ฑ๊ณตํ๋ค.
4๏ธโฃ ์ ๋ ฅ ๊ฐ์ฒด์ ์๊ธฐ ์์ ์ ๋์๋๋ 'ํต์ฌ' ํ๋๋ค์ด ๋ชจ๋ ์ผ์นํ๋์ง ํ๋์ฉ ๊ฒ์ฌํ๋ค.
return p.x == x && p.y == y;
๋ชจ๋ ํ๋๋ค์ด ์ผ์นํ๋ฉด true๋ฅผ, ํ๋๋ผ๋ ๋ค๋ฅด๋ฉด false๋ฅผ ๋ฐํํ๋ค.
์ด๋ float์ double์ ์ ์ธํ ๊ธฐ๋ณธ ํ์ ํ๋๋ ==์ฐ์ฐ์๋ก ๋น๊ตํ๊ณ , ์ฐธ์กฐ ํ์ ํ๋๋ ๊ฐ๊ฐ equals ๋ฉ์๋๋ก, float์ double ํ๋๋ ๊ฐ๊ฐ ์ ์ ๋ฉ์๋์ธ Float.compare(float, float)์ Double.compare(double, double) ๋ก ๋น๊ตํ๋ค. float์ double์ ๋ถ๋ ์์๊ฐ์ ๋ค๋ค์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ๋๋ก null ๋ ์ ์ ๊ฐ์ผ๋ก ์ทจ๊ธํ๋ ์ฐธ์กฐ ํ์ ํ๋๋ ์๋๋ฐ ์ด๋ฐ ํ๋๋ ์ ์ ๋ฉ์๋์ธ Objects.equals(Object, Object)๋ก ๋น๊ตํด์ NPE๋ฅผ ์๋ฐฉํ๋ฉด ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ค ํ๋๋ฅผ ๋จผ์ ๋น๊ตํ๋๋๊ฐ equals์ ์ฑ๋ฅ์ ์ข์ฐํ๊ธฐ๋ ํ๋ค.
์ต์์ ์ฑ๋ฅ์ ๋ฐ๋๋ค๋ฉด ๋ค๋ฅผ ๊ฐ๋ฅ์ฑ์ด ๋ ํฌ๊ฑฐ๋ ๋น๊ตํ๋ ๋น์ฉ์ด ์ผ ํ๋๋ฅผ ๋จผ์ ๋น๊ตํ๋ฉด ์ข๋ค.
๐ค equals ๋ฉ์๋ ๊ตฌํ ๋ฐฉ๋ฒ ์ ๋ฆฌ
equals๋ฅผ ์ง์ ์์ฑํ ์๋ ์์ง๋ง equals ์์ฑ์ ๋์์ฃผ๋ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ๋ค์ด ์๋ค.
- ๊ตฌ๊ธ์ AutoValue
์ฐ์ build.gradle์
compileOnly "com.google.auto.value:auto-value-annotations:1.6"
annotationProcessor "com.google.auto.value:auto-value:1.6"
๋ฅผ ์ถ๊ฐํ๊ณ gradle ํ๋ฒ refresh ํด์ค๋ค.
@AutoValue
abstract class Point
{
static Point create(int x, int y)
{
return new AutoValue_Point(x, y); // IDE์์๋ ์๋ค๊ณ ํ์ง๋ง ์ปดํ์ผ ํ ๋ ๋ง๋ค์ด์ค๋ค.
}
abstract int x();
abstract int y();
}
๊ทธ๋ฆฌ๊ณ AutoValue_Point๊ฐ IDE์์๋ ์๋ค๊ณ ์ปดํ์ผ ์๋ฌ๊ฐ ๋ฐ ๊ฒ์ด์ง๋ง ์ปดํ์ผ ์์ ์ AutoValue_Point๋ฅผ ๋ง๋ค์ด์ค๋ค!! (์ฆ, ์๋ฌ ์๋๋ ์๋ฆฌ)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package chapter01.item10.autovalue;
final class AutoValue_Point extends Point {
private final int x;
private final int y;
AutoValue_Point(int x, int y) {
this.x = x;
this.y = y;
}
int x() {
return this.x;
}
int y() {
return this.y;
}
public String toString() {
return "Point{x=" + this.x + ", y=" + this.y + "}";
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Point)) {
return false;
} else {
Point that = (Point)o;
return this.x == that.x() && this.y == that.y();
}
}
public int hashCode() {
int h$ = 1;
h$ *= 1000003;
h$ ^= this.x;
h$ *= 1000003;
h$ ^= this.y;
return h$;
}
}
-> build -> classes ๋ก ๊ฐ๋ณด๋ฉด AutoValue_Point๊ฐ ์์ฑ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๊ทผ๋ฐ ์ด ๊ตฌ๊ธ์ AutoValue๋ ์นจํฌ์ ์ด๊ธฐ๋ ํด์ ์ด ๊ฐ์์ ๊ฐ์ฌ๋์ ์ ์ฌ์ฉํ์ง ์๋๋ค๊ณ ํ๋ค.
- Lombok
๋๋ถ๋ถ ์ด Lombok์ ์ฌ์ฉํ์ง ์์๊น ์ถ๋ค.
@EqualsAndHashCode
@ToString
public class Point
{
private final int x;
private final int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
๋กฌ๋ณต์ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ ์ค๊ณ ์ข๋ค. (์ฝ๊ฐ์ ๋ ผ๋? ์ด ์๊ธฐ๋ ํ์ง๋ง.. ์ฌ์ฉ์ ๋ฌด๋ฆฌ๋ ์๋ค๊ณ ํ๋ค.)
- IDE ์ ์ฝ๋ ์์ฑ ๊ธฐ๋ฅ ์ฌ์ฉ
์ด๋ฐ์์ผ๋ก ์ธํ ๋ฆฌ์ ์ด์์๋ equals์ hascode ์์ฑ์ ๋์์ค๋ค.
public class Point
{
private final int x;
private final int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// IDE ์ฌ์ฉ -> ๋จ์ : ์ฝ๋๊ฐ ์ง์ ๋ถํด์ง๋ค, ํ๋๊ฐ ๋์ด๋๋ฉด ๋ค์ ๋ง๋ค์ด์ผ ํ๋ค.
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Point point = (Point) o;
return x == point.x && y == point.y;
}
@Override
public int hashCode()
{
return Objects.hash(x, y);
}
}
-> ์ฌ๊ธฐ์ ๋จ์ ์ ์ฝ๋๊ฐ ์ง์ ๋ถํด์ง๋ค๋ ์ ๊ณผ ํ๋๊ฐ ์ถ๊ฐ๋๋ฉด ๋ค์ ๋ง๋ค์ด์ค์ผ ํ๋ค๋ ์ ์ด ์๋ค!! (ํ๋๋ ์ถ๊ฐํ๊ณ equals ์ hascode๋ฅผ ์์ ํ์ง ์์ผ๋ฉด ํฐ์ผ๋๋ค ใ ใ )
equals ์ฃผ์์ฌํญ
1๏ธโฃ equals๋ฅผ ์ฌ์ ์ํ ๋ hashcode๋ ๋ฐ๋์ ์ฌ์ ์ํด์ผํ๋ค.
2๏ธโฃ ๋๋ฌด ๋ณต์กํ๊ฒ ํด๊ฒฐํ๋ ค ๋ค์ง ๋ง์!
ํ๋๋ค์ ๋์น์ฑ๋ง ๊ฒ์ฌํด๋ equals ๊ท์ฝ์ ์ด๋ ต์ง ์๊ฒ ์งํฌ ์ ์๋ค. ์คํ๋ ค ๋๋ฌด ๊ณต๊ฒฉ์ ์ผ๋ก ํ๊ณ ๋ค๋ค๊ฐ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์๋ค.
3๏ธโฃ Object ์ธ์ ํ์ ์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๋ equals ๋ฉ์๋๋ ์ ์ธํ์ง ๋ง์.
public boolean equals(Point obj)
{
...
}
์ด๋ฐ์์ผ๋ก ์ ๋ ฅํ์ ์ Object๊ฐ ์๋ ๋ค๋ฅธ ํ์ ์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ผ๋ฉด ์๋๋ค..!!
์ด๊ฑด ์ค๋ฒ๋ผ์ด๋ฉ์ด ์๋๋ผ ์ค๋ฒ๋ก๋ฉ์ด ๋๋ค...