简体   繁体   English

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

[英]Why are all fields in an interface implicitly static and final?

I am just trying to understand why all fields defined in an Interface are implicitly static and final .我只是想了解为什么 Interface 中定义的所有字段都是隐式staticfinal The idea of keeping fields static makes sense to me as you can't have objects of an interface but why they are final (implicitly)?保持字段static的想法对我来说很有意义,因为您不能拥有接口的对象,但为什么它们是final (隐式)?

Any one knows why Java designers went with making the fields in an interface static and final ?任何人都知道为什么 Java 设计者要使接口中的字段成为staticfinal吗?

An interface is intended to specify an interaction contract, not implementation details.接口旨在指定交互契约,而不是实现细节。 A developer should be able to use an implementation just by looking at the interface, and not have to look inside the class which implements it.开发人员应该能够仅通过查看接口来使用实现,而不必查看实现它的类内部。

An interface does not allow you to create an instance of it, because you cannot specify constructors.接口不允许您创建它的实例,因为您不能指定构造函数。 So it cannot have instance state, although interface fields can define constants, which are implicitly static and final.所以它不能有实例状态,尽管接口字段可以定义常量,这些常量是隐式静态和最终的。

You cannot specify method bodies or initializer blocks in an interface, although since Java 8 you can specify default methods with bodies.您不能在接口中指定方法主体或初始化程序块,但从 Java 8 开始,您可以使用主体指定默认方法。 This feature is intended to allow new methods to be added to existing interfaces without having to update all the implementations.此功能旨在允许将新方法添加到现有接口,而无需更新所有实现。 But you still cannot execute such a method, without first creating an instance implementing the interface.但是,如果不首先创建实现接口的实例,您仍然无法执行这样的方法。

Aside: Note that you can implement an interface with an anonymous inner class:旁白:请注意,您可以使用匿名内部类实现接口:

interface Foo {
    String bar();
}

class FooBar {
    Foo anonymous = new Foo() {
         public String bar() {
             return "The Laundromat Café";
    };
}

You have to provide the full implementation of the interface for the anonymous inner class to compile.您必须为要编译的匿名内部类提供接口的完整实现。

new Foo() is initializing the anonymous inner class with its default constructor. new Foo()正在使用其默认构造函数初始化匿名内部类。

Reason for being final final原因

Any implementations can change value of fields if they are not defined as final.如果字段未定义为 final,则任何实现都可以更改字段的值。 Then they would become a part of the implementation.然后他们将成为实施的一部分。 An interface is a pure specification without any implementation.接口是没有任何实现的纯规范。

Reason for being static static原因

If they are static, then they belong to the interface, and not the object, nor the run-time type of the object.如果它们是静态的,那么它们属于接口,而不是对象,也不属于对象的运行时类型。

There are a couple of points glossed over here:这里有几个要点:

Just because fields in an interface are implicitly static final does not mean they must be compile-time constants, or even immutable.仅仅因为接口中的字段是隐式静态 final 并不意味着它们必须是编译时常量,甚至是不可变的。 You can define eg您可以定义例如

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

(Beware that doing this inside an annotation definition can confuse javac , relating to the fact that the above actually compiles to a static initializer.) (请注意,在注释定义中执行此操作可能会混淆 javac ,这与上述实际上编译为静态初始值设定项的事实有关。)

Also, the reason for this restriction is more stylistic than technical, and a lot of people would like to see it be relaxed .此外,这种限制的原因更多的是文体而不是技术,很多人希望看到它放松

The fields must be static because they can't be abstract (like methods can).字段必须是静态的,因为它们不能是抽象的(就像方法一样)。 Because they can't be abstract, the implementers will not be able to logically provide the different implementation of the fields.因为它们不能是抽象的,所以实现者将无法在逻辑上提供字段的不同实现。

The fields must be final, I think, because the fields may be accessed by many different implementers allows they to be changeable might be problematic (as synchronization).我认为这些字段必须是最终的,因为这些字段可能会被许多不同的实现者访问,允许它们可变可能会出现问题(作为同步)。 Also to avoid it to be re-implemented (hidden).还要避免它被重新实现(隐藏)。

Just my thought.只是我的想法。

I consider the requirement that the fields be final as unduly restrictive and a mistake by the Java language designers.我认为字段是 final 的要求是过度限制并且是 Java 语言设计者的错误。 There are times, eg tree handling, when you need to set constants in the implementation which are required to perform operations on an object of the interface type.有时,例如树处理,当您需要在实现中设置常量时,需要在接口类型的对象上执行操作。 Selecting a code path on the implementing class is a kludge.在实现类上选择代码路径是一个麻烦事。 The workaround which I use is to define an interface function and implement it by returning a literal:我使用的解决方法是定义一个接口函数并通过返回一个文字来实现它:

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";
    }
    ...
}

However, it would be simpler, clearer and less prone to aberrant implementation to use this syntax:但是,使用此语法会更简单、更清晰且不易出现异常实现:

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";
    ...
}

Specification, contracts... The machine instruction for field access uses object address plus field offset.规范、合同... 用于字段访问的机器指令使用对象地址加上字段偏移量。 Since classes can implement many interfaces, there is no way to make non-final interface field to have the same offset in all classes that extend this interface.由于类可以实现许多接口,因此无法使非最终接口字段在扩展此接口的所有类中具有相同的偏移量。 Therefore different mechanism for field access must be implemented: two memory accesses (get field offset, get field value) instead of one plus maintaining kind of virtual field table (analog of virtual method table).因此必须实现不同的字段访问机制:两次内存访问(获取字段偏移量,获取字段值)而不是一次加维护一种虚拟字段表(类似于虚拟方法表)。 Guess they just didn't want to complicate jvm for functionality that can be easily simulated via existing stuff (methods).猜猜他们只是不想让 jvm 复杂化,因为这些功能可以通过现有的东西(方法)轻松模拟。

In scala we can have fields in interfaces, though internally they are implemented as I explained above (as methods).在 Scala 中,我们可以在接口中有字段,尽管在内部它们是按照我上面解释的(作为方法)实现的。

static : static

Anything (variable or method) that is static in Java can be invoked as Classname.variablename or Classname.methodname or directly. Java 中任何static (变量或方法)都可以作为Classname.variablenameClassname.methodname或直接调用。 It is not compulsory to invoke it only by using object name.仅使用对象名称调用它不是强制性的。

In interface, objects cannot be declared and static makes it possible to invoke variables just through class name without the need of object name.在接口中,不能声明对象,而static使得可以通过类名调用变量而无需对象名。

final : final

It helps to maintain a constant value for a variable as it can't be overridden in its subclasses.它有助于保持变量的恒定值,因为它不能在其子类中被覆盖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM