Come leggere il valore di un campo privato da una classe diversa in Java?


Answers

Prova FieldUtils da apache commons-lang3:

FieldUtils.readField(object, fieldName, true);
Question

Ho una classe mal progettata in un JAR terze parti e devo accedere a uno dei suoi campi privati . Ad esempio, perché dovrei scegliere un campo privato è necessario?

class IWasDesignedPoorly {
    private Hashtable stuffIWant;
}

IWasDesignedPoorly obj = ...;

Come posso usare la riflessione per ottenere il valore di stuffIWant ?




Un'altra opzione che non è stata ancora menzionata: usa Groovy . Groovy ti consente di accedere a variabili di istanza private come effetto collaterale del design della lingua. Che tu abbia o meno un getter per il campo, puoi semplicemente usarlo

def obj = new IWasDesignedPoorly()
def hashTable = obj.getStuffIWant()



Se si utilizza Spring, ReflectionTestUtils fornisce alcuni strumenti utili che aiutano in questo modo con il minimo sforzo. È descritto come "da utilizzare in scenari di test di unità e integrazione" . Esiste anche una classe simile chiamata ReflectionUtils ma che è descritta come "Destinata solo ad uso interno" - vedi questa risposta per un'interpretazione di cosa significa.

Per indirizzare l'esempio pubblicato:

Hashtable iWantThis = (Hashtable)ReflectionTestUtils.getField(obj, "stuffIWant");



Devi fare quanto segue:

private static Field getField(Class<?> cls, String fieldName) {
    for (Class<?> c = cls; c != null; c = c.getSuperclass()) {
        try {
            final Field field = c.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field;
        } catch (final NoSuchFieldException e) {
            // Try parent
        } catch (Exception e) {
            throw new IllegalArgumentException(
                    "Cannot access field " + cls.getName() + "." + fieldName, e);
        }
    }
    throw new IllegalArgumentException(
            "Cannot find field " + cls.getName() + "." + fieldName);
}



Come menziona oxbow_lakes, puoi usare il reflection per aggirare le restrizioni di accesso (presumendo che SecurityManager ti consenta).

Detto questo, se questa classe è progettata così male da farti ricorrere a questo tipo di hackery, forse dovresti cercare un'alternativa. Certo, questo piccolo trucco potrebbe farti risparmiare qualche ora, ma quanto ti costerà?






Links