更改 java 8 默认方法的可见性

Changing visibility of java 8 default method

我有一个 class(比如说 FOO),它有一个具有 default 可见性的方法, 如下所示:

void sayHi() {}

现在,如果在扩展 class 时覆盖此方法,我无法降低它的可见性。所以我只能用default或者public.

public class MyClassTest extends FOO {
    @Override
    // Or I can use public void sayHi()
    void sayHi() {
        System.out.println("Overriden sayHi");
    }
}

现在,如果我使用如下默认方法在 Java 8 中编写接口:

public interface InterfaceX {

    // Java-8 defalu method
    default String printName() {
        System.out.println("Interface1 default metod");
        return "Interface1 default metod";
    }
}

现在,如果我在 class 中重写此方法,如果保持重写方法的可见性 default,它应该可以编译。

public class Java8InterfaceTest implements InterfaceX{
    @Override
     void printHello() {
        System.out.println("Printing..!");
        Interface1.super.printName();
    }
 }

它说

Cannot reduce the visibility of the inherited method from InterfaceX

我已经知道 publicinterface 中的每个方法默认情况下,但在上面的示例中我们使用 default 我认为是 access modifierjava.

我有以下问题:

  1. interface 中的 default 是否不同于未应用访问修饰符时提供的 default 可见性?
  2. 如果不同,那么它有何不同?

default 与默认可见性无关。接口中的 default 方法是在接口中具有默认实现的方法。

该方法的可见性仍然是 public

因此,在您的 Java8InterfaceTest class 中实现的方法必须具有 public 可见性:

public void printHello() {
    ...
}

其他答案很好地概述了 "syntactical" 您关于 default 是 "visibility" 的假设的缺陷。

但背后有一个值得专门回答的概念性问题:降低方法的可见性并不是健全

请记住:class 或接口的 pubic "API" 声明一个 contract 供客户端代码使用。比如:在基础 class/interface Animal.

上有一个方法 eat()

重点是不同的subclasses/implementations可以提供他们自己的eat()实现。这样你就可以拥有:

Animal whatever = ...
whatever.eat();

并且无论 ... 实际上创建了什么(可能是 CatDogUnicorn)- 调用 whatever.eat() 是有效的。

你的想法是说:我想"hide"eat()一个特定的子classDonkey。如果你能做到这一点——突然间上面的代码可能是无效的。因为当 whatever 恰好是 Donkey.

的实例时,whatever.eat() 不再是有效调用

长话短说:阅读 Liskov Substitution Principle 了解为什么 "taking away" public 不是一个好主意 - 完全独立于混淆 "default package protected visibility" 和 接口中的默认关键字。

我认为如果你把你的界面写成:

interface Test {
    default public void go() {

    }
}

这是有道理的。 default 方法仍然是 public;与 "default" 可见性无关。