-
μΈμ€ν΄μ€μ λμΌμ¬λΆλ₯Ό νμ νλ equals μλλ μ€λ²λΌμ΄λ©μ΄ κ°λ¨νκ² κ°μ§λ§ μλͺ»λλ κ²½μ°κ° γ λ³μ
- λ¬Έμ λ₯Ό νΌνλ κ°μ₯ μ¬μ΄ λ°©λ²μ equals λ©μλ(object κ²)
- λ€λ₯Έ μνΌν΄λμ€μμ object μ΄λ―Έ μ€λ²λΌμ΄λ© νκ²μ μ€λ²λΌμ΄λ νμ§ μκ³ μμλ°μ κ·Έλλ‘ μ¬μ©
-
ν΄λμ€μ κ° μΈμ€ν΄μ€κ° λ³ΈλλΆν° μ μΌνκ²½μ° -μΈμ€ν΄μ€κ° κ°λ κ°λ³΄λ€λ νλνλ κ°μ²΄μμ λνλ΄λκ²μ΄ λμ€μν μ€λ λμ κ°μ ν΄λμ€κ° μ¬κΈ° ν΄λΉ
- κ·Έλ° ν΄λμ€λ€μ μΈμ€ν΄μ€κ° κ°λ λ Όλ¦¬μ μΈ λΉκ΅λ μλ―Έκ° μμ
- Objectμ equalsλ₯Ό κ·Έλ₯ μ¬μ©νλ©΄λ¨
-
λ μΈμ€ν΄μ€κ° λ Όλ¦¬μ μΌλ‘ κ°μμ§ κ²μ¬νμ§ μμλ λλ ν΄λμ€μ κ²½μ°
- ex) java.util.Random ν΄λμ€μΌγ μλ λκ°μ Random μΈμ€ν΄μ€κ° κ°μ λμμ΄μ λ§λλμ§ νμΈνκΈ° μν΄ equals λ©μλλ₯Ό μ€λ²λΌμ΄λ© ν μ μμμ κ²μ΄μλ€.
- Objectμ equalsλ₯Ό κ·Έλ₯ μ¬μ©νλ©΄λ¨
-
μνΌ ν΄λμ€μμ equals λ©μλλ₯Ό μ΄λ―Έ μ€λ²λΌμ΄λ© νκ³ , κ·Έλ©μλλ₯Ό κ·Έλλ‘ μ¬μ©ν΄λ μ’μκ²½μ°
- Set μΈν°νμ΄μ€λ₯Ό ꡬννλ λλΆλΆμ ν΄λμ€λ€μ AbstractSet μ ꡬνλ equalsλ₯Ό μμλ°μ μ¬μ©ν¨
- List κ²½μ°λ AbstractList μμ μμλ°μ
- Map AbstractMap μμ μμλ°μ
-
private μ΄λ ν¨ν€μ§ μ μ©(package-private) ν΄λμ€λΌμ μ΄ν΄λμ€μ equals λ©μλκ° μ λ νΈμΆλμ§ μμμΌ ν κ²½μ°
- μ κ·Ό μ§μμλ₯Ό μ§μ νμ§ μμ λν΄νΈ ν¨ν€μ§ μ κ·Όμ λ§ν¨
- μ€λ²λΌμ΄λ© ν΄μ νΈμΆλμ§ μλλ‘ ν΄μΌν¨
@Override public boolean equals(Object o){
throws new AssertionError(); // λ©μλκ° μ λ νΈμΆλμ§ μλλ€.
}- κ°μ²΄ μ°Έμ‘°λ§μΌλ‘ μΈμ€ν΄μ€ λμΌ μ¬λΆλ₯Ό νλ¨νλκ²μ΄μλλΌ μΈμ€ν΄μ€κ° κ°λ κ°μ λΉκ΅νμ¬ λ
Όλ¦¬μ μΌλ‘ κ°μμ§ νλ¨ν νμκ° μλ ν΄λμ€λ‘μ¨
μμ μ μνΌν΄λμ€μμ equlas λ©μλλ₯Ό μ€λ²λΌμ΄λ νμ§ μμμλ - μΌλ°μ μΌλ‘ value ν΄λμ€κ° μ¬κΈ°μ ν΄λΉ
- νλμ κ°μ λνλ΄λ ν΄λμ€ ex) Integer, Date
- κ°μ²΄ μ°Έμ‘° μ¬λΆλ μ€μνμ§ μκ³ κ°μ²΄κ° κ°λ κ°μ΄ λ Όλ¦¬μ μΌλ‘ κ°μμ§κ° κ΄μ¬μ¬
- equals λ©μλμ μ€λ²λΌμ΄λ©μ νλ‘κ·Έλλ¨Έμ μꡬ μΆ©μ‘±
- Mapμ ν€λ Setμ μμλ₯Ό κ°μ²΄κ° μ΄λ―Έ μλμ§ λΉκ΅νλ μλ¨μ μ 곡ν΄μΌνκΈ° λλ¬Έ
- κ° κ° λΉ μ΅λνλμ κ°μ²΄λ§ μ‘΄μ¬νλλ‘ μΈμ€ν΄μ€ μ μ΄λ₯Ό μ¬μ©νλ ν΄λμ€
- μ΄κ±°ν enum
- κ·Έλ° ν΄λμ€λ€μ κ²½μ° λ Όλ¦¬μ μΈ μΌμΉμ κ°μ²΄ μ°Έμ‘° μΌμΉκ° λμΌν μλ―Έ
- Object equals λ©μλκ° λ Όλ¦¬μ μΈ equals λ©μλμ κΈ°λ₯μ νλ μ
-
μ¬κ·μ μ΄λ€(Reflexive)
- nullμ΄ μλ λͺ¨λ μ°Έμ‘° κ° xμ λν΄, x.equals(x) λ°λμ true λ°ν
-
λμΉμ μ΄λ€(Symmetric)
- nullμ΄ μλ λͺ¨λ μ°Έμ‘° κ° xμ yμ λν΄ y.equals(x)κ° true λ°ννλ©΄
- x.equals(y) λ λ°λμ true λ°νν΄μΌν¨
-
μ΄νμ μ΄λ€(Transitive)
- null μ΄ μλ λͺ¨λ μ°Έμ‘° κ° x,y,z μ λν΄ , equals λ©μλμμ κ°μ²΄ λΉκ΅μ μ¬μ©νλ μ λ³΄κ° λ³κ²½λμ§ μλλ€λ©΄
- x.equals(y)λ₯Ό μ¬λ¬λ² νΈμΆνλλ‘ μΌκ΄μ±μκ² true λλ falseλ₯Ό λ°νν΄μΌν¨
- nullμ΄ μλ λͺ¨λ μ°Έμ‘°κ° xμ λν΄ x.equals(null)μ λ°λμ false λ°νν΄μΌν¨
-
μ¬κ·μ±(Reflexivity)
- 첫λ²μ¨° μ‘°νμλ κ°μ²΄λ₯Ό μκΈ° μμ κ³Ό λΉκ΅νλ©΄ κ°μμΌλλ€κ³ λμμμ
- μ΄κΈ°κΈ° μ΄λ €μ
-
λμΉμ±(Symmetry)
- λ κ°μ²΄κ±΄ λμΉμ μΌλ‘ μλ‘ λΉκ΅νλ©΄ κ°μμΌλ¨
- μ¬κ·μ±κ³Ό λ€λ₯΄κ² λ¬΄μ¬ μ΄κΈ°κΈ° μ¬μ
μλ₯Όλ€μ΄ μλ¬Έ λμλ¬Έμλ₯Ό ꡬλΆνμ§ μλ λ¬Έμμ΄μ ꡬν
// κ³μ½ κΉ¨μ§ - λμΉμ±μ μλ°°λ¨
public final class CaseInsensitiveString{
private final String s;
public CaseInsesitiveString(String s){
if(s == null)
throws new NullPointerException();
this.s=s;
}
//κ³μ½ κΉ¨μ§ - λμΉμ±μ μλ°°λ¨
@Override
public boolean equals(Object o){
if(o instanceof CaseInsesitivieString)
return s.equalsIgnoreCase((CaseInsesitiveString) 0).s);
if(o instanseof String) //νμͺ½μΌλ‘λ§ μνΈ μ΄μ©λλ€.
return s.equalsIgnoreCase((String) o);
return false;
}
...//λλ¨Έμ§μ½λ μλ΅
}- equals λ©μλμμ λμλ¬Έμλ₯Ό ꡬλΆνμ§ μλ λ¬Έμμ΄(CaseInsensitiveString κ°μ²΄)κ³Ό μΌλ°λ¬Έμμ΄(String κ°μ²΄) λͺ¨λλ₯Ό κ°μ΄ μ²λ¦¬νλ €κ³ νλ€.
CaseInsesitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";- cis.equals(s)λ true λ°ν
- κ·Έλ¬λ CaseInsensitiveString μ equals λ©μλλ μΌλ° λ¬Έμμ΄ μ²λ¦¬νκ³ μλ λ°λ©΄
- String μ equals λ©μλλ λμλ¬Έμλ₯Ό ꡬλΆνμ§ μλ λ¬Έμμ΄μ μΈμνμ§ λͺ»νλ κ²μ΄ λ¬Έμ μ
- λ°λΌμ s.equals(cis)λ false λ°ν
- λμΉμ±μ μλ°
List<CaseInsensitiveString> list = new ArrayList<CaseInsensitiveString>();
list.add(cis);-
μΌλ¨ equals κ³μ½μ μ΄κΈ°λ©΄,μ°λ¦¬κ°μ²΄μ κ°μ΄ μ¬μ©λλ λ€λ₯Έ κ°μ²΄λ€μ΄ μ΄λ»κ² λμν μ§ μμ μμ
-
λ¬Έμ λ₯Ό ν΄μνλ €λ©΄ equals λ©μλλ‘ λΆν° String κ°μ²΄λ₯Ό μ²λ¦¬νλ μ½λλ₯Ό μ κ±°νλ©΄λ¨
@Override
public boolean equals(Object o){
return o instanseof CaseInsensitiveString &&
((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}μ΄νμ±(Transitivity)
-
첫λ²μ§Έ κ°μ²΄κ° λλ²μ§Έ κ°μ²΄μ λμΌνκ³ λλ²μ§Έ κ°μ²΄κ° μΈλ²μ§Έ κ°μ²΄μ λμΌνλ€λ©΄ 첫λ²μ§Έ κ°μ²΄λ μΈλ²μ§Έ κ°μ²΄μ κ°μμΌ ν¨
-
κΈ°μ‘΄ μνΌ ν΄λμ€μ κ° μ»΄ν¬λνΈ(value component) Color κ°μ²΄λ₯Ό μΆκ°νλ μλΈ ν΄λμ€ μκ°
- equals λ©μλκ° κ°μ²΄λ₯Ό λΉκ΅νλλ° νμν μ 보λ₯Ό μλΈ ν΄λμ€μμ μΆκ° μ 곡
-
μ μ μ’νμ΄ μ μ λνλ΄λ λΆλ³(immutable) ν΄λμ€
public class Point{
private final int x;
private final int y;
public Point(int x, int y){
this.x=x;
this.y=y;
}
@Override
public boolean equals(Object o){
if(!(o instanceof Point))
return false;
Point p =(Point)0;
return p.x == x && p.y === y;
}
...// λλ¨Έμ§μ½λ μλ΅
}- μ λ§λ€ μμμ μΆκ°ν΄μ λ€μκ³Ό κ°μ μλΈ ν΄λμ€
public class ColorPoint extends Point{
private final Color color;
public ColorPoint(int x, int y, Color color){
super(x,y);
this.color = color;
}
// λλ¨Έμ§ μ½λ μλ΅
}@Override
public boolean equals(Object o){
if(!(o instanceof ColorPoint))
return false;
return super.equals(o) && ((ColorPoint) o).color == color;
}- μ΄ λ©μλμ λ¬Έμ μ Point κ°μ²΄λ₯Ό ColorPoint μ λΉκ΅ν λ κ·Έλ¦¬κ³ κ·Έλ°λλ‘ λΉκ΅ν λ λ€λ₯Έκ²°κ³Ό λμ΄
- Point κ°μ²΄λ₯Ό ColorPoint λΉκ΅ν λλ μμμ΄(Color) λΉκ΅μμ λΉ μ§ λ°λλ‘ λΉκ΅ν λλ νμ false λ°ν
- μΈμκ°μ΄ ν리기 λλ¬Έμ
Point p = new Point(1,2);
ColorPoint cp = new ColorPoint(1,2, Color.RED);- μ΄κ²½μ° p.equals(cp)λ true λ°λ©΄ cp.equals(p)λ false
// κ³μ½ κΉ¨μ§ - μ΄νμ±μ μλ°°λλ€
@Override
public boolean equals(Object o){
if(!(o instanseof Point))
return false;
// λ§μΌ oκ° Point κ°μ²΄λΌλ©΄ Colorλ₯Ό λΉΌκ³ λΉκ΅νλ€.
if(!(o instanceof ColorPoint))
return o.equals(this);
// oκ° ColorPoint κ°μ²΄λΌλ©΄, Pointμ Color λͺ¨λ λΉκ΅νλ€.
return super.equals(o) && ((ColorPoint)o).color == color;
}- Point κ°μ²΄λ₯Ό λΉκ΅ν λλ μμ(Color)λ₯Ό 무μνλλ‘ λ€μκ³Ό κ°μ΄ ColorPoint.equals μμ νμ¬ λ¬Έμ ν΄κ²°ν μμμ§λ§ λ¬Έμ κ°μκΉ
- μ΄νμ±μ λν λ¬Έμ
ColorPoint p1 = new ColorPoint(1,2,Color.RED);
Point p2 = new Point(1,2);
ColorPoint p3 = new ColorPoint(1,2,Color.BLUE);-
p1.equals(p2), p2.equals(p3) true λ°ν
-
p1.equals(p3)λ false λ°ν
- λͺ λ°±ν μ΄νμ± μλ°
-
μΈμ€ν΄μ€ μμ±μ΄ κ°λ₯ν ν΄λμ€μ μλΈ ν΄λμ€ κ° μ»΄ν¬λνΈλ₯Ό μΆκ°νλ©΄μ equals κ³μ½μ μ§ν¬ μ μλ λ°©λ²μ μμ
// 리μ€μ½ν(Liskov)μ λ체μμΉ(substitution principle)μ μλ°°λλ€.
@Override public boolean equals(Object o){
if(o == null || o.getClass() != getClass())
return false;
Point p = (Point) o;
return p.x == x && p.y ==y;
}-
μ κ²½μ° λΉκ΅νλ λκ°μ²΄μ ν΄λμ€λ§ κ°μλλ§ ν¨κ³Ό μμ
-
μ μμ μ’ν κ°μ κ°λ μ μ΄ λ¨μμ(Unit Circle) μμ μλμ§ μλ €μ£Όλ λ©μλμμ±
// λ¨μμ μμ λͺ¨λ μ λ― ν¬ν¨νλλ‘ UnitCircle μ΄κΈ°ν νλ€.
private static final Set<Point> unitCicle;
static {
unitCircle = new HashSet<Point>();
unitCircle.add(new Point(1,0));
unitCircle.add(new Point(0,1));
unitCircle.add(new Point(-1,0));
unitCircle.add(new Point(0,-1));
}
public static boolean onUnitCircle(Point p){
return unitCircle.contains(p);
}- κ·Έλ¬λ κ° μ»΄ν¬λνΈλ₯Ό μΆκ°νμ§ μλ μΌλ°μ μΈ λ°©λ²μΌλ‘ Point μλΈ ν΄λμ€λ₯Ό λ§λ λ€κ³ ν΄λ³΄λ©΄ μΌλ§λ λ§μ μΈμ€ν΄μ€κ° μμ±λμλμ§ κΈ°μ΅νλ μμ±μλ₯Ό κ°λκ²μ΄λ€.
public class CounterPoint extends Point{
private static final AtomicInteger counter = new AtomicInteger();
public CounterPoint(int x, int y){
super(x,y);
counter.incrementAndGet();
}
public int numberCreated() { return counter.get(); }
}-
νΉμ νμ μ μ΄λ€ λ©μλ건 μμ μ μλΈ νμ μμλ λκ°μ΄ λμνκΈ° μν΄μ κ·Ένμ μ μ΄λ€ μ€μν μμ±λ μμ μ μλΈνμ μ μν΄ κ°κ³ μμ΄μΌλλ€κ³ 리μ€μ½νμ λ체μμΉ(Liskov substitution principleμ λμμμ
-
CounterPoint μΈμ€ν΄μ€λ₯Ό onUnitCircle λ©μλ μΈμλ‘ μ λ¬νλ€κ³ κ°μ
-
λ§μΌ Point ν΄λμ€μμ getClass ννμ equals λ©μλλ₯Ό μ¬μ©νλ€λ©΄, CounterPoint μΈμ€ν΄μ€μΈ xμ y κ΄κ³μμ΄ onUnitCircle λ©μλμμ falseλ₯Ό λ°νν κ²μ
- κ·Έ μ΄μ λ onUnitCircle λ©μλμμ μ¬μ©νλ HashSetκ³Ό κ°μ 컬λ μ μμ μ μ₯λ κ°μ²΄μΈμ§ μ¬λΆλ₯Ό νμΈνκΈ° μν΄ equals λ©μλλ₯Ό μ¬μ©νλλ° CounterPoint μΈμ€ν΄μ€λ μ΄λ€ Point μΈμ€ν΄μ€μλ κ°μ§μκΈ° λλ¬Έμ΄λ€.
-
Point ν΄λμ€μμ instanceof ννμ equals λ©μλλ₯Ό μ¬μ©νλ€λ©΄, CounterPoint μΈμ€ν΄μ€λ₯Ό μΈμλ‘ μ£Όμ΄λ onUnitCircle λ©μλλ μ λμ ν κ²μ΄λ€.
-
μμ(inheritance)보λ€λ μ»΄ν¬μ§μ (composition)μ μ¬μ©νμλ κΆκ³ λ₯Ό λ°λ₯΄λ κ²
-
ColorPoint λ₯Ό Point μλΈ ν΄λμ€λ‘ λ§λλλμ private Point νλμ public λ·° λ©μλλ₯Ό ColorPoint ν΄λμ€μ μΆκ°νλκ²
-
λ·° λ©μλλ ColorPoint μΈμ€ν΄μ€μ κ°μ μ’ν μμΉλ₯Ό κ°λ Point μΈμ€ν΄μ€λ₯Ό λ°ννλ€.
// equals κ³μ½μ μ΄κΈ°μ§ μμΌλ©΄μ κ° μ»΄ν¬λνΈλ₯Ό μΆκ°νλ€.
public class ColorPoint{
private final Point point;
private final Color color;
public ColorPoint(int x, int y, Color color){
if(color ==null)
throw new NullPointerException();
point = new Point(x,y);
this.color = color;
}
/**
* ColorPoint μΈμ€ν΄μ€μ κ°μ μ’νλ₯Ό κ°λ Point μΈμ€ν΄μ€λ₯Ό λ°ννλ€,
*/
public Point asPoint(){
return point;
}
@Override
public boolean equals(Object o){
if(!(o instanceof ColorPoint))
return false;
ColorPoint cp = (ColorPoint) o;
return cp.point.equals(point) && cp.color.equals(color);
}
..// λλ¨Έμ§ μ½λλ μλ΅
}- μΈμ€ν΄μ€ μμ±μ΄ κ°λ₯ν ν΄λμ€λ‘ λΆν° μμλ°μ κ° μ»΄ν¬λνΈλ₯Ό μΆκ°νκ³ μλ ν΄λμ€λ€μ΄ μ€μ λ‘ μλ° νλ«νΌμ μλ€.
- μΆμ(abstract) ν΄λμ€μ μλΈ ν΄λμ€μμλ equals κ³μ½μ μλ°°νμ§ μκ³ μ»΄ν¬λνΈλ₯Ό μΆκ° ν μμλ€λκ²μ μ£Όλͺ©
- μλ₯Ό λ€μ΄ κ° μ»΄ν¬λνΈκ° μλ Shape λΌλ μΆμν΄λμ€κ° μκ³ κ·Έκ²μ μλΈ ν΄λμ€λ‘ Circle, Rectangle μ΄ μμ μ μμ
- μ΄ κ²½μ° μμκ°μ λ¬Έμ μ μκΈ°μ§ μμ μνΌν΄λμ€μ μΈμ€ν΄μ€λ₯Ό μ§μ μμ±ν μ μκΈ°λλ¬Έ
- μΌκ΄μ±(Consistency) λ§μΌ λκ°μ²΄κ° λμΌνλ€λ©΄, νλκ° λ³κ²½λμ§ μλ ν νμ λμΌν¨μ μ μ§ν΄μΌ νλ€λκ²μ΄ equals λ€λ²μ§Έ μ‘°ν
- μ¦ κ°λ³ κ°μ²΄λ€μ μμ μ΄ λ¬λΌμ Έλ λ€λ₯Έ κ°μ²΄λ€κ³Ό λμΌ ν μ μμ§λ§ λΆλ³κ°μ²΄λ€μ κ·Έλ΄ μ μμ
- λΆλ³ ν΄λμ€λ‘ λ§λ€μ΄μΌ λλ€λ©΄ λμΌν κ°μ²΄λ€μ κΎΈμ€ν λμΌν¨μ μ μ§νκ³ λμΌνμ§ μλ κ°μ²΄λ€μ μ€κ³§ λμΌνμ§ μμμ μ μ§νλλ‘ equals λ©μλλ₯΄ μμ±
- ν΄λμ€κ° λΆλ³μ΄κ±΄ μλ건 μ λ’°ν μ μλ μμμ μμ‘΄νλ equals λ©μλλ₯Ό μμ±νμ§λ§μ
- Null μλ λ©μλκ° κ΅¬ννλ λλ±κ΄κ³ λ§μ§λ§ μꡬμ¬ν λͺ¨λ κ°μ²΄λ nullκ³Ό κ°μ§ μμμΌ νλ€λ μλ―Έ
@Override public boolean equals(Object o){
if(o == null)
return false;
}- μμ κ°μ κ²μ¬ λΆνμν¨ equals λ©μλμμλ μ°μ λΉκ΅μ μ ν©ν νμ
μΌλ‘ μΈμλ₯Ό λ°νν΄μΌ νλ©° μ΄μ°¨νΌ nullμ΄ κ±Έλ¬μ§
- νμ μ λ°ννλ μ΄μ λ κ°μ²΄λ₯Ό λΉκ΅ν λ κ·ΈμΈμκ° μ°Έμ‘°νλ κ°μ²΄μ λ©μλλ₯Ό νΈμΆνκ±°λ νλλ₯Ό μ κ·Ό ν μ μμ΄μΌ νκΈ° λλ¬Έ
- μ λ¬λ μΈμμ νμ μ΄ Object dml μνΌ ν΄λμ€ νμ μΌλ‘ μλμ μΊμ€ν λλ―λ‘ equals λ©μλ λ΄λΆμμ μ΄ μΈμλ₯Ό μ¬λ°λ₯΄κ² μ¬μ©νλ €λ©΄ μ ν©ν μλΈν΄λμ€ νμ μΌλ‘ λ³ν(λ€μ΄μΊμ€ν ) ν΄μΌν¨
@Override
public boolean equals(Object o){
if(!(o instanceof MyType))
return false;
myType mt = (MyType) o;
...
}- νμ κ²μ¬λ₯Ό νμ§ μμλλ° μλͺ»λ νμ μ μΈμκ° equals λ©μλλ‘ μ λ¬λλ©΄ ClassCastException μμΈκ° λ°μ
- equals κ³μ½μ μλ°νκ²λ¨
- instanceof μ°μ°μλ‘ κ²μ¬νλ©΄, λλ²μ§Έ νΌμ°μ°μ(μ€λ₯Έμͺ½) νμ κ³Ό μκ΄μμ΄ νΌμ°μ°μ(μΌμͺ½) nullμΈ κ²½μ° false κ° λ°νλλ€.
- null μ΄ μΈμλ‘ μ λ¬λλ©΄ false κ° λ°νλλ―λ‘ λ°λ‘ nullμ κ²μ¬ ν νμκ° μμ
- κ°μ²΄μ κ°μ λΉκ΅ ν νμ μκ³ μ°Έμ‘°λ§μΌλ‘ κ°μ κ°μ²΄μΈμ§ λΉκ΅ κ°λ₯νλ€λ©΄ == μ°μ°μλ₯Ό μ¬μ©νμ. κ·Έλ¦¬κ³ κ°λ€λ©΄ true λ₯Ό λ°νν¨ μ΄κ²μ μ½λ μ±λ₯μ μ΅μ ν νλ κ²μ λΆκ³Όνμ§λ§, λ§μΌ λΉκ΅νλ λΉμ©μ΄ μμ² λ§μ΄ λ λ€λ©΄ κ·Έλ¬κ²ν κ°μΉκ° μμ
2.instanceof μ°μ°μλ₯Ό μ¬μ©ν΄μ μ λ¬λ μΈμκ° μ¬λ°λ₯Έ νμ μΈμ§ νμΈνμ.
- λ§μΌ κ·Έλ μ§ μλ€λ©΄ false λ₯Ό λ°ννλ€. λκ°μ κ²½μ° μ¬λ°λ₯Έ νμ μ΄λ νΈμΆλ equals λ©μλκ° μ μλ ν΄λμ€λ₯Ό λ§νμ§λ§ κ·Έ ν΄λμ€κ° ꡬννλ μΈν°νμ΄μ€λ μ¬λ°λ₯Έ νμ μ΄ λ μ μλ€.
- λ°λΌμ μ΄λ€ μΈν°νμ΄μ€λ₯Ό ꡬννλ ν΄λμ€λ€μ΄ μ¬λ¬κ° μκ³ κ° ν΄λμ€λ€μ equals κ³μ½μ λ§κ² equals λ©μλλ₯Ό μ€λ²λΌμ΄λ© νκ³ μλ€ κ·Έ μΈν°νμ΄μ€λ μ¬λ°λ₯Έ νμ μ΄ λ μ μμ
- μΈν°νμ΄μ€λ₯Ό ꡬννλ ν΄λμ€λ€μ΄ μ¬λ¬κ° μκ³ κ°ν΄λμ€λ€μ equals κ³μ½μ λ§κ² equals λ©μλλ₯Ό μ€λ²λΌμ΄λ© νκ³ μλ€λ©΄ κ·Έ μΈν°νμ΄μ€ νμ
μΌλ‘ κ° ν΄λμ€λ€μ κ°μ²΄λ₯Ό λΉκ΅ ν μ μμ
- ex) Set,List,Map, Map.Entry κ°μ 컬λ μ μΈν°νμ΄μ€κ° κ·Έλ°νν
-
μμ νμ μ μ¬λ°λ₯Έ νμ μΌλ‘ λ³ννλ€. μ΄λ° νμ λ³νμ instanceof κ²μ¬ν ννκ² λλ―λ‘ μμΈκ° μκΈ°μ§μκ³ μμ νκ² μ²λ¦¬λλ€.
-
ν΄λμ€μ μ€μν(곑 λΉκ΅ν΄μΌ νλ)νλ κ°κ°μ λν΄μλ μΈμλ‘ μ λ¬λ κ°μ²΄μ νλμ νμ¬ κ°μ²΄μ νλκ° λͺ¨λ κ°μμ§ λΉ νΈλ¦¬μ§ λ§κ³ λΉκ΅νλ€.
- λͺ¨λ κ°λ€λ©΄ true, κ·Έλ μ§ μλ€λ©΄ false λ₯Ό λ°ν
- λ§μΌ μμ 2λ²μμ νμ κ²μ¬μ λΉκ΅ν κ°μ²΄μ νμ μ΄ μΈν°νμ΄μ€μΌλλ κ·Έ μΈν°νμ΄μ€μ λ©μλλ₯Ό ν΅ν΄μ μΈμμ νλλ₯Ό μ κ·Όνλ©°, λΉκ΅ν κ°μ²΄μ νμ μ΄ ν΄λμ€λΌλ©΄ νλλ₯Ό λ°λ‘ μ κ·Ό ν μ μλ€.
- λ¬Όλ‘ ν΄λΉ νλμ μ κ·Ό λ²μκ° μ΄λ»κ² μ§μ λμλκ°μ λ°λΌ λ€λ¦
(field == o.field || (field ! =null && field.equals(o.field))- μ΄λ° κ²½μ°μλ νλμ νμ€νμ(canonical form)μ μ μ§νμ¬ equals λ©μλμμ κ·Έκ²μ κΈ°μ€μΌλ‘ νλ κ°μ λμΌ μ¬λΆλ₯Ό λΉκ΅νλ€λ©΄ λΉμ©μ΄ μ κ² λλ λΉκ΅λ₯Ό ν μ μμ
- μ΄ κΈ°λ²μ λΆλ³ ν΄λμ€ κ°μ²΄λ₯Ό λΉκ΅ν λ κ°μ₯μ ν©νλ€.
- λ§μ½ κ°μ²΄μ κ°μ΄ λ³κ²½ λ μ μλ€λ©΄ νμ€ νμμ μ΅μ μΌλ‘ μ μ§ν΄μΌνλ€.
- equals λ©μλμ μ±λ₯μ λΉκ΅νλ νλμ μμμ μν₯μ λ°μ μ μλ€.
- μ±λ₯μ κ°μ₯ μ’κ² νλ €λ©΄ λ€λ₯Ό κ°λ₯μ±μ΄ λ§κ±°λ λΉκ΅λΉμ©μ΄ μ κ²λλ νλλΆν° λ¨Όμ λΉκ΅
- κ°μ²΄μ λκΈ°ν(synchronizeation)μ μ¬μ©λλ λ½(lock) νλμ²λΌ κ°μ²΄ μμ μ΄ κ°μ§ μλ νλλ₯Ό λΉκ΅νλ©΄ μλλ€.
- λΉκ΅λ₯Ό ν΄μΌνλ μ€μνλμ κ°μ μ°μ°μ²λ¦¬νμ¬ μ»μ΄μ§λ νμ νλλ λΉκ΅ν νμ μλ€.
- κ·Έλ¬λ νμ νλκ° κ·Έ κ°μ²΄ μ 체λ₯Ό μμ½ν΄μ λνλ΄λ μν μ΄λΌλ©΄ κ° νλμ κ°μ λΉκ΅νλκ²λ³΄λ€ νμ νλλ₯Ό λΉκ΅νλκ²μ΄ μ±λ₯ ν₯μμ λμμ΄ λ κ²μ΄λ€.
- λ€κ°ν(Polygon) ν΄λμ€κ° μκ³ λ κ°μ λ€κ°ν κ°μ²΄λ€μ λ©΄μ μ νμνλλ‘ κ°κ³ λΉκ΅νλ€λ©΄ κ° λ€κ°νμ λ³κ³Ό κΌμ§μ μ λͺ¨λ λΉκ΅ ν νμκ° μμ
- equals λ©μλλ₯Ό μμ±ν νμ κ³Όμ° κ·Έλ©μλκ° λμΉμ μ΄λ©° μ΄νμ μ΄κ³ , μΌκ΄μ± μλμ§λ₯Ό νμΈν¨.
- λ¨μ ν μ€νΈ μ½λλ₯Ό μμ±νμ¬ κ·Έλ° μμ±λ€μ΄ μ§μΌμ§λμ§ κ²μ¬νλ€.
- λ§μΌ μ§μΌμ§μ§ μλλ€λ©΄ equals λ©μλλ₯Ό μμ νλ€. λ¬Όλ‘ λ€λ₯Έ λκ°μ§ μμ±(μ¬κ·μ±κ³Ό nullμ΄ μλ λ λ§μ‘±ν΄μΌν¨)
μ μν μ¬ν
- equals λ©μλλ₯Ό μ€λ²λΌμ΄λν λ hashCode λ©μλλ νμ μ€λ²λΌμ΄λ νλ€.
- λ무 λλνμ² νμ§λ§λΌ λ¨μν νλ κ°μ΄ κ°μμ§ κ²μ¬νλ κ²μ΄λΌλ©΄ equals κ³μ½ μ€μκ° μ΄λ ΅μ§ γ
λ³λ€.
- νμ§λ§ λ무 μ§λμΉκ² λμΌμ¬λΆλ₯Ό λΉκ΅νλ €λ©΄ λ¬Έμ κ° μκΈ°κΈ° μ½λ€.
- μ¨λ¦¬μ΄μ± (λκ° μ΄μμ κ°μ²΄ μ°Έμ‘°κ° λμΌν κ°μ²΄λ₯Ό κ°λ¦¬ν€λκ²μ μ¨λ¦¬μ΄μ±μ΄λΌκ³ ν¨) λ κ°μ²΄λ€μ λΉκ΅κΉμ§λ κ³ λ €νλκ²μ μ’μμκ°μ΄ μλ
- equals λ©μλ μΈμ νμ μ Object λμ λ€λ₯Έ νμ μΌλ‘ λ°κΎΈμ§ λ§μ.
public boolean equals(MyClass o){
...
}- μ¬κΈ°μλ λ©μλ μΈμ Object νμ μΈ Object.equalsλ₯Ό μ€λ²λΌμ΄λ(override) νκ²μ΄ μλλΌ μ€λ²λ‘λ(overload) νκ³ μλ€λ κ²μ΄ λ¬Έμ μ΄λ€.
- λ λ©μλμ λ°ννμ μ΄ κ°λ€λ©΄ νλ²ν equals λ©μλμ λΆκ°νμ¬ λλ€λ₯Έ equals(μΈμμ κ°μλ νμ μ΄ λ€λ₯Έ) λ©μλλ₯Ό μ μ(μ€λ²λ‘λ)ν΄λ λ¬Έμ μλ€.
- κ·Έλ¬λ μ¬κΈ°μλ κ·ΈλμΌν μ΄μ κ°μμ μ€λ²λΌμ΄λ© ν΄μΌν κ²μ μλͺ»ν΄μ μ€λ²λ‘λ© νκ²μ΄κΈ° λλ¬Έμ
- @Override μ£Όμμ μΌκ΄λκ² μ¬μ©νλ©΄ μ΄λ° μ€μλ₯Ό λ§μμ€ λ€μκ³Ό κ°μ equals λ©μλλ μ»΄νμΌμλ¬ μκΈΈκ²μ΄κ³ κ·Έμ΄μ λ μλ¬λ©μΈμ§μμ μμλ €μ€
@Override public boolean equals(MyClass o){
....
}
- equals λ©μλλ₯Ό μ€λ²λΌμ΄λ νλ λͺ¨λ ν΄λμ€μμλ λ°λμ hashCode λ©μλλ μ€λ²λΌμ΄λ ν΄μΌν¨
- κ·Έλ μ§ μμΌλ©΄ Object.hashCode λ©μλμ 보νΈμ κ³μ½μ μλ°νκ² λλ―λ‘ HashMap,HashSet,Hashtable μ ν¬ν¨νλ λͺ¨λ ν΄μ κΈ°λ°μ 컬λ μ λ€κ³Ό μ°λ¦¬ ν΄λμ€λ₯Ό κ°μ΄ μ¬μ©ν κ²½μ° μ¬λ°λ₯΄κ² λμνμ§ μμ κ²μ΄λ€.
μλ° API λ¬Έμμ Object.hashCode λͺ μΈ
-
μ΄ν리μΌμ΄μ μ€νμ€μ κ°μ κ°μ²΄μ λν΄ νλ² μ΄μ νΈμΆλλλΌλ hashCode λ©μλλ κ°μ μ μλ₯Ό μΌκ΄μ± μκ² λ°νν΄μΌ νλ€.
-
equals(Object) λ©μλ νΈμΆ κ²°κ³Ό λκ°μ²΄κ° λμΌνλ€λ©΄, λ κ°μ²΄ κ°κ°μ λν΄ hashCode λ©μλλ₯Ό νΈμΆ νμλ κ°μ μ μ κ°μ΄ λμμΌ νλ€.
-
equals(Object) λ©μλ νΈμΆ κ²°κ³Ό λ κ°μ²΄κ° λ€λ₯΄λ€κ³ ν΄μ λκ°μ²΄ κ°κ°μ λν΄ hashCode λ©μλλ₯Ό νΈμΆνμλ λ°λμ λ€λ₯Έ μ μ κ°μ΄ λμ¬ νμλ μμ
- κ·Έλ¬λ κ°μ΄ μμ κ°μ²΄λ€μ λν΄ hashCode λ©μλμμ μλ‘λ€λ₯Έ μ μκ°μ λ°ννλ©΄, μ΄ λ©μλλ₯Ό μ¬μ©νλ ν΄μ컬λ μ λ€(HashMap,HashSet,Hashtable) λ±μ΄ μ±λ₯μ ν₯μ μν¬μ μμμ μμμΌ νλ€.
-
hashCode μ μ€λ²λΌμ΄λ©μ μ€ν¨ νμλ μλ°°λλ μ£Όμ μ‘°νμ λλ²μ§Έ κ²μΌλ‘μ¨ λμΌν κ°μ²΄λ€μ κ°μ ν΄μμ½λλ₯Ό κ°μ κ°μ ΈμΌ νλ€λκ²
public final class PhoneNumber{
private final short areaCode;
private final short prefix;
private final short lineNumber;
public PhoneNumber(int areaCode, int prefix, int lineNumber){
rangeCheck(areaCode, 999 , "area code");
rangeCheck(prefix, 999 , "prefix");
rangeCheck(lineNumber, 9999, "line number");
this.areaCode = (short) areaCode;
this.prefix = (short) prefix;
this.lineNumber = (short) lineNumber;
}
private static void rangeCheck(int arg, int max, String name){
if(arg < 0 || arg > max)
throw new IllegalArgumentException(name + ": "+arg);
}
@Override
public boolean equals(Object o){
if(o == this)
return true;
if(!(o instanceof PhoneNumber))
return false;
PhoneNumber pn = (PhoneNumber)o;
return pn.lineNumber = lineNumber
&& pn.prefix=prefix
&& pn.areaCode = areaCode;
}
// κ³μ½ κΉ¨μ§ - hashCode λ©μλκ° μλ€!
...// λλ¨Έμ§ μ½λ μλ΅
}- μ΄ν΄λμ€λ₯Ό HashMap κ³Ό ν¨κ» μ¬μ©νλ€κ³ νλ©΄
Map<PhoneNumber, String> m = new HashMap<PhoneNumber,String>();
m.put(new PhoneNumber(707,867, 5309),"jenny");-
m.get(new PhoneNumber(707,867, 5309)) λ₯Ό νΈμΆνλ©΄ "jenny"κ° λ°νλ κ²κ°μ§λ§ μ€μ λ‘λ null
-
λκ°μ μΈμ€ν΄μ€κ° κ°μ λμ΄μμμ μ£Όλͺ© νλλ HashMap μ μ½μ ν λ ν€λ‘ μ¬μ©λμκ³ μ²«λ²μ§Έμ λμΌν κ°μ κ°λ λλ²μ§Έ μΈμ€ν΄μ€λ κ²μ ν€μ μ¬μ©λμμ
-
PhoneNumber ν΄λμ€μμ hashCode λ©μλλ₯Ό μ€λ²λΌμ΄λ νμ§μμμ λ μΈμ€ν΄μ€κ° μλ‘λ€λ₯Έ ν΄μ μ½λ κ°μ κ°κ² λ κ²μ
-
λ°λΌμ get λ©μλμμλ put λ©μλμ μ μ₯ν μΈμ€ν΄μ€μ κ²κ³Ό λ€λ₯Έ ν΄μ λ²ν·(bucket)μμ PhoneNumber μΈμ€ν΄μ€λ₯Ό μ°Ύλλ€.
-
μ¬μ§μ΄ λ μΈμ€ν΄μ€κ° κ°μ λ²ν·μ λμ΄λλΌλ get λ©μλλ null μ λ°ννλ κ²μ
-
HashMap μ κ° νλͺ©κ³Ό μ°κ΄λ ν΄μ μ½λλ₯Ό μ μ₯νλ μ΅μ ν μ½λλ₯Ό κ°κ³ μμ΄ ν΄μμ½λκ°μ΄ μΌμΉνμ§ μμΌλ©΄ κ°μ²΄μ λμΌ μ¬λΆλ₯Ό νμΈνμ§ μκΈ° λλ¬Έμ΄λ€.
-
hoshCode λ©μλ μΆκ°νλ©΄ ν΄κ²°λ¨ νμ§λ§ λ°μμ²λΌ μ λ μ΄λ κ² μ¬μ©νλ©΄μλ¨
@Override public int hashCode(){ return 42; }-
λμΌν κ°μ²΄λ€μ΄ κ°μ ν΄μγ λλ₯Ό κ°κ² λλ―λ‘ μ΄ λ©μλλ μ λ²νλ€.
-
νμ§λ§ λͺ¨λ κ°μ²΄κ° λ€ λκ°μ ν΄μμ½λλ₯Ό κ°κ² λλ μ΅μ μ λ©μλ
-
λͺ¨λ κ°μ²΄λ€μ κ°μ λ²ν·μ μμΉνλ―λ‘ μ΄ κ°μ²΄λ€μ μ μ₯νλ ν΄μ 컬λ μ (HashMap, HashSet, Hashtable)μμλ λ§ν¬ 리μ€νΈ(linked list)λ₯Ό λ€μ μμ±νλ€.
- κ²°κ΅ νλ‘κ·Έλ¨μ κ°μ²΄μμ μ νμ μΌλ‘ λΉλ‘νμ¬ λλ¦¬κ² μ€νλ μ λ°μ μμ ν°ν΄μ 컬λ μ λ€μ κ²½μ° λμμ΄ λλμ§ μμ¬λ μ λλ‘ μ¬κ°ν μ±λ₯μ°¨μ΄
-
μ’μ ν΄μ λ©μλλ λμΌνμ§ μμ κ°μ²΄λ€μ λν΄ μλ‘ λ€λ₯Έ ν΄μ μ½λλ₯Ό λ§
-
ν΄μ¬μ½λ 겨μ κ· μΌνκ² λΆν¬νλ λ°©λ²
- μλ₯Ό λ€μ΄ 17κ³Ό κ°μ΄ 0μ΄ μλ μ΄λ€ μμ κ°μ result λΌλ int λ³μμ μ μ₯νλ€.
- μ°λ¦¬ κ°μ²΄μ κ° μ£Όμνλ(equals λ©μλμμ λΉκ΅νλ)fμ λν΄ λ€μμ μννλ€.
a. κ° νλμ λν int νμ μ ν΄μ μ½λ cλ₯Ό λ€μκ³Όκ°μ΄ μ°μΆνλ€.
- νλ fκ° boolean νμ μ΄λ©΄ (f ? 1 : 0)
- νλ fκ° byte, char, short, int νμ μ΄λ©΄, (int) f
- νλ fκ° long νμ μ΄λ©΄ (int) (f ^(f >>>32))
- νλ fκ° float νμ μ΄λ©΄ Float.floatToIntBits(f).
- νλ fκ° double νμ μ΄λ©΄, Double.doubleToLongBits(f)λ₯Ό μ€ννν λ°νλ long νμ μ κ°μ μμ 2.a.3 μ²λΌ μ²λ¦¬ν΄μ ν΄μμ½λ κ°μ ꡬνλ€
- νλ fκ° κ°μ²΄ μ°Έμ‘°μΌ κ²½μ°λ νμ¬(equals λ©μλκ° νΈμΆλ)κ°μ²΄μ equals λ©μλμμ κ·Έ νλλ₯Ό λΉκ΅νκΈ° μν΄ fκ° μ°Έμ‘°νλ κ°μ²΄μ equals λ©μλλ₯Ό μ¬κ·μ μΌλ‘ νΈμΆνλ€.
- κ·Έλ¬λ©΄ κ·Έ κ°μ²΄μ νλμ λν΄ hashCode λ©μλλ μ¬κ·μ μΌλ‘ νΈμΆλλ€.
- λ§μΌ λ 볡μ‘ν λΉκ΅κ° νμνλ€λ©΄ νλμ νμ€ νμμ λ§λ€μ΄ μ²λ¦¬νκ³ κ·Έ νμ€νμμ λν΄ hashCode λ©μλλ₯Ό νΈμΆνλ€.
- λ§μΌ νλ fμ κ°μ΄ null μ΄λ©΄ 0μ λ°ννλ€.(λλ€λ₯Έ μ΄λ€ μμ κ°λ κ°λ₯νμ§λ§ κ΄λ‘μ μΌλ‘ 0μ μ¬μ©νλ€.)
- νλ fκ° λ°°μ΄μ΄λΌλ©΄ λ°°μ΄μ κ° μμμ λ³κ°μ νλμ²λΌ μ²λ¦¬νλ€. μ¦ μμ κ·μΉλ€μ μ μ©νμ¬ μ²λ¦¬ν΄μΌν μμ κ°κ°μ ν΄μμ½λ κ°μ μ°μΆ
- λ°λ‘ 2.b μμμ μ΄μ©νμ¬ κ·Έκ°λ€μ ν©μ ꡬνλ€
- λ§μΌ λ°°μ΄ νλμ λͺ¨λ μμλ₯Ό μ²λ¦¬ν΄μΌλλ€λ©΄ μλ° 1.5 λ²μ μ μΆκ°λμ΄ μ€λ²λ‘λ©λ Arrays.hashCode λ©μλλ€ μ€ νλλ₯Ό μ¬μ©ν μμλ€.
b. μμ 2.a λ¨κ³μμ ꡬν ν΄μμ½λ cλ₯Ό resultμ ν©κ³νλ€. - result = 31 * result + c; 3. resultλ₯Ό λ°ννλ€. 4. hashCode λ©μλ μμ±μ΄ λλλ©΄ λμΌν μΈμ€ν΄μ€λ€μ΄ κ°μ κ°μ ν΄μμ½λλ₯Ό κ°λμ§ κ²ν νμ - λ¨μ ν μ€νΈλ₯Ό μμ±νμ¬ μ μ€ν λλμ§ κ²μ¦, λ§μΌ λμΌν μΈμ€ν΄μ€λ€μ΄ μλ‘ λ€λ₯Έ ν΄μμ½λ κ°μ κ°λλ€λ©΄ κ·Έ μ΄μ λ₯Ό μ°Ύμ λ¬Έμ λ₯Ό ν΄κ²°
@Override public int hashCode(){
int result=17;
result = 31 * result + areaCode;
result = 31 * result + prefix;
result = 31 * result + lineNumber;
return result;
}-
μ΄ λ©μλμμ PhoneNumber μΈμ€ν΄μ€ μΈκ°μ§ μ€μ νλλ§μΌλ‘ κ°λ¨ν μ°μ°ν κ²°κ³Όλ₯Ό λ°ννλ―λ‘ λμΌν PhoneNumber μΈμ€ν΄μ€λ€μ λκ°μ ν΄μ μ½λ κ°μ κ°λλ€.
-
PhoneNumber μ λ§κ² μλ²½νκ² κ΅¬νλ hashCodeλ‘μ¨ μλ° νλ«νΌ λΌμ΄λΈλ¬λ¦¬μ κ²κ³Ό λλ±
-
μ΄ λ©μλλ κ°λ¨νκ³ μ€νμλκ° λΉ λ₯΄λ€. κ·Έλ¦¬κ³ λμΌνμ§ μμ phoneNumber μΈμ€ν΄μ€λ€μ μλ‘ λ€λ₯Έ ν΄μ λ²ν·μ μ λΆμ°μν¨λ€.
-
λΆλ³μ΄λ©΄μ ν΄μ μ½λ μ°μ° λΉμ©μ΄ μ€μν ν΄λμ€λΌλ©΄ ν΄μ κ°μ΄ λ§€λ² νμν λλ§λ€ κ³μ°νλκ² λ³΄λ€λ κ°μ²΄ λ΄λΆμ ν΄μμ½λλ₯Ό μ μ₯νλ κ²μ κ³ λ €ν΄λ³Όμμμ
-
κ·Έλ° νμ μ κ°μ²΄λ€μ ν΄μν€λ‘ μ¬μ©ν κ±°λΌλ©΄ μΈμ€ν΄μ€κ° μμ±λ λ ν΄μμ½λλ₯Ό μ°μΆν΄μΌν¨
-
κ·Έλ μ§ μλ€λ©΄ hashCode λ©μλκ° μ΅μ΄ νΈμΆλ λ λ¦μ μ΄κΈ°ν(Lazy initialization) ν μμμ
// Lazy initialization νλ©΄μ κ°μ²΄μ ν΄μμ½λλ₯Ό μ μ₯
private volatile int hashCode;
@Override
public int hashCode(){
int result = hashCode;
if( result == 0){
result = 17;
result = 31 * result + areaCode;
result = 31 * result + prefix;
result = 31 * result + lineNumber;
hoshCode = result;
}
return result;
}- ν΄μμ½λλ₯Ό μ°μΆν λλ μ±λ₯ νμμ μ΄μ λ‘ κ°μ²΄μ μ€μ λΆλΆμ μ μΈμν€μ§λ§μ.
- κ·Έλ‘ μΈν΄ ν΄μλ©μλμ μ€νμλλ λλΉ¨λΌμ§μ μμ§λ§ νμ§ μ νλ‘ μΈν΄ λ무 λλ € μ¬μ© λΆκ°λ₯ν μ λκΉμ§ ν΄μ ν μ΄λΈλ€μ μ±λ₯μ λ¨μ΄ νΈλ¦΄μμμ
- μ± μ΄νν°λΈμλ°