2011-07-12 50 views
6

Tôi đang làm việc trên một dự án sử dụng sự phản chiếu để có được các trường của một ứng dụng java đang chạy.Câu hỏi phản chiếu Java

Tôi đã quản lý để có được các trường, nhưng tôi không thể đọc hoặc viết thư cho họ. Đây là ví dụ tôi tìm thấy trên web:

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

Vấn đề là tôi sử dụng các lớp từ tệp jar đang chạy và các lớp tôi cố gắng thao tác được lấy từ classLoader. Vì vậy, thay vì 'MyObject.class' tôi chỉ có '.class'. Để có được 'MyObject' tôi đã cố gắng sử dụng một ClassLoader nhưng điều đó không hoạt động.

Nếu tôi chỉ sử dụng' .class':

Object value = field.get(theLoadedClass); 

tôi sẽ nhận được lỗi này:

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

Cảm ơn.

+0

Bạn có ý gì khi 'tệp jar đang chạy'? Là nó trên classpath của bạn? – wjans

Trả lời

0

Câu hỏi của bạn không rõ ràng lắm, nhưng tôi nghĩ bạn đang hỏi cách đọc giá trị của một trường từ một đối tượng sử dụng sự phản chiếu.

Nếu bạn nhìn vào JavaDoc của Field.get bạn sẽ thấy đối số đó là Field.get phải là đối tượng đối tượng bạn đang cố gắng đọc trường từ (không phải đối tượng Lớp). Vì vậy, nó phải là một cái gì đó như:

Object value = field.get(someInstanceOfTheLoadedClass); 

Bạn erros có vẻ là kết quả của việc ấn định thứ gì đó kiểu Class vào một trường kiểu int. Bạn nên sử dụng Field.setInt để đặt các trường int.

Việc bạn có được đối tượng Lớp không quan trọng bằng cách sử dụng .class hoặc bằng cách sử dụng Class.forName.

+0

... hoặc bằng cách sử dụng 'myObject.getClass()'. –

2

Bạn cần một phiên bản của lớp thích hợp để chuyển sang các phương thức field.get/set.

Để có được một thể hiện từ một class bạn có thể thử các tùy chọn này:

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

Nếu bạn không biết loại tại biên dịch thời gian sử dụng:

Class = objectInstance.getClass(); 

Cũng như các áp phích khác nói bạn phải biết loại trường là gì và sử dụng đúng loại cho phù hợp.

Để xác định thời gian chạy này Field.getType() và sử dụng getter và setter chính xác sau đó.

3

Điều này sẽ giúp:

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

Từ các tài liệu: java.lang.IllegalArgumentException được ném:

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.

Điều này có nghĩa các loại đối tượng (Object) bạn cố gắng để thiết lập các lĩnh vực để không thể chuyển đổi thành loại thực tế. Hãy thử không sử dụng một đối tượng ở đó.

Không liên quan, nhìn vào mã của bạn tôi sẽ thay đổi mảnh

Class aClass = MyObject.class; 

tới:

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

Liệu công việc này?

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);