1

我有以下示例代码解释示例多态性概念 - 覆盖

    超级类
    {
        公共整数 = 1;
        公共字符超文本='a';
        公共字符串 getColor()
        {
            返回“红色”;
        }
    }

    类 Sub 扩展 Super
    {
        公共整数 = 2;
        public char subText='b';

        公共字符串 getColor()
        {
            返回“蓝色”;
        }
    }


    公开课 Sample2
    {
        公共静态无效主要(字符串 [] 参数)
        {
            超级超级子 = 新子();
            System.out.println(supersub.getColor() + supersub.number + supersub.superText );
        }



    }

输出为蓝色 1。

问题一:

派生类 getColor() 中的方法被覆盖,并显示超类的字段。

有人可以解释为什么不调用派生类中的数字字段吗?即,输出为 blue2


问题 2: *关于内存分配*

对于以下对象实例化,

   子子对象 = 新子();
字段“数字”的内存在堆中分配,数字变量的地址分配给对象引用 subobj。

考虑以下情况,

超级超级子 = 新子();

(a)这里创建了派生类 'Sub' 中的变量、'number and subText' 的内存,并将变量的地址放在 supersub 对象中

当我访问时,supersub.subText 我得到 subText 无法解析的错误。

所以,请解释上述点(a) ,即派生类变量的内存分配

谢谢,电子人

4

5 回答 5

2

Java 中的字段不会被调用,并且永远不会受到动态调度/运行时多态性的影响。在您的情况下,实际上有两个单独的字段恰好具有相同的名称:Super#numberSub#number. 该类Sub继承Super#number,因此它同时具有,您访问哪一个取决于您访问它的变量的静态编译时类型。这就解释了为什么subobj访问一个和superobj另一个。

于 2013-02-12T14:36:51.320 回答
2

有人可以解释为什么不调用派生类中的数字字段吗?

那是因为fields不是多态的。当访问特定引用上的字段时,您可以访问引用类型中定义的字段,并且决定不是基于实际的对象类型。

字段“数字”的内存在堆中分配,数字变量的地址分配给对象引用 subobj。

number是原始类型int,原始类型不在堆上分配。它们存储在文字池中。Primitives 和 Wrapper 类是两个不同的东西。如果您使用Integer而不是int,那么您将在 上创建对象Heap,如果该值不在范围内,则由Java文字池缓存。

supersub.subText 我收到 subText 无法解析的错误。

这可以从您对第一个疑问的解释中推断出来。由于字段访问是基于引用类型而不是实际对象类型来解析的。因此,显然您无法访问subText引用Super,因为该字段不是该类的一部分,而是子类的一部分。

于 2013-02-12T14:37:03.430 回答
2

问题一:

显示方法是派生类,并显示超类的字段。

有人可以解释为什么不调用派生类中的数字字段吗?即,输出为 blue2

字段不能被覆盖。即使两个类共享父子关系,字段也属于定义它们的类,即使它们与继承的字段共享名称。换句话说,numberin 与 inSub是完全不同的number领域Super

问题2:这里创建了派生类'Sub'中的变量内存,'number and subText',并且当我访问时,变量的地址被放置在supersub Object中,supersub.subText我得到了无法解析subText的错误。

存储的对象supersub是 type Sub,但编译器不知道。

因为 Java 是一种静态类型语言,所以编译器会使用引用的声明类型(即变量类型),因为在大多数实际情况下,运行时类型(表达式中明显的类型new)不是必须在编译时知道。例如,您可能从另一个方法或两个或三个候选方法中获取了此对象,因此运行时类型是不可预测的。

将引用存储在超类变量中意味着您打算暂时使用该对象Super。然后,编译器会根据您的这种感知意图进行工作。Super不保证只有运行时类型的实例Sub,因此它不能做出您期望的假设。

话虽如此,将引用存储在一种或另一种变量中不会修改对象。如果您要将对象强制转换回一个类型的变量,该变量实际上知道您尝试访问的那些成员(在您的情况下是Sub类型),您会发现它们仍然存在(并且它们保留了它们的值)。

于 2013-02-12T14:41:03.400 回答
0

很简单,因为您不能覆盖字段。方法是唯一可以被覆盖的东西。

于 2013-02-12T14:36:36.863 回答
0

您不会覆盖 Java 中的类变量:您隐藏它们。覆盖是实例方法。

于 2013-02-12T14:37:13.197 回答