...
Code Block |
---|
|
public final class CaseInsensitiveString {
private String s;
public CaseInsensitiveString(String s) {
if (s == null) {
throw new NullPointerException();
}
this.s = s;
}
//This method violates asymmetry
public boolean equals(Object o) {
if (o instanceof CaseInsensitiveString) {
return s.equalsIgnoreCase(((CaseInsensitiveString)o).s);
}
if (o instanceof String) {
return s.equalsIgnoreCase((String)o);
}
return false;
}
public static void main(String[] args) {
CaseInsensitiveString cis = new CaseInsensitiveString("Java""Java");
String s = "java""java";
System.out.println(cis.equals(s)); // Returns true
System.out.println(s.equals(cis)); // Returns false
}
}
|
...
Code Block |
---|
|
public final class CaseInsensitiveString {
private String s;
public CaseInsensitiveString(String s) {
if (s == null) {
throw new NullPointerException();
}
this.s = s;
}
public boolean equals(Object o) {
return o instanceof CaseInsensitiveString &&
((CaseInsensitiveString)o).s.equalsIgnoreCase(s);
}
public static void main(String[] args) {
CaseInsensitiveString cis = new CaseInsensitiveString("Java""Java");
String s = "java""java";
System.out.println(cis.equals(s)); // Returns false now
System.out.println(s.equals(cis)); // Returns false now
}
}
|
...
Code Block |
---|
|
public class Card {
private final int number;
public Card(int number) {
this.number = number;
}
public boolean equals(Object o) {
if (!(o instanceof Card)) {
return false;
}
Card c = (Card)o;
return c.number == number;
}
}
class XCard extends Card {
private String type;
public XCard(int number, String type) {
super(number);
this.type = type;
}
public boolean equals(Object o) {
if (!(o instanceof Card)) {
return false;
}
// Normal Card, do not compare type
if (!(o instanceof XCard)) {
return o.equals(this);
}
// It is an XCard, compare type as well
XCard xc = (XCard)o;
return super.equals(o) && xc.type == type;
}
public static void main(String[] args) {
XCard p1 = new XCard(1, "type1""type1");
Card p2 = new Card(1);
XCard p3 = new XCard(1, "type2""type2");
System.out.println(p1.equals(p2)); // Returns true
System.out.println(p2.equals(p3)); // Returns true
System.out.println(p1.equals(p3)); // Returns false, violating transitivity
}
}
|
...
Code Block |
---|
|
public class Card {
private final int number;
public Card(int number) {
this.number = number;
}
public boolean equals(Object o) {
if (!(o instanceof Card)) {
return false;
}
Card c = (Card)o;
return c.number == number;
}
}
class XCard extends Card {
private String type;
private Card card;
public XCard(int number, String type) {
super(number);
this.type = type;
}
public Card viewCard() {
return card;
}
public boolean equals(Object o) {
if (!(o instanceof XCard)) {
return false;
}
XCard cp = (XCard)o;
return cp.card.equals(card) && cp.type.equals(type);
}
public static void main(String[] args) {
XCard p1 = new XCard(1, "type1""type1");
Card p2 = new Card(1);
XCard p3 = new XCard(1, "type2""type2");
System.out.println(p1.equals(p2)); // Returns false
System.out.println(p2.equals(p3)); // Returns false
System.out.println(p1.equals(p3)); // Returns false
}
}
|
Wiki Markup |
---|
""There are some classes in the Java platform libraries that do extend an instantiable class and add a value component. For example, {{java.sql.Timestamp}} extends {{java.util.Date}} and adds a nanoseconds field. The {{equals}} implementation for {{Timestamp}} does violate symmetry and can cause erratic behavior if {{Timestamp}} and {{Date}} objects are used in the same collection or are otherwise intermixed."" \[[Bloch 08|AA. Java References#Bloch 08]\] |
...
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[API 06|AA. Java References#API 06]\] [method equals()|http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#equals(java.lang.Object)]
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 8: Obey the general contract when overriding equals
\[[Darwin 04|AA. Java References#Darwin 04]\] 9.2 Overriding the equals method |
...
MET05-J. Validate method parameters 12. Methods (MET) MET31-J. Ensure that hashCode() is overridden when equals() is overridden