【问题标题】:Variable and Method shadowing in JavaJava中的变量和方法阴影
【发布时间】:2013-02-25 13:27:05
【问题描述】:

基本上我想知道为什么静态方法不能被实例方法遮蔽,(我知道为什么,在某些情况下会导致歧义),而静态变量可以被实例变量遮蔽(它适用仅适用于子类)。

例子:

public class Apartment{

    static int area = 10;

    public static int getArea(){
        return area;
    }
}

class BedroomFlat extends Apartment {

    int area = 10;// no problem at all 

    public int getArea(){ // illegal line it cannot hide the super static method
        return area;
    }
}

因此,如果我尝试在超类中声明int area(实例变量)和static int area,则会出现错误,但在子类中声明时不会发生这种情况,即使static int area 仍然可见来自子类。

尝试使用实例方法隐藏静态方法和尝试使用实例变量隐藏静态变量之间的行为究竟有什么区别。

提前致谢。

【问题讨论】:

  • 我完全理解为什么静态方法不会被覆盖。我只想知道为什么实例变量区域阴影(用 new Bedroom().a 而言将返回实例变量而不是超静态),而对于方法它不会发生

标签: java static instance instance-variables shadowing


【解决方案1】:

没有人可以继承静态方法和字段,因为它们属于类。

在您的情况下,您没有从父级覆盖 getArea();,您正在尝试创建具有相同签名的方法 - 这会导致编译错误。

【讨论】:

  • 我完全理解为什么静态方法不会被覆盖。我只想知道为什么实例变量区域阴影(用 new Bedroom().a 而言将返回实例变量而不是超静态),而对于方法它不会发生
【解决方案2】:

在您的子类(BedroomFlat)中,编译器不允许您在基类中声明与静态方法同名的实例方法,因为方法覆盖仅适用于实例方法。扩展类仅使子类可以使用实例方法进行覆盖(而不是类方法,即静态方法)。 此外,当您尝试声明与静态方法具有相同签名的方法时,编译器会抛出一个错误,指出您无法覆盖静态方法,因为覆盖发生在实例方法上。

但是编译器不会阻止你从超类声明一个与静态变量同名的实例变量,因为变量不是覆盖的候选者。

【讨论】:

    【解决方案3】:

    问题是:你根本没有在这里隐藏任何东西......

    您的实例变量可以通过我的命名直接访问,通常您必须编写 ClassName.staticVar 之类的内容才能访问静态变量。 Java 只允许在引用静态变量时省略类名。

    这很清楚,不是吗?

    【讨论】:

    • 我知道它为什么不能编译。假设我有 new BedreoomFlat().getArea() 编译器不知道要选择哪个 getArea。静态还是实例?两者都可以通过这种方式访问​​。但是对于实例变量区域,即使静态变量区域可见,也没有问题,因此会被遮蔽。
    【解决方案4】:

    Java中的静态方法和字段只属于类,不能被对象继承,否则会导致编译错误。

    【讨论】:

      【解决方案5】:

      我们知道子继承父,但我们也知道静态方法不能被覆盖。所以在这种情况下,您将在孩子中有两个具有相同方法签名的方法。这将产生问题,因为 java 不支持相同签名的两种方法,尽管这里一种方法是静态的,另一种是非静态的。但对于静态变量,情况并非如此。

      【讨论】:

      • 这就是重点,如果一个方法指向类而另一个方法指向实例。为什么要产生冲突?静态 int area = 10 和 int area = 10 的逻辑不一样吗?为什么不是这样有什么区别?
      【解决方案6】:

      我的猜测是,这会给多态性(或至少如何实现)带来一些问题。假设你做了这样的事情 Apartment x = new BedroomFlat(); 。调用方法getArea(),它不知道它是隐藏方法还是被覆盖,因为如果它是隐藏的(静态)它应该调用类Apartment中的方法,但如果它被覆盖它应该调用实例之一。

      当然,通常应该避免这些情况(它会带来不必要的头痛)。

      编辑:我找到了这个链接,在页面底部,您可以看到静态方法和实例方法之间的方法隐藏/覆盖表。不知道为什么会这样,但至少我们知道它写在某个地方 (https://docs.oracle.com/javase/tutorial/java/IandI/override.html)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-15
        • 1970-01-01
        • 2022-01-27
        • 2010-11-08
        • 2018-08-14
        相关资源
        最近更新 更多