QString and Android String are not comparable??
-
Sorry if it was already discussed but I never met this in Internet. I did not find this in Qt Bug report site. Please let me know if I missed something.
I call Java function like this:
bool res = QAndroidJniObject::callStaticMethod<jboolean>( PCpath, "setAccountName", "(Ljava/lang/String;)Z", QAndroidJniObject::fromString( QString("stringInJavaCode") ).object<jstring>() ); qWarning()<<res;
The PCpath is static const char* string with proper content. The java method looks like:
public static boolean setAccountName( String accountName ) { //accountName = "stringInJavaCode"; if( accountName == "stringInJavaCode" ) // defenitely the same cause it was copy-pasted { DebugMessage("BUT IT IS TRUE!!!"); return true; } return false; }
And the output:
: (null):0 ((null)): false
Uncomment accountName assignment and it will print:
: (null):0 ((null)): "BUT IT IS TRUE!!!" : (null):0 ((null)): true
When printing both strings in Java code they are look identically. No difference. I suppose there was left invisible character from QString - the trailing '\0'. Looks like a bug in QAndroidJniObject::fromString() - it must convert QString content clearly. If there is trailing '\0' then it must be removed. Java strings are not null terminated. Backward conversion must add trailing zero.
-
Sorry if it was already discussed but I never met this in Internet. I did not find this in Qt Bug report site. Please let me know if I missed something.
I call Java function like this:
bool res = QAndroidJniObject::callStaticMethod<jboolean>( PCpath, "setAccountName", "(Ljava/lang/String;)Z", QAndroidJniObject::fromString( QString("stringInJavaCode") ).object<jstring>() ); qWarning()<<res;
The PCpath is static const char* string with proper content. The java method looks like:
public static boolean setAccountName( String accountName ) { //accountName = "stringInJavaCode"; if( accountName == "stringInJavaCode" ) // defenitely the same cause it was copy-pasted { DebugMessage("BUT IT IS TRUE!!!"); return true; } return false; }
And the output:
: (null):0 ((null)): false
Uncomment accountName assignment and it will print:
: (null):0 ((null)): "BUT IT IS TRUE!!!" : (null):0 ((null)): true
When printing both strings in Java code they are look identically. No difference. I suppose there was left invisible character from QString - the trailing '\0'. Looks like a bug in QAndroidJniObject::fromString() - it must convert QString content clearly. If there is trailing '\0' then it must be removed. Java strings are not null terminated. Backward conversion must add trailing zero.
@gourmet
interesting, it shouldn'tthis is the fromString function
QJNIObjectPrivate QJNIObjectPrivate::fromString(const QString &string) { QJNIEnvironmentPrivate env; jstring res = env->NewString(reinterpret_cast<const jchar*>(string.constData()), string.length()); QJNIObjectPrivate obj(res); env->DeleteLocalRef(res); return obj; }
QString::length returns the number of chars that excludes the 0 termination QString("Hello").length() == 5
what do you get, when you log the string and the length of the string on the Java side?
-
@gourmet
interesting, it shouldn'tthis is the fromString function
QJNIObjectPrivate QJNIObjectPrivate::fromString(const QString &string) { QJNIEnvironmentPrivate env; jstring res = env->NewString(reinterpret_cast<const jchar*>(string.constData()), string.length()); QJNIObjectPrivate obj(res); env->DeleteLocalRef(res); return obj; }
QString::length returns the number of chars that excludes the 0 termination QString("Hello").length() == 5
what do you get, when you log the string and the length of the string on the Java side?
@j-hilk Of course length() function excludes trailing zero. This is not a visible character and it is not taken in QString comparison.
@j-hilk said in QString and Android String are not comparable??:
when you log the string and the length of the string on the Java side?
Prints equal sizes.
public static boolean setAccountName( String accountName ) { String line = "stringInJavaCode"; if( accountName == line ) // defenitely the same cause it was copy-pasted { DebugMessage("BUT IT IS TRUE!!!"); return true; } DebugMessage(accountName.length()+" "+line.length()); return false; }
: (null):0 ((null)): "16 16" : (null):0 ((null)): false
-
@j-hilk Of course length() function excludes trailing zero. This is not a visible character and it is not taken in QString comparison.
@j-hilk said in QString and Android String are not comparable??:
when you log the string and the length of the string on the Java side?
Prints equal sizes.
public static boolean setAccountName( String accountName ) { String line = "stringInJavaCode"; if( accountName == line ) // defenitely the same cause it was copy-pasted { DebugMessage("BUT IT IS TRUE!!!"); return true; } DebugMessage(accountName.length()+" "+line.length()); return false; }
: (null):0 ((null)): "16 16" : (null):0 ((null)): false
well, to investigate further I suggest the following:
public static boolean setAccountName( String accountName ) { String line = "stringInJavaCode"; int l1 = accountName.length(); int l2 = line.length(); int lmin = Math.min(l1, l2); for (int i = 0; i < lmin; i++) { int str1_ch = (int)str1.charAt(i); int str2_ch = (int)str2.charAt(i); if(str1_ch != str2_ch) //Diff at index i DebugMessage("Diff here"); } if( accountName == line ) // defenitely the same cause it was copy-pasted { DebugMessage("BUT IT IS TRUE!!!"); return true; } DebugMessage(accountName.length()+" "+line.length()); return false; }
Actually, in Java, == tests for reference equality (wether they are the same object) and .equals() tests for value equality (wether they are logically equal)
// These two have the same value new String("test").equals("test") // --> true // ... but they are not the same object new String("test") == "test" // --> false // ... neither are these new String("test") == new String("test") // --> false
I guess,
working as indented... -
well, to investigate further I suggest the following:
public static boolean setAccountName( String accountName ) { String line = "stringInJavaCode"; int l1 = accountName.length(); int l2 = line.length(); int lmin = Math.min(l1, l2); for (int i = 0; i < lmin; i++) { int str1_ch = (int)str1.charAt(i); int str2_ch = (int)str2.charAt(i); if(str1_ch != str2_ch) //Diff at index i DebugMessage("Diff here"); } if( accountName == line ) // defenitely the same cause it was copy-pasted { DebugMessage("BUT IT IS TRUE!!!"); return true; } DebugMessage(accountName.length()+" "+line.length()); return false; }
Actually, in Java, == tests for reference equality (wether they are the same object) and .equals() tests for value equality (wether they are logically equal)
// These two have the same value new String("test").equals("test") // --> true // ... but they are not the same object new String("test") == "test" // --> false // ... neither are these new String("test") == new String("test") // --> false
I guess,
working as indented...