为什么接口中的所有字段都是隐式的静态和最终的?

我只是想了解为什么在接口中定义的所有字段都是隐式static并且是final 。 保持字段static的想法对我来说是有意义的,因为你不能拥有一个接口的对象,但为什么它们是final (隐含的)?

任何人都知道为什么Javadevise人员将界面设置为staticfinal的界面?

一个接口不能有行为或状态,因为它只是指定一个交互契约,没有实现细节。 不允许方法/构造函数体或静态/实例初始化块强制执行。 没有状态是通过只允许静态最终字段来实施的。因此,类可以有一个状态(静态),但实例状态不是由接口推断的。

顺便说一句:在Java中的一个常量是由一个静态的最后一个字段来定义的(通过名字使用UPPER_CASE_AND_UNDERSCORES)。

原因是final

任何实现都可以改变字段的值,如果它们没有被定义为最终的。 然后,他们将成为实施的一部分。 一个接口是一个没有任何实现的纯规范。

原因是static

如果它们是静态的,那么它们属于接口,而不是对象,也不属于对象的运行时types。

有几点在这里掩盖:

只是因为接口中的字段是隐式静态的,final并不意味着它们必须是编译时常量,甚至是不可变的。 你可以定义例如

 interface I { String TOKEN = SomeOtherClass.heavyComputation(); JButton BAD_IDEA = new JButton("hello"); } 

(注意,在注释定义中这样做会混淆javac ,这与上面实际编译到静态初始化器的事实有关。

此外,这个限制的原因比技术更具风格,许多人希望看到它放松 。

这些字段必须是静态的,因为它们不能是抽象的(就像方法一样)。 由于它们不能抽象,实施者将无法在逻辑上提供不同的字段实现。

我认为这些字段必须是最终的,因为这些字段可能被许多不同的实现者访问,使得他们可以改变可能是有问题的(作为同步)。 也要避免它被重新实现(隐藏)。

只是我的想法。

我认为要求这些字段是Java语言devise者过分限制和错误的最终结果。 在需要在接口types的对象上执行操作所需的实现中设置常量时,有时候(例如树处理)。 在实现类中select代码path是一个混乱。 我使用的解决方法是定义一个接口函数,并通过返回一个文字实现它:

 public interface iMine { String __ImplementationConstant(); ... } public class AClass implements iMine { public String __ImplementationConstant(){ return "AClass value for the Implementation Constant"; } ... } public class BClass implements iMine { public String __ImplementationConstant(){ return "BClass value for the Implementation Constant"; } ... } 

但是,使用这种语法会更简单,更清晰,更不容易出现exception实现:

 public interface iMine { String __ImplementationConstant; ... } public class AClass implements iMine { public static String __ImplementationConstant = "AClass value for the Implementation Constant"; ... } public class BClass implements iMine { public static String __ImplementationConstant = "BClass value for the Implementation Constant"; ... } 

规范,合同…字段访问的机器指令使用对象地址加字段​​偏移量。 由于类可以实现多个接口,因此无法使非终接接口字段在扩展此接口的所有类中具有相同的偏移量。 因此必须实现不同的字段访问机制:两个内存访问(获取字段偏移量,获取字段值)而不是一个加上维持虚拟字段表(模拟虚拟方法表)的types。 猜猜他们只是不想复杂jvm的function,可以很容易地通过现有的东西(方法)模拟。

在scala中,我们可以在接口中有字段,但是在内部,它们是按照我上面解释的(作为方法)来实现的。

static

Java中static任何东西(variables或方法)都可以作为Classname.variablename或者Classname.methodname或直接调用。 仅通过使用对象名称来调用它并不是强制的。

在接口中,对象不能被声明, static使得可以通过类名来调用variables而不需要对象名。

final

它有助于保持一个variables的常量值,因为它的子类不能被覆盖。