为什么Java8中的接口允许有main方法?

为什么Java8中的接口允许有main方法?,java,java-8,Java,Java 8,为什么Java 8中的接口允许有main方法 正如下面代码中所述,它工作良好,输出正常 public interface Temp { public static void main(String args[]){ System.out.println("Hello"); } } 目前它的行为就像一个类,我已经用main方法执行了interface 为什么我们需要这个?因为Java 8,接口中允许使用静态方法 main()是一个静态方法 因此,接口中允许使用m

为什么Java 8中的接口允许有
main
方法

正如下面代码中所述,它工作良好,输出正常

public interface Temp {
    public static void main(String args[]){
         System.out.println("Hello");
    }
}
目前它的行为就像一个类,我已经用main方法执行了
interface


为什么我们需要这个?

因为Java 8,接口中允许使用静态方法

main()是一个静态方法

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

我们不需要这个,因为以前是不允许的,但我们活了下来。但是,根据定义,静态方法不绑定到类的实例,而是绑定到类本身,因此在接口中允许它们是有意义的。它允许在接口本身中定义与接口相关的实用程序方法(例如,
集合
),而不是单独的类)


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

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


我们可以使用这些静态方法声明常见的帮助器方法

我支持@jb nizet的答案。对此没有“绝望的需要”,但它消除了不必要的限制。例如,一个示例是,您现在可以在接口中声明工厂方法:

 public interface SomeService {

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

   ...

 }
在Java8之前,我们总是需要一个单独的工厂类。一个最受欢迎的例子是google app engine API。

更多的是一个附录:这里可能有一个想法是类似于您可以使用Scala中的特性:

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

只需扩展
应用程序
,就可以将类转换为运行的类

来自Brian Goetz的评论:


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


我想你的问题倒过来了。问题不是“是否应该允许使用主方法”,而是“既然在接口中允许使用静态方法,那么我们是否应该明确禁止使用主方法”(或者,等价地,将接口类排除在java启动器的目标之外。)这可能只是为了排除一些人认为奇怪的东西而添加了额外的规则(但不危险)--这是一个失败的游戏。你想定义尽可能少的新规则,因为否则你会陷入复杂性的泥潭。@BrianGoetz是的,同意!!我在寻找与我在输出中表达的相同的东西,我关心的是,为什么我们有一个行为像类的接口,而Java能够执行接口的main方法。最终接口实际上是一个类,java无法区分接口的main和类。接口是类类型,并且一直都是。它们有一些不同的默认值(方法是公共的和抽象的),以及一些不同的限制。在Java 8中,我们删除了一些限制,比如对静态方法的限制。我们不会制定一个特殊的规则来取缔一个特定的静态方法,仅仅因为一开始对一些人来说它看起来很奇怪。当你真正理解新规则时,这看起来并不奇怪——事实上,限制n您提出的方法看起来很奇怪。@BrianGoetz,但内部接口方法应该是抽象的。在Java8中,静态方法是否也会删除此规则?类上的静态方法和接口上的静态方法至少有一个小区别:类上的静态方法可以“继承”由子类继承,但接口上的静态方法不会被任何子类型继承。@StuartMarks,静态方法的继承只是一种编译器魔法,因为用相同的签名声明相同的方法将在超类中隐藏静态方法。在字节码中,静态方法只是通过类+me上的完全限定调用来调用的thod.@bestsss:这不正确。
静态
方法被继承,编译器将使用在源代码中找到的正式目标类型来解析(再次)在运行时。调用包含对类+方法的引用,但这也适用于虚拟方法调用。关键点是,实际的方法声明不必在指定的类中,而可以在超类中。请参阅(这与接口中的
静态
方法有根本不同)…@Holger可继承,但不可重写,非常奇怪的情况,因此在接口上使用main方法可能是调用factiry来获取一个对象,然后委托给该对象来执行程序的操作。