|
From: Jim A. <ji...@tr...> - 2001-03-28 06:17:11
|
I wasn't sure whether to post to 'jython-user': but I think this brings
up something relevant for 'dev'...
I have just found a problem with my Java/Jython code that was driving me
crazy! It turns out it was because of the use of
'System.identityHashCode(key)' instead of 'key.hashCode()' in
PyStringMap. When I change the 3 occurences to 'key.hashCode()' all my
problems disappear.
I have included some test code below that demonstrates the problem. Am I
doing something I shouldn't be ?
If not, then the question is: is this a bug? Or will I create one by
changing the code? In general I have been trying to extend the Jython
classes when necessary to add/change functionality.
But I'm not sure what to do here: I can't see a reason in this case to
use 'identityHashCode' instead of 'hashCode()' since 'key' is only a
'String'. (In other classes that use PyObjects I can sort of see why you
might need 'identityHashCode' (?) )
If this can be a patch to Jython, I will leave my code in until I get a
new version. If not, I may try to reimplement the 'PyStringMap' method
in an extending class (?) or figure out some other workaround.
Thanks (Finn: nice job on the Complex Number bug !)
__o
Jim Adrig _ \<,_
ji...@tr... ' `/ ' `
___________ `-' `-'
=============================================
Here is some backround info from Sun's web site (1.1 Update changes):
http://java.sun.com/docs/books/jls/first_edition/html/1.1Update.html
%< ------------------------------------------
D.2.2 New Hashing Method
The default implementation of Object.hashCode is to return keys that are
likely to be different for different objects. As described on page 64,
many
classes override both hashCode and equals to provide different notions
of equality. However, sometimes you need the original notion of
equality, in
which all objects are different, even for an object that usually is used
with a broader notion. You can use == to test if two objects are the
same, but you will
need to use System.identityHashCode to hash the objects, since it
preserves the default implementation of hashCode in which all objects
are
considered different.
%< ------------------------------------------
=============================================
And the test code:
=============================================
// Set up two strings that look the same but are different internally:
String key1 = "TESTKEY";
String key2 = "12345" + "TESTKEY" ;
key2 = key2.substring(5); // This just adjusts the pointers
to the internal byte[]
System.out.println("keys are '.equal' ?" + key1.equals(key2) );
System.out.println("keys are '==' ?" + (key1 == key2));
// The 'identityHashCode' attempts to hash differently if it finds any
differences:
System.out.println("key1 identityHashCode:" +
System.identityHashCode(key1));
System.out.println("key2 identityHashCode:" +
System.identityHashCode(key2));
// The 'String' class does it's own 'hashCode' based on the actual
characters:
System.out.println("key1 HashCode:" + key1.hashCode());
System.out.println("key2 HashCode:" + key2.hashCode());
// -= This is the bug it causes: =-
PythonInterpreter python = new PythonInterpreter();
python.exec( "class TestClass: pass" );
// Get the Class Object:
PyClass classObject = (PyClass)python.get( "TestClass" );
// So we can build new instances of it dynamically:
PyInstance classInstance = new PyInstance( classObject );
// Add attributes dynamically to support syntax like
"BorrowerList[1].AssetList[1].AssetAmount" :
classInstance.__setattr__( key1, new PyString("In my code this is
actually a PyList object..." ));
// Looking it up using the original key1 works:
PyObject findIt1 = classInstance.__findattr__(key1);
System.out.println("Using 'key1' this is OK :" + findIt1);
// But even though key2 is '.equal' it doesn't work:
PyObject findIt2 = classInstance.__findattr__(key2);
System.out.println("But with 'key2' it is not :" + findIt2);
|