Question

I have written a Java class to practice reflection. This is a shorten version that gets right to the problem:

import org.apache.commons.lang3.builder.CompareToBuilder;

public class StringExample {
public StringExample(){
    String[] persons = {"John","Paul","George","Ringo"};
    System.out.println("Person 1\tPerson2\t->\tString.compareTo\tReflection\t\tDifferent?\n");
    for (int i=0;i<persons.length;i++)
        for (int j=0;j<persons.length;j++) {

// Here the problem arises

            int sct = signum(persons[i].compareTo(persons[j])),
                    rct = signum(CompareToBuilder.reflectionCompare(persons[i], persons[j]));
            System.out.println(persons[i]+"\t:\t"+persons[j]+"\t->\t"+sct+"\t\t|\t"+rct+"\t\t->\t"+(sct==rct?"ok":"fault"));
        }
}

private int signum(int x) {
    if (x<0)
        return -1;
    if (x>0)
        return 1;
    return 0;
}

public static void main(String[] a){
    new StringExample();
}
}

Output:

Person 1 Person2 -> String.compareTo Reflection Different?

John : John -> 0 | 0 -> ok

John : Paul -> -1 | -1 -> ok

John : George -> 1 | -1 -> fault

John : Ringo -> -1 | -1 -> ok

Paul : John -> 1 | 1 -> ok

Paul : Paul -> 0 | 0 -> ok

Paul : George -> 1 | -1 -> fault

Paul : Ringo -> -1 | -1 -> ok

George : John -> -1 | 1 -> fault

George : Paul -> -1 | 1 -> fault

George : George -> 0 | 0 -> ok

George : Ringo -> -1 | 1 -> fault

Ringo : John -> 1 | 1 -> ok

Ringo : Paul -> 1 | 1 -> ok

Ringo : George -> 1 | -1 -> fault

Ringo : Ringo -> 0 | 0 -> ok

"fault" indicates where CompareToBuilder.reflectionCompare returns a signum different from String's own compareTo method. I found this only with String (neither Integer, nor int, nor Double, nor double, nor own classes implementing Comparable).

Please help me: Why is this happening?

Was it helpful?

Solution

The problem with CompareToBuilder and Strings is that the CompareToBuilder reflectively takes all fields into account when comparing two objects. Besides the char array which contains the String, a String additionally stores its size internally explicitly. The reflective comparison takes this into account as well leading to the strange behaviour.

You can actually see all Sting fields in a debugger. Integer, Double, etc. do only have their value as field, hence, there it works.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top