Mit ‘equals’ getaggte Artikel

Klassenvergleich bei der Verwendung von CGLIB

Montag, 09. Juni 2008

Wird die Java Bibliothek CGLIB zur dynamischen Kapselung von Klassen verwendet, kann es dazu kommen, dass beim Vergleich der Klassen zweier Instanzen ein Fehler auftritt.

Beispiel soll hier eine überschriebene Equals-Methode sein:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public boolean equals(Object obj) {
    boolean isEqual = false;
    if (obj == null) {
        isEqual = false;
    } else if (this == obj) {
        isEqual = true;
    } else if (!(obj instanceof Superklasse)) {
        isEqual = false;
    /* Problematischer Vergleich */
    } else if (!this.getClass().equals(obj.getClass())) {
        isEqual = false;
    } else {
/* weitere Tests, z.B. mit einem EqualsBuilder */
    }
    return isEqual;
}

Der direkte Klassevergleich funtioniert nun nicht mehr, da es sich bei obj um eine Instanz der CGLIB-generierten Subklasse handelt.

Ein Möglichkeit ist die Aufweichung der Klassenbedingung:

!this.getClass().isAssignableFrom(obj.getClass())

Eine bessere die Verwendung der ClassUtils aus dem Spring Framework:

!this.getClass().equals(ClassUtils.getUserClass(obj))

Ersatzweise hier auch der benutzte Code aus der ClassUtils-Klasse:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public abstract class ClassUtils {
    /** The CGLIB class separator character "$$" */
    public static final String CGLIB_CLASS_SEPARATOR = "$$";
 
    /**
     * Return the user-defined class for the given instance: usually simply
     * the class of the given instance, but the original class in case of a
     * CGLIB-generated subclass.
     * @param instance the instance to check
     * @return the user-defined class
     */
    public static Class getUserClass(Object instance) {
        return getUserClass(instance.getClass());
    }
 
    /**
     * Return the user-defined class for the given class: usually simply the given
     * class, but the original class in case of a CGLIB-generated subclass.
     * @param clazz the class to check
     * @return the user-defined class
     */
    public static Class getUserClass(Class clazz) {
        return (clazz != null && clazz.getName().indexOf(CGLIB_CLASS_SEPARATOR) != -1 ?
                clazz.getSuperclass() : clazz);
    }
 
}

Hendrik Lange