Issue2153

classification
Title: Any string given to java.util.HashMap from Jython is always coerced into unicode
Type: behaviour Severity: normal
Components: Core Versions: Jython 2.7
process
Status: closed Resolution: invalid
Dependencies: Superseder:
Assigned To: Nosy List: santa4nt, zyasoft
Priority: Keywords:

Created on 2014-05-22.20:06:45 by santa4nt, last changed 2014-05-23.15:57:22 by zyasoft.

Messages
msg8568 (view) Author: Santoso Wijaya (santa4nt) Date: 2014-05-22.20:06:45
Is this not weird?

>>> d = {}
>>> d['a'] = 1
>>> d[1] = 'a'
>>> d[2] = b'b'
>>> d[b'b'] = 2
>>> d[3] = u'c'
>>> d[u'c'] = 3
>>> [e for e in d.iteritems()]
[(u'c', 3), ('b', 2), ('a', 1), (3, u'c'), (2, 'b'), (1, 'a')]
>>> from java.util import HashMap
>>> d = HashMap(d)
>>> for k in d:
...     print repr(k), repr(d[k])
... 
1 u'a'
2 u'b'
3 u'c'
u'b' 2
u'c' 3
u'a' 1
msg8572 (view) Author: Jim Baker (zyasoft) Date: 2014-05-23.15:55:38
It's a bit strange I agree. Let's see how it works out:

1. The type of the keys and values in d, the instance of HashMap in your example, is Object, not PyObject.

2. Jython, via __tojava__, takes your item (1, 'a') and converts the PyInteger, PyString to an java.lang.Integer and java.lang.String respectively. In the case of PyString, it actually just returns the underlying j.l.String used (the string field), but that's just an optimization (and one that's guaranteed to work because of string immutability). This is what is inserted into the HashMap d.

3. Later on you ask for item, eg, d[1]. Once again, the Python PyInteger is reboxed as j.l.Integer; it's looked up in the map d; it get backs a j.l.String. In order to work with this in Python, the j.l.String is reboxed (via Py.java2py), but not as a PyString, but as PyUnicode. This is because j.l.String actually corresponds to a Python unicode string.

You can also observe that the effect of reboxing in how object identity is lost:

>>> d = {}
>>> a = 'a'
>>> d[1] = a
>>> d[1] is a
True
>>> from java.util import HashMap
>>> d = HashMap(d)
>>> d[1]
u'a'
>>> d[1] is a
False

Jython 3.x would make most of this strangeness go away, per my message here: http://bugs.jython.org/msg8473
msg8573 (view) Author: Jim Baker (zyasoft) Date: 2014-05-23.15:57:22
Closing this out as the issue reported is expected behavior in Jython 2 since 2.5
History
Date User Action Args
2014-05-23 15:57:22zyasoftsetstatus: open -> closed
resolution: invalid
messages: + msg8573
2014-05-23 15:55:39zyasoftsetnosy: + zyasoft
messages: + msg8572
2014-05-22 20:06:45santa4ntcreate