two equal objects, but different classes?

When programming on binding Referenceable object with JDK version 1.5.0_06, I have encountered a very strange phenomenon: two objects are equal, but they belong to different classes!!!

The source codes of the program bind_ref.java are listed as below:

+++++++++++++++++++++++++++++++++++++++++++++++++++++++

import java.lang.*;

import java.io.*;

import java.util.*;

import javax.naming.*;

import javax.naming.spi.ObjectFactory;

import java.util.Hashtable;

public class bind_ref {

public static void main( String[] args ) {

// Set up environment for creating the initial context

Hashtable env = new Hashtable();

env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory" );

env.put( Context.PROVIDER_URL, "file:/daniel/" );

Context ctx = null;

File f = null;

Fruit fruit1 = null, fruit2 = null;

byte [] b = new byte[10];

try {

ctx = new InitialContext( env );

Hashtable the_env = ctx.getEnvironment();

Object [] keys = the_env.keySet().toArray();

int key_sz = keys.length;

fruit1 = new Fruit( "Orange" );

SubReference ref1 = fruit1.getReference();

ctx.rebind( "reference", fruit1 );

fruit2 = ( Fruit )ctx.lookup( "reference" );

System.out.println( "ref1's class = (" + ref1.getClass().toString() + ")" );

System.out.println( "fruit2.myRef's class = (" + fruit2.myRef.getClass().toString() + ")" );

System.out.println( "( ref1 instanceof SubReference ) = " + ( ref1 instanceof SubReference ) );

System.out.println( "( fruit2.myRef instanceof SubReference ) = " + ( fruit2.myRef instanceof SubReference ) );

System.out.println( "ref1.hashCode = " + ref1.hashCode() + ", fruit2.myRef.hashCode = " + fruit2.myRef.hashCode() );

System.out.println( "ref1.equals( fruit2.myRef ) = " + ref1.equals( fruit2.myRef ) );

} catch( Exception ne ) {

System.err.println( "Exception: " + ne.toString() );

System.exit( -1 );

}

}

}

+++++++++++++++++++++++++++++++++++++++++++++++++++++++

All the outputs are shown as below:

=======================================================

Fruit: I am created at Mon Jun 18 11:35:13 GMT+08:00 2007

SubReference: I am created at Mon Jun 18 11:35:13 GMT+08:00 2007

(i)subref.hashCode() = (-1759114666)

SubReference: I am created at Mon Jun 18 11:35:13 GMT+08:00 2007

(i)subref.hashCode() = (-1759114666)

FruitFactory: obj's class = (class javax.naming.Reference)

FruitFactory: obj's hashCode = -1759114666

FruitFactory: obj = (Reference Class Name: Fruit

Type: fruit

Content: Orange

)

FruitFactory: ( obj instanceof SubReference ) = false

FruitFactory: subref_class_name = (Fruit)

Fruit: I am created at Mon Jun 18 11:35:13 GMT+08:00 2007

ref1's class = (class SubReference)

fruit2.myRef's class = (class javax.naming.Reference)

( ref1 instanceof SubReference ) = true

( fruit2.myRef instanceof SubReference ) = false

ref1.hashCode = -1759114666, fruit2.myRef.hashCode = -1759114666

ref1.equals( fruit2.myRef ) = true

========================================================

I hightlight the critical codes and outputs related to the strangeness with bold texts.

Who can tell me what happens? Is it really possible that two objects belonging to different classes are equal? If so, why that?

[3566 byte] By [liaodongyana] at [2007-11-27 7:57:42]
# 1

I don't know what Referenceable is, and I'm not going to read all that unformatted code. It's not that uncommon for two objects of different classes to be equal though.

For instance, java.util.List is an interface, and its equals contract specifies that two Lists are equal if all their elements are equal and in the same order. So a LinkedList containing {"A", "B", "C"} would be equal to an ArrayList containing {"A", "B", "C"}. If the two classes here implement a common interface or extend a common base class, it might be valid for them to be equal.

jverda at 2007-7-12 19:39:35 > top of Java-index,Java Essentials,Java Programming...
# 2

It can also depend on how you implement the equals method.

class Cat {

String name;

Cat(String n) {

name = n;

}

}

class Dog {

String name;

Dog(String n) {

name = n;

}

public boolean equals(Object o) {

return name.equals(o.name);

}

public static void main(String[] args) {

Dog d = new Dog("Fred");

Cat c = new Cat("Fred");

System.out.println(d.equals(c));

}

}

floundera at 2007-7-12 19:39:35 > top of Java-index,Java Essentials,Java Programming...
# 3
Um... What are you going to cast that object to so that name will exist?
jverda at 2007-7-12 19:39:35 > top of Java-index,Java Essentials,Java Programming...
# 4
Also, since Cat doesn't override equals, you're violating symmetry.
jverda at 2007-7-12 19:39:35 > top of Java-index,Java Essentials,Java Programming...
# 5
Ahhhh shaddup ;)It was a very contrived example.
floundera at 2007-7-12 19:39:35 > top of Java-index,Java Essentials,Java Programming...
# 6
> Ahhhh shaddup ;)> > It was a very contrived example.I know. It seems that to make it realistic (i.e., will actually compile), however, it would have to be like the situation I described--e.g. Cat and Dog both extend mammal.
jverda at 2007-7-12 19:39:35 > top of Java-index,Java Essentials,Java Programming...
# 7

Woot!

Just noticed my upgrade.

Shiny! Shiny!

Bad times behind me.

As for the example I was trying more to show that you could, if you wanted to, make any two objects appear to be equal. I guess the ultimate would be:

public boolean equals(Object other) {

return true;

}

floundera at 2007-7-12 19:39:35 > top of Java-index,Java Essentials,Java Programming...