<< Unit Tests Are Not Enough | Home | Reintroducing Jini 2.1 >>

Friday Java Quiz: Object Identity

Kevin IM-ed me yesterday with the following question:

How come foo.getBar() == expectedBar is true yet foo.getBar().equals(expectedBar) is false?

I'll make that today's Java quiz: Have you encountered a situation in non-play code where obj1 == obj2 is true yet obj1.equals(obj2) is false?

By non-play code I mean a code base where all equals() and hashCode() overrides honor their contracts. In other words, there are no silly code like

public boolean equals(Object other) {
  return false;
}
Tags :


Re: Friday Java Quiz: Object Identity

WATCHOUT: SPOILER!

Think of i n h e r i t a n c e

Separate class proxies considered harmful

This can happen if you create a *separate* proxy out of a concrete class and the proxied equals method accesses fields. I think both Spring and Hibernate do this. Technically, the user's equals method abides by the contract, but evil frameworks can break it. Note that making the proxy and your object the same instance (like Guice does) doesn't have this problem, nor does proxying interfaces.

Separate class proxies considered harmful

Note also that a framework could check for == in the generated proxy, but this won't work if proxy could forward to multiple different objects.

Re: Friday Java Quiz: Object Identity

This simply breaks equals contract. Please bear in mind that proper equals method should be reflexive, symmetric and transitive. Reflexive means that a.euals(a) should return true. Your example breaks this very rule.

Re: Friday Java Quiz: Object Identity

The implementation of Foo must be suspect, e.g.:
class Foo {
  boolean equals(Object o) {
    return false;
  }
}

Re: Friday Java Quiz: Object Identity

It's gotta be something to do with autoboxing.

Re: Friday Java Quiz: Object Identity

A mutable class with the value-based equality semantics in a concurrent environment?

Re: Friday Java Quiz: Object Identity

It's quite common to start equals() with checking the class membership, e.g., if(!otherObject instanceof MyClass) {return false;}. This becomes problematic if MyClass is loaded by sibling class loaders (such as, two Web apps) and the call is made across the classloader boundary.

Re: Friday Java Quiz: Object Identity

In that case, == wouldn't work either.

Re: Friday Java Quiz: Object Identity

Sure would... Say, some code in CL1 calls method areEqual(obj1, obj2) where both variables point to the same actual instance created in CL2. The instance(s) are passed through a reference to java.lang.Object OTOH, == is "JVM global". What am I missing?

Re: Friday Java Quiz: Object Identity

That's not how it works. No matter what, you have a single instance which can only have one class (the class loaded in CL2).

Re: Friday Java Quiz: Object Identity

int y = 1;
Long x = 1L;
System.out.println(x == y);
System.out.println(x.equals(y));

Re: Friday Java Quiz: Object Identity

I'd go with the for the classloader exp. Is Bob implying that that proxy equals modifies the fields ?

Add a comment Send a TrackBack