Java reflection 'Can not set' error

2019-08-01 14:12发布

问题:

I am trying to get the instance of a generic Field attribute using Java reflection in order to execute a method of this Field.

For instance, If I have a type MyType class with a method getValue() and I have another class MyContainer with an attribute of MyType class, what I am looking for is to get this Field dynamically and execute the getValue() method. Is this possible?

With the following code structure, I am getting:

Exception in thread "main" java.lang.IllegalArgumentException: Can not set test.MyType field test.MyContainer.field1 to test.MyType
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
    at java.lang.reflect.Field.get(Field.java:393)
    at test.Main.main(Main.java:24)

MyContainer

public class MyContainer {

MyType field1;
MyType field2;

public MyContainer() {
    super();
}

public MyContainer(MyType field1, MyType field2) {
    super();
    this.field1 = field1;
    this.field2 = field2;
}

public MyType getField1() {
    return field1;
}

public MyType getField2() {
    return field2;
}
}

MyType

public class MyType {

private MyEnum var1;
private String var2;

public MyType() {
    super();
}

public MyType(MyEnum var1, String var2) {
    this.var1 = var1;
    this.var2 = var2;
}

public MyEnum getVar1() {
    return var1;
}

public String getVar2() {
    return var2;
}   
}

MyEnum

public enum MyEnum {

A(""),

N("0");

private final String value;

private MyEnum(String value) {
    this.value = value;
}

@Override
public String toString() {
    return this.value;
}
}

Execution

    java.lang.reflect.Field[] allFields = MyContainer.class.getDeclaredFields();        
    MyType obj = new MyType();

    for (java.lang.reflect.Field field : allFields) {

        if ( MyType.class == field.getType() ){                 

            field.setAccessible(true);              
            MyType myAux = (MyType) field.get(obj);             
            String dowhatever = myAux.getVar2();    

        }
    }

As you could see in the exception, test.MyType field type seems to be totally equivalent to test.MyType provided in the casting. What I am doing wrong?

回答1:

obj should be of class MyContainer, not MyType

java.lang.reflect.Field[] allFields = MyContainer.class.getDeclaredFields();        
MyContainer obj = new MyContainer();

for (java.lang.reflect.Field field : allFields) {

    if ( MyType.class == field.getType() ){                 

        field.setAccessible(true);              
        MyType myAux = (MyType) field.get(obj);             
        String dowhatever = myAux.getVar2();    

    }
}

See here

get(Object obj)

Returns the value of the field represented by this Field, on the specified object.