java.lang.String is not java.lang.String
Thanks for the great project!
Somehow in pytests I can end up with this error:
from java.lang import String
> assert type(a) is String, f"not a string: {type(a)}"
E AssertionError: not a string: <java class 'java.lang.String'>
It happens in a multiprocessing-heavy context. Otherwise I did not investigate much into it (need to run a very large test suite to reproduce). Worth noting that it is probably not related to serializing the object because it would otherwise simply fail during serialization.
jpype 1.6.0 cpython 3.9.18
Unfortunately while Java strings and Python string seem compatible they sadly are not. Use ‘str(x)’ on a Java string if you want a Python one.
The funny thing is, it is a part of the function that converts String to str
def jstr(a: Any) -> str:
from java.lang import String
assert type(a) is String, f"not a string: {type(a)}"
return str(a)
I used it for debugging purposes mostly to ensure that I do not convert something non-String to str. Ended up with this one
def jstr(a: Any) -> str:
assert str(type(a)) == "<java class 'java.lang.String'>", f"not a string: {type(a)}"
return str(a)
Not a big deal for sure: just wondering what happens here.
I am guessing that you are hit by the fact that back end has multiple String instances and you are checking “is”. Likely you meant isinstance(a, JString) which would be safer as then you would have caught the internal subtyping properly.
import jpype jpype.startJVM() j =jpype.JString("a") j.class.mro (<java class 'java.lang.String'>, <java class 'java.io.Serializable'>, <java class 'java.lang.Comparable'>, <java class '_jpype._JComparable'>, <java class 'java.lang.CharSequence'>, <java class 'java.lang.constant.Constable'>, <java class 'java.lang.constant.ConstantDesc'>, <java class 'java.lang.Object'>, <java class '_jpype._JObject'>, <class 'object'>) jpype.JString.mro (<java class 'JString'>, <java class '_jpype._JObject'>, <class 'object'>)
isinstance(j, jpype.JString) True isinstance(j, jpype.java.lang.String) True
As you can see string is a complex set of wrappers not a simple type. So “is” won’t work. Depending on whether you are passing a String created in Java or something that Python can cast to a String will give different type trees. And during startup some String instances must be created before the formal string is declared adding to the confusion as to which wrapper type you may have.