Java多态性和向下转换

Java多态性和向下转换,java,reflection,polymorphism,rtti,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

我正在使用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));
    }
}
(为了简单起见,省略了其他基本类型和数组。)

尽管
字段
获取
方法返回一个
对象
,但我认为应该为基本类型包装器(整数、字符串等)调用正确的方法,但实际上,只调用
显示(对象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的好朋友们

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

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

当您使用超类型的方法和SybType的重写方法时,这就是运行时多态性

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

因此,在您的例子中,编译器必须在编译时知道要执行哪个方法(/重载),它不会在运行时做出这个决定

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

class Field<T> 
然后,编译器将能够在编译时知道使用哪种方法进行显示,就像它在编译时知道field.get返回的类型一样

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

问候,,
Stéphane

您想要的是所谓的“双重分派”,Java不支持这种分派

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


对于这个问题,这是不必要的聪明。您的if-else链很好。

Java不支持“多重多态性”。您可能需要查看访客模式。这几乎是一个Visitor的教科书示例。

这看起来像是一个典型的解决方案,继承和多态性可以解决您的问题。但我不知道如何在不扩展所有可显示类型的子类的情况下做到这一点。@Steven:
(Integer)o
正在向下转换。@Oli:哇,真不敢相信我一直在用另一种方式命名它们。:O谢谢。+1除了泛型以外的所有东西。但是-1关于泛型的东西(至少在你澄清你的意思之前!我不确定你在这里建议如何使用泛型…)除非我没有正确理解你所说的,否则我无法控制反射API提供的
get
方法。因此,我不能将其作为通用方法。
T get( Object o )