Java 多态和向下转型
我正在使用 Java 的反射 API,并且正在编写检查给定对象并描述其字段、方法等的方法。
我使用 getFields()
方法来迭代不同的属性并显示对象内容:(
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));
}
}
为了简单起见,省略了其他基本类型和数组。)
尽管 Field
的get
方法返回一个 Object
,我认为将为基本类型包装器(整数、字符串等)调用正确的方法,但实际上,仅 display (对象 o)
是调用(不执行隐式向下转换)。
目前,我找到的唯一解决方案是如果可能的话,像这样残酷地向下转换对象:
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));
}
}
但这看起来确实很丑陋,我想知道是否有一种更优雅的方法来确保调用正确的方法。 有什么想法吗?
预先感谢 StackOverflow 的好心人!
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));
}
}
(Other 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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好问题。昨天晚上我也在想;)
所以答案是,有两种不同类型的多态性:编译时多态性和运行时多态性。
当您使用超类型的方法和 sybtype 的重写方法时,这就是运行时多态性。
当您使用超类型和子类型作为不同重载方法的参数时,这就是编译时多态性。
因此,在您的情况下,编译器必须在编译时知道要执行哪个方法(/重载),它不会在运行时做出此决定。
如果您要控制字段类,那么解决方案是使用泛型,以便您定义一个
方法
然后编译器将能够在编译时知道使用哪个方法来显示,因为它会知道,在编译时,field.get 返回什么类型。
但是,根据您的评论,您使用 JDK 的类 java.lang.reflect.Field,因此您无法控制它以使其通用。在这种情况下,是的,唯一的解决方案是有一个显示方法来处理 field.get 的所有不同可能类型。但事实上,String.valueOf 方法在这里可以提供很大帮助,因为它提供了 java 中任何类型的字符串表示形式,已经完成了您正在寻找的重载工作。
来源在这里。
问候,
史蒂芬
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
with a method
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
你想要的是Java不支持的所谓“双重调度”。
您可以通过反射来模拟它:检查所有
display
方法及其参数类型,并根据对象的运行时类型动态调用其中之一。对于这个问题来说,这是不必要的聪明。你的 if-else 链就很好。
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不支持“多重多态”。您可能想看看访客模式。这几乎是Visitor的教科书示例。
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.