Java多态性和向下转型

时间:2011-06-13 17:37:00

标签: java reflection polymorphism rtti

我正在使用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的{​​{1}}方法返回get,我认为会为原始类型包装器(整数,字符串等)调用正确的方法,但实际上,仅调用Object(不执行隐式向下转换)。

目前,我发现的唯一解决方案是尽可能粗暴地对象进行翻译:

display(Object o)

但这看起来很丑陋,我想知道是否有更优雅的方法来确保调用正确的方法。 有什么想法吗?

提前感谢StackOverflow的好人!

3 个答案:

答案 0 :(得分:3)

好问题。我昨天晚上也想知道;)

所以答案是有两种不同类型的多态:编译时和运行时多态。

当您使用超类型的方法和sybtypes的 overriden 方法时,这是运行时多态。

当您使用超类型和子类型作为不同重载方法的参数时,这是编译时多态性。

因此,在您的情况下,编译器必须在编译时知道要执行哪个方法(/ overload),它不会在运行时做出此决定。

如果您可以控制字段类,那么解决方案是使用泛型,以便您定义

class Field<T> 

使用方法

T get( Object o )

然后编译器将能够在编译时知道用于显示的方法,因为它在编译时知道field.get返回的是什么类型。

但是,根据您的评论,您使用JDK的类java.lang.reflect.Field,因此,您无法控制它以使其通用。在这种情况下,是的,唯一的解决方案是使用一个显示方法来处理field.get的所有不同的可能类型。但实际上,String.valueOf方法在这里可以提供很大的帮助,因为它提供了java中任何类型的字符串表示,已经完成了你正在寻找的重载工作。

Source here

此致  斯特凡

答案 1 :(得分:1)

你想要的是所谓的“双重调度”,Java不支持。

您可以通过反射来模拟它:检查所有display方法及其参数类型,并根据对象的运行时类型动态调用其中一个方法。

对于这个问题,这是不必要的聪明。你的if-else连锁就好了。

答案 2 :(得分:0)

Java不支持“多重多态”。您可能想要查看访问者模式。这几乎是访客的教科书范例。