I am playing with Java's reflection API, and I'm writing methods that inspect a given object and describes its fields, methods, and so on.
I am using the getFields()
method to iterate on the different attributes and display the object contents:
public static void display(Integer i)
{
System.out.println("An integer: " + i);
}
// Basically a method for each primitive type wrapper
public static void display(Object o)
{
for (Field f : c.getFields())
{
System.out.println("A " + o.getClass() + " which is composed of:");
display(f.get(o));
}
}
(Othe开发者_运维知识库r primitive types and arrays omitted for simplicity's sake.)
Eventhough Field
's get
method returns an Object
, I thought the right methods would be called for the primitive type wrappers (Integers, Strings, etc.), but actually, only display(Object o)
is called (no implicit downcasting is performed).
For now, the only solution I have found is to brutally downcast the objects if possible like this:
public static void display(Object o)
{
if (o instanceof Integer)
{
display((Integer) o);
return;
}
else if (o instanceof String
{
...
} // And so on
for (Field f : c.getFields())
{
System.out.println("A " + o.getClass() + " which is composed of:");
display(f.get(o));
}
}
This does however seem ugly, and I was wondering if there was a more elegant way to make sure the right method is called. Any ideas?
Thanks in advance, good people from StackOverflow!
Good question. I was wondering yesterday night too ;)
So the answer is that there are 2 different types of polymorphism : compile-time and run-time polymorphism.
When you use a method of a supertype and the overriden methods of sybtypes, this is run-time polymorphism.
When you use a super types and sub types as parameters for different overloaded methods, this is compile-time polymorphism.
So the compiler, in your case, has to know at compile-time which method(/overload) to execute, it won't take this decision at run-time.
If you would have Control over the field class, then a solution would be to use generics so that you define a
class Field<T>
with a method
T get( Object o )
Then the compiler would be able to know, at compile time, which method to use for display as it would know, at compile-time, what type is returned by field.get.
But, according to your comments, you use the JDK's class java.lang.reflect.Field and thus, you have no control over it to make it generic. In this case, yes, the only solution is to have a display method that handles all the different possible types for field.get. But indeed, the String.valueOf method could greatly help here as it provides a string representation of any type in java, already does the overload job you are looking for.
Source here.
Regards, Stéphane
What you want is so called "double dispatch" which Java doesn't support.
You can simulate it through reflection: check all your display
methods and their argument types, and dynamically invoke one of them based on the runtime type of an object.
That is unnecessarily clever for this problem. Your if-else chain is just fine.
Java does not support "multiple polymorphism". You may want to have a look at the Visitor pattern. This is almost a textbook example of Visitor.
精彩评论