Java 子类数据作为超类返回时的安全性

Java 子类数据作为超类返回时的安全性,java,polymorphism,return-type,Java,Polymorphism,Return Type,在Java中,我很难找到在超类类型的方法中返回子类时发生的具体情况。例如: public class SuperClass { int a; } public class SubClass extends SuperClass { int b; } SuperClass superObj; SubClass subObj; private SuperClass getObject ()

在Java中,我很难找到在超类类型的方法中返回子类时发生的具体情况。例如:

    public class SuperClass
    {
        int a;
    }
    public class SubClass extends SuperClass
    {
        int b;
    }


    SuperClass superObj;
    SubClass subObj;

    private SuperClass getObject ()
    {
        return subObj;
    }


    public static void main (...)
    {
        superObj = getObject();
    }
当subbj作为其超类返回时,它到底发生了什么?我在输入这个示例时意识到,我自己可能也可以轻松地测试它,但我仍然很好奇,当这种情况发生时,到底是什么过程,以及它被认为是好的(如果有效的话)还是坏的做法

我这样问是因为我目前正在从事一个项目,在这个项目中,我有两个抽象基类,每个基类有几个子类。我试图找出处理必须从一个子类更改为另一个子类的好/坏方法,同时仍然使用使用抽象基类时添加的方便多态性


编辑:我修复了main和类声明,对此很抱歉

子类是超类的扩展

您只是将其向下转换为基类,所有扩展都不可用,您不应该试图将它们返回到实现中,因为您可能会猜测这是什么,因为您可以以各种方式多次扩展它


返回的类将具有a但不具有b

在代码中有一些奇怪之处(在main中定义方法?),但这无法承受。。。getObject方法不会更改子对象,它只会返回一个类似于类型超类的对它的引用。我所说的“看起来像”是指它将只公开来自超类的任何方法或成员。但是,如果您接受该返回值并尝试将其向下转换为子类,转换将成功,并且您将发现子类中的字段/方法将按预期工作,而不会丢失作为超类返回的信息。

转换不会从根本上将对象更改为其他类型,它只是告诉编译器将对象视为其超类(向下转换时为子类)。在您的示例中,superObj仍然是子类类型的实例,但现在它似乎是一个超类。这意味着,如果您尝试引用
superObj.b
,您将得到一个编译错误(因为b在超类中不存在)。但是,您可以引用
(子类)superObj.b
。在这种情况下,你告诉编译器把子类看作子类的一个实例(它真的是)。 让我们更进一步,在代码中添加另一个类:

public class SisterClass extends SuperClass
{
    int c;
}

在不更改代码中任何其他内容(语法问题除外)的情况下,您可以尝试引用
((姐妹类)superObj)
。这将编译,但会因ClassCasRuntime运行时错误而失败。虽然SisterClass是超类的一个子类,但superObj不是SisterClass的实例。因此,您只能强制转换到对象的实际类型。

但是,值得注意的是,如果您有一个超类类型的对象引用,那么Java将允许您查询它以确定它是否是一个更具体的类型(在本例中为子类)并且可以让您在适当的时候向下转换。@Tuckrmi如果您首先返回基类型,则表明设计不佳。虽然这通常是正确的,但在某些情况下向下转换是可以接受的。而且,更重要的是,我认为它值得一提,因为它强调了JVM正在做什么,而不是在其他语言/运行时如何处理上转换。