2011-07-12 5 views
6

Pracuję nad projektem, który używa refleksji, aby uzyskać pola uruchomionej aplikacji java.Java reflection question

Udało mi się zdobyć pola, ale nie mogę ich odczytać ani napisać. To jest przykład znalazłem w internecie:

Class aClass = MyObject.class 
Field field = aClass.getField("someField"); 
MyObject objectInstance = new MyObject(); 
Object value = field.get(objectInstance); 
field.set(objetInstance, value); 

Problemem jest to, że mogę użyć klas z uruchomionego pliku jar i klasy I próbować manipulować uzyskuje się z classloader. Więc zamiast "MyObject.class" po prostu mam ".class". Aby uzyskać "MyObject" próbowałem użyć ClassLoader, ale to nie zadziałało.

Gdybym po prostu użyć”.class':

Object value = field.get(theLoadedClass); 

będę się ten błąd:

java.lang.IllegalArgumentException: Can not set int field myClass.field to java.lang.Class 

Dzięki.

+0

Co masz na myśli mówiąc "działający plik jar"? Czy to jest na twojej ścieżce klasowej? – wjans

Odpowiedz

0

Twoje pytania nie są zbyt jasne, ale myślę, że pytasz, jak odczytać wartość pola z obiektu za pomocą refleksji.

Jeśli spojrzysz w JavaDoc pliku Field.get, zobaczysz, że argumentem dla Field.get powinna być instancja obiektu, z której próbujesz odczytać pole (nie obiekt klasy). Powinno to być coś takiego:

Object value = field.get(someInstanceOfTheLoadedClass); 

Erros wydaje się być wynikiem próby przypisania czegoś typu Class do pola typu int. Powinieneś użyć Field.setInt, aby ustawić pola int.

Nie ma znaczenia, czy obiekt klasy zostanie uzyskany za pomocą klasy .class, czy przy użyciu Class.forName.

+0

... lub używając 'myObject.getClass()'. –

2

Potrzebujesz instancji odpowiedniej klasy, aby przejść do metod field.get/set.

Aby uzyskać instancję z class można wypróbować następujące opcje:

Class<?> clazz = MyObject.class; 
// How to call the default constructor from the class: 
MyObject myObject1 = clazz.newInstance(); 
// Example of calling a custom constructor from the class: 
MyObject myObject2 = clazz.getConstructor(String.class, Integer.class).newInstance("foo", 1); 
0

Jeśli nie znasz typu w czasie kompilacji użyciem:

Class = objectInstance.getClass(); 

również jako inne plakaty powiedział, że musisz wiedzieć, jaki typ pola jest i odpowiednio użyć odpowiedniego typu.

Aby określić to środowisko wykonawcze, należy użyć Field.getType() i następnie użyć poprawnego programu pobierającego i ustawiającego.

3

To powinno pomóc:

Class aClass = myClassLoader.loadClass("MyObject"); // use your class loader and fully qualified class name 
Field field = aClass.getField("someField"); 
// you can not use "MyObject objectInstance = new MyObject()" since its class would be loaded by a different classloader to the one used to obtain "aClass" 
// instead, use "newInstance()" method of the class 
Object objectInstance = aClass.newInstance(); 
Object value = field.get(objectInstance); 
field.set(objetInstance, value); 
2

Z dokumentacji: java.lang.IllegalArgumentException jest wyrzucany:

If, after possible unwrapping, the new value cannot be converted to the type of the underlying field by an identity or widening conversion, the method throws an IllegalArgumentException.

Oznacza to typ obiektu (Object) próbując ustawić pole do nie można przekonwertować na rzeczywisty typ. Spróbuj nie używać tam obiektu.

Unrelated, patrząc na kodzie chciałbym zmienić

Class aClass = MyObject.class; 

egzemplarzao:

Class aClass = Class.forName("fullyQualifiedMyObjectClassName.e.g.com.bla.bla.MyObject"); 
0

to działa?

Class aClass = MyObject.class; 
Field field = aClass.getDeclaredField("someField"); 
field.setAccessible(true); 
MyObject objectInstance = new MyObject(); 
Object value = field.get(objectInstance); 
field.set(objectInstance, value);