关于static:Java中的变量和方法阴影

Variable and Method shadowing in Java

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

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

用实例方法隐藏静态方法和用实例变量隐藏静态变量之间的行为究竟有什么不同。

事先谢谢。


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

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


在子类(BedromFlat)中,编译器不允许您声明与基类中静态方法同名的实例方法,因为方法重写只适用于实例方法。扩展类只能使实例方法对子类可用以重写(而不是类方法,即静态方法)。此外,当您试图声明与静态方法具有相同签名的方法时,编译器将抛出一个错误,说明不能重写静态方法,因为重写发生在实例方法中。

但是编译器不会阻止您声明一个与超级类中的静态变量同名的实例变量,因为变量不是重写的候选变量。


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

当然,通常这些病例应该避免(它会引起不必要的头痛)。

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


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


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


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

您的实例变量可以直接访问我的命名,通常您需要编写classname.staticvar之类的东西来访问静态变量。Java只允许在引用静态变量时省略类名。

这很清楚,不是吗?