Java 为什么可以';降低继承的静态方法的可见性

Java 为什么可以';降低继承的静态方法的可见性,java,inheritance,overriding,static-methods,Java,Inheritance,Overriding,Static Methods,不允许重写和降低继承方法的可见性,但关键是无论如何都不能重写静态方法: 如果子类定义的静态方法与超类中的静态方法具有相同的签名,则子类中的方法将隐藏超类中的方法 那么,为什么第二次隐藏可以,而第一次隐藏不可以呢 public class Base { public static void foo(){ System.out.println("Base"); } } 隐藏1: public class Sub extends Base { static void fo

不允许重写和降低继承方法的可见性,但关键是无论如何都不能重写静态方法:

如果子类定义的静态方法与超类中的静态方法具有相同的签名,则子类中的方法将隐藏超类中的方法

那么,为什么第二次隐藏可以,而第一次隐藏不可以呢

public class Base {

  public static void foo(){
      System.out.println("Base");
  }
}
隐藏1:

public class Sub extends Base {

  static void foo(){          //cannot reduce visibility error!
      System.out.println("Sub");
  }
}
隐藏2:

public class Sub extends Base {
  public static void foo(){   //OK
      System.out.println("Sub");
  }
}

原因是,您可能希望将子类的实例作为超类的一种类型提供给使用者。此使用者尝试运行他用来运行的(public)方法,因为它是public的,但是您将其隐藏起来,使其受到保护。为了防止这种情况,引入了此规则。(问题在于可见性,而不是静态!)。
尽管我不得不承认,这种推理并不完全适用于静态方法,当消费者想要直接拥有一个子类(作为子类)时,就像他用来运行超类一样。

在子类中隐藏
静态
超类方法是可以的:

public class Base {
    public static void foo(){
        System.out.println("Base");
    }
}

public class Sub extends Base {
    static void foo(){          //cannot reduce visibility error!
        System.out.println("Sub");
    }
}

public class Sub1 extends Base {
    public static void foo(){   //OK
        System.out.println("Sub1");
    }
}

输出:

基地

Sub1

Sub
中,您试图降低可见性(从
public
变为
no modifier
)。在
Sub1
中,您没有降低可见性(从
public
public
)。这就是为什么它在
Sub1
中编译,而不是
Sub
中编译。这与方法的可见性有关。它与覆盖/隐藏无关。(在本例中隐藏,因为它是
静态方法)

如果尝试在
main
方法中运行
Sub.foo()
,而不更改任何内容,则会出现以下异常:

线程“main”java.lang中出现异常。错误:未解决的编译问题: 无法降低从基继承的方法的可见性


是一个类似的问题和答案。

请参阅@Mena无法找到“为什么”的答案there@A.Steiner因为您试图降低
静态方法的可见性。你不能降低能见度。如果方法是
public
,则无法将其更改为“无修改器”,因为这样会降低可见性。查看@Mena链接到的答案,并确保仔细阅读整个内容。…。@A.Steiner例如,如果您删除
public static void foo()上的
public
修饰符{
在你的
基类中
子类中的两个方法都会编译,因为你不会降低可见性…你不能同时在子类中拥有这两个方法,尽管你必须先把一个放进去,然后再把另一个放进去,否则你会得到一个
重复的方法
编译错误。实际上…这样的静态方法在某种意义上是“被覆盖的”。请参阅。问题是,静态方法的设计比必要的更具动态性;回想起来是一个错误。在任何情况下,出于理智的考虑,“隐藏”一个本来可以访问的方法只会造成混乱。如果添加
class Sub2 extensed Sub
,那么
Sub2.foo()
确切的意思是?没有这样的方法?每个子对象拒绝访问?或者每个基对象可访问?问题是它没有覆盖,所以根据这个推理,它不是被认为是非法重载而不是可见性错误吗?它是一种覆盖(称为隐藏),当然不是重载(无法使用相同的代码调用超级静态和子静态,因为您使用类型引用它们)。@A.Steiner看看我的评论。。。
public class Main {
    public static void main(String[] args)
    {
        Base.foo();
        Sub1.foo();
    }
}