Java reflecting nested anonymous classes
Why does this code return "class java.lang.Object" ?
Object a = new Object() {
public Object b = new Object(){
public int c;
};
};
System.out.println(a.getClass().getField("b").getType());
Why does the inner-inner type get lost? How can I reflect the c field ?
Edit:
This one works (as pointed out in some answers):
a.getClass()开发者_Python百科.getField("b").get(a) ...
But then I have to invoke a getter, is there any way to reflect c with only reflection meta data?
Because b
is declared as Object
:
public Object b = ...;
There is a distinction between type of variable (static type) and type of the object referenced by that variable (runtime type).
Field.getType()
returns static type of the field.
If you want to get runtime type of the object referenced by the field, you need to access that object and call getClass()
on it (since a
is declared as Object
and therefore b
is not visible as its member you have to use reflection to access it):
System.out.println(
a.getClass().getField("b").get(a).getClass());
UPDATE: You can't reflect c
without accessing the instance of object containing it. That's why these types are called anonymous - a type containing c
has no name, so that you can't declare field b
as a field of that type.
Let's look at this line carefully:
System.out.println(a.getClass().getField("b").getType());
First, your take the a
variable. It is of some anonymous subclass of the Object. Let's call that class MyClass$1
. Okay, so far so good.
Next, you call the getClass() method. It returns the class of a, that is, a description of the MyClass$1
class. This description is not tied to any particular instance of that class, though. The class is the same for all instances, be it a
or whatever else (unless different class loaders are used). In this particular case, however, there can be only one instance, because the class is anonymous, but the mechanism is still the same.
Now, from the class, you get the field b
. As the class isn't directly tied to any of this instances, the field has nothing to do with a
either. It's just a description of what exactly the field a
of the class MyClass$1
is.
Now you get its type. But since it isn't tied to any instance, it can't know the runtime type. In fact, if the class wasn't anonymous, you could have numerous instances of MyClass$1
, each having different value in a
. Or you could have no instances at all. So the only thing getType() can possibly tell you is the declared type of b
, which exactly what it does. The b
field could in fact be null
at that point, and you'd still get Object
as the result.
The Field class provides the get() method to actually access that particular field of some object, like this:
System.out.println(a.getClass().getField("b").get(a).getClass());
Now you get something like MyClass$1$1
, which is the name of the anonymous class of the object that field b
references to, in the a
instance.
Why does the inner-inner type get lost?
Because you are getting the type type of the field "b" (Object), not the type of the anonymous inner class of which you assigned the instance to "b".
How can I reflect the c field ?
You could use this
System.out.println(a.getClass().getField("b").get(a).getClass().getField("c"));
instead. This gets the value of the field "b" and it's class, but this only works if "b" is guaranteed be not null.
Doing this seems to indicate a bad design, there might be other ways to archive what you want to do with this. But without knowing the purpose, this is everything I can answer.
精彩评论