我只是想了解为什么接口中定义的所有字段都是隐式的 static
和 final
。将字段保持 static
的想法对我来说很有意义,因为您无法拥有接口的对象,但是它们为什么是 final
(隐式)?
有人知道为什么Java设计者选择使接口中的字段具有 static
和 final
吗?
我只是想了解为什么接口中定义的所有字段都是隐式的 static
和 final
。将字段保持 static
的想法对我来说很有意义,因为您无法拥有接口的对象,但是它们为什么是 final
(隐式)?
有人知道为什么Java设计者选择使接口中的字段具有 static
和 final
吗?
接口的目的是指定交互契约,而不是实现细节。开发人员应该能够通过查看接口来使用实现,而不必查看实现它的类的内部。
接口不允许您创建其实例,因为您无法指定构造函数。因此,它不能具有实例状态,尽管接口字段可以定义常量,这些常量隐含为静态和final。
您不能在接口中指定方法体或初始化块,不过自Java 8以来,您可以指定带有方法体的默认方法。此功能旨在允许添加新方法到现有接口中而不必更新所有实现。但是,在执行此类方法之前,仍然需要创建实现接口的实例。
附注:请注意,您可以使用匿名内部类实现接口:
interface Foo {
String bar();
}
class FooBar {
Foo anonymous = new Foo() {
public String bar() {
return "The Laundromat Café";
};
}
为了编译,您必须提供匿名内部类的完整实现。
new Foo()
使用默认构造函数初始化匿名内部类。
static final
,而不是承认他们失败了。在Java中,这是最接近真正(真正的C/C++)const
的方法。不幸的是,这是隐式的,可能会导致非专家的困惑。(我刚意识到它们是static
,因为我观察到了意外的行为。我从这个答案中学到它们只是final
。) - not-a-userfinal
的原因
如果字段没有被定义为 final
,它们的值可以由任何实现更改,然后它们将成为实现的一部分。接口是一个纯粹的规范,没有任何实现。
static
的原因
如果它们是 static
,那么它们属于接口,而不属于对象或对象的运行时类型。
这些字段必须是静态的,因为它们不能像方法一样是抽象的。由于它们不能是抽象的,实现者将无法逻辑地提供字段的不同实现。
我认为这些字段必须是final的,因为这些字段可能被许多不同的实现程序访问,允许它们是可变的可能会有问题(例如同步)。此外,这也避免了它被重新实现(隐藏)。
以上是我的想法。
public static
字段不是final
,findbugs会抱怨(理所当然!)。 - Tom Hawtin - tacklinepublic 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";
}
...
}
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";
...
}
规范、合同... 对于字段访问的机器指令使用对象地址加上字段偏移量。由于类可以实现多个接口,因此无法使非最终接口字段在扩展此接口的所有类中具有相同的偏移量。因此必须实现不同的字段访问机制:两个内存访问(获取字段偏移量、获取字段值)而不是一个,同时还要维护一种虚拟字段表(类似于虚拟方法表)。我猜他们只是不想为可以通过现有功能轻松模拟的功能(方法)增加JVM的复杂性。
在Scala中,我们可以在接口中拥有字段,尽管在内部它们是按照我上面解释的方式实现的(作为方法)。
静态
:
在 Java 中,任何被声明为 static
的变量或方法都可以作为 Classname.variablename
或 Classname.methodname
直接调用。不必通过对象名称来调用它。
在接口中,无法声明对象,而 static
可以使得仅通过类名就可以调用变量,无需使用对象名称。
最终
:
它有助于保持变量的常量值,因为它不能在其子类中被重写。