Pobieranie wartości publicznego statycznego pola końcowego / właściwości klasy w Javie poprzez odbicie

103

Powiedz, że mam zajęcia:

public class R {
    public static final int _1st = 0x334455;
}

Jak mogę uzyskać wartość „_1st” poprzez odbicie?

Viet
źródło
R._1stnie mógł działać? Jeśli mówisz o programowaniu na Androida, myślę, że Rklasa jest zawsze tam ...
Matthieu
@Matthieu Też tak myślałem, aż do dziś, kiedy musiałem robić to samo, ale tylko z BRklasą.
Sevastyan Savanyuk

Odpowiedzi:

132

Najpierw pobierz właściwość pola klasy, a następnie możesz pobrać wartość. Jeśli znasz typ, możesz użyć jednej z metod get z wartością null (tylko w przypadku pól statycznych, w rzeczywistości w przypadku pól statycznych argument przekazany do metody get jest całkowicie ignorowany). W przeciwnym razie możesz użyć getType i napisać odpowiedni przełącznik jak poniżej:

Field f = R.class.getField("_1st");
Class<?> t = f.getType();
if(t == int.class){
    System.out.println(f.getInt(null));
}else if(t == double.class){
    System.out.println(f.getDouble(null));
}...
M. Jessup
źródło
dzięki. Próbowałem, ale to nie zadziałało. Wyjątek jest zgłaszany w operacji f.getInt (null). Złapałem to, ale dlaczego jest wyjątek?
Viet
1
Jaki wyjątek otrzymałeś?
M. Jessup,
Cześć, wyjątek e.getMessage () zwraca nazwę pola, czyli „_1st” i nic więcej.
Viet
1
Ale jaki jest rodzaj wyjątku? (tj. NullPointerException, SecurityException, ...)
M. Jessup
2
Dlaczego dokumentacja nigdy nie wspomina, że getInt()ignoruje przekazany argument? Spędził wiele godzin na próbach przeniesienia instancji klasy.
Sevastyan Savanyuk
70
 R.class.getField("_1st").get(null);

Obsługa wyjątków pozostawia się czytelnikowi jako ćwiczenie.

Zasadniczo otrzymujesz pole jak każde inne przez odbicie, ale kiedy wywołujesz metodę get, przekazujesz wartość null, ponieważ nie ma instancji do działania.

Działa to dla wszystkich pól statycznych, niezależnie od tego, czy są ostateczne. Jeśli pole nie jest publiczne, musisz setAccessible(true)najpierw je wywołać i oczywiście SecurityManager musi zezwolić na to wszystko.

Yishai
źródło
Mam to. Klasa, której potrzebowałem, to właściwie R.id. Dzięki za pomoc!
Viet
1

Szedłem tą samą trasą (przeglądałem wygenerowaną klasę R) i wtedy miałem takie okropne wrażenie, że prawdopodobnie była to funkcja w klasie Resources. Miałem rację.

Znaleziono to: Resources :: getIdentifier

Pomyślałem, że to może zaoszczędzić ludziom trochę czasu. Chociaż mówią, że jest to zniechęcone w dokumentach, co nie jest zbyt zaskakujące.

Brian
źródło
Więc wywnioskowałeś, że to kwestia Androida. Powinien być wskazany w tagach ...
Matthieu
To nie jest kwestia Androida, to pytanie refleksyjne dotyczące języka Java, które wykorzystuje konkretny przykład. Pytania są oznaczane na podstawie ich tematu.
Matthew Przeczytaj