【问题标题】:Why are interfaces in Java 8 allowed to have the main method?为什么 Java 8 中的接口允许有 main 方法?
【发布时间】:2014-10-23 06:09:17
【问题描述】:

为什么在 Java 8 中允许接口具有 main 方法?

如下面的代码所述,它可以正常工作并正确生成输出。

public interface Temp {
    public static void main(String args[]){
         System.out.println("Hello");
    }
}

目前它表现得像一个类,我已经用 main 方法执行了interface

我们为什么需要这个?

【问题讨论】:

  • 我认为你的问题倒过来了。问题不是“应该允许主要方法”,而是“现在我们是否应该明确禁止主要方法,因为接口中允许使用静态方法”(或者,等效地,排除接口类作为 java 启动器的目标。)这将有添加额外规则只是为了排除一些人认为奇怪(但不危险)的东西——这是一场失败的游戏。您希望定义尽可能少的新规则,因为否则您会陷入复杂性的泥潭。
  • @BrianGoetz 是的,同意!!我正在寻找与输出相同的东西,我担心的是,为什么我们有一个实际上表现得像一个类的接口,而 Java 能够执行 interface 的主要方法.最后接口实际上是一个类,java无法区分接口的main和类。
  • 接口类类型,而且一直都是。它们有一些不同的默认值(方法是公共的和抽象的),以及一些不同的限制。在 Java 8 中,我们删除了一些限制——例如对静态方法的限制。我们不会仅仅因为一开始对一些人来说很奇怪,就制定一个特殊的规则来禁止一种特定的静态方法。当你真正了解新规则时,这看起来并不奇怪——实际上你提出的限制看起来会很奇怪。
  • @BrianGoetz 但内部接口方法应该是抽象的。如果是静态方法,这条规则是否也会在 Java8 中被删除?

标签: java java-8


【解决方案1】:

从 Java 8 开始,接口中允许使用静态方法。

main() 是一个静态方法。

因此,接口中允许使用 main()。

我们不需要这个,因为以前不允许这样做,但我们幸免于难。但是由于静态方法,根据定义,并不绑定到类的实例,而是绑定到类本身,因此在接口中允许它们是有意义的。它允许在接口本身而不是单独的类中定义与接口相关的实用方法(例如在Collections 中找到的方法)。

类静态方法和接口静态方法没有区别。

【讨论】:

  • 类和接口上的静态方法至少有一点区别:类上的静态方法可以被子类“继承”,但接口上的静态方法不能被任何子类型继承。
  • @StuartMarks,静态方法的继承只是编译器的魔法,因为用相同的签名声明相同的方法会影响超类中的静态方法。在字节码中,静态方法只是通过对类+方法的完全限定调用来调用的。
  • @bestsss:这是不正确的。 static 方法被继承,编译器将使用在源代码中找到的正式目标类型,在运行时(再次)解析。该调用包含对类+方法的引用,但这也适用于虚拟方法调用。关键是实际的方法声明不必在指定的类中,而是可以在超类中。请参阅ideone.com/n9Caa2(这与接口中的static 方法根本不同)……
  • @Holger 可继承,但不可覆盖,很奇怪的情况
【解决方案2】:

我赞同@jb-nizet 的回答。对此没有“迫切需要”,但它消除了不必要的限制。例如。一个例子是,你现在可以在接口中声明一个工厂方法:

 public interface SomeService {

   public static SomeService getInstance() {
     // e.g. resolve via service provider interface
   }

   ...

 }

在 Java 8 之前,我们总是需要一个单独的工厂类。一个最喜欢的例子是谷歌应用引擎 API。

【讨论】:

  • 因此,在接口上使用 main 方法的合理用法是调用工厂获取对象,然后委托给该对象以执行程序的操作。
【解决方案3】:

在 Java 8 中,接口可以有静态方法。由于 main 方法也是一个静态方法,所以它会允许它。

我们可以使用这些静态方法声明常用的辅助方法。

【讨论】:

    【解决方案4】:

    来自 Brian Goetz 在 cmets 中:

    我认为你的问题倒过来了。问题不是“应该 主要方法被允许”,它是“我们应该明确禁止 主要方法现在接口中允许使用静态方法” (或者,等效地,排除接口类作为 java 的目标 启动器。)这将添加额外的规则只是为了排除 有些人认为奇怪(但不危险)的东西 - 和 那是一场失败的比赛。您想定义尽可能少的新规则 合理地逃脱 - 因为否则你会陷入困境 复杂性。

    【讨论】:

      【解决方案5】:

      更多的附录:也许这里的一个想法是类似于你可以用 Scala 中的 Application trait 做的事情:

      object Main extends Application {
        Console.println("Hello World!")
      }
      

      只需扩展 Application,您就可以将一个类变成可以运行的东西。

      【讨论】:

        猜你喜欢
        • 2014-06-20
        • 2014-06-20
        • 1970-01-01
        • 2014-11-20
        • 1970-01-01
        • 2021-02-02
        • 1970-01-01
        相关资源
        最近更新 更多