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

发布于 2024-08-06 02:19:19 字数 226 浏览 9 评论 0原文

我只是想理解为什么接口中定义的所有字段都是隐式的staticfinal。保持字段静态的想法对我来说很有意义,因为你不能拥有接口的对象,但为什么它们是final(隐式)?

有人知道为什么 Java 设计者会选择将接口中的字段设置为 staticfinal 吗?

I am just trying to understand why all fields defined in an Interface are implicitly static and final. 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)?

Any one knows why Java designers went with making the fields in an interface static and final?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

┈┾☆殇 2024-08-13 02:19:19

接口旨在指定交互契约,而不是实现细节。开发人员应该能够仅通过查看接口来使用实现,而不必查看实现它的类的内部。

接口不允许您创建它的实例,因为您无法指定构造函数。因此它不能有实例状态,尽管接口字段可以定义常量,这些常量是隐式静态和最终的。

尽管从 Java 8 开始您可以使用方法体指定默认方法,但您不能在接口中指定方法体或初始化块。此功能旨在允许将新方法添加到现有接口,而无需更新所有实现。但是,如果不首先创建实现该接口的实例,您仍然无法执行这样的方法。

旁白:请注意,您可以使用匿名内部类实现接口:

interface Foo {
    String bar();
}

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

您必须提供接口的完整实现,以便匿名内部类进行编译。

new Foo() 使用默认构造函数初始化匿名内部类。

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. 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.

冷情妓 2024-08-13 02:19:19

成为最终的原因

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

静态的原因

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

Reason for being final

Any implementations can change value of fields if they are not defined as final. Then they would become a part of the implementation. An interface is a pure specification without any implementation.

Reason for being static

If they are static, then they belong to the interface, and not the object, nor the run-time type of the object.

多情癖 2024-08-13 02:19:19

这里忽略了几点:

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

接口 I {
  String TOKEN = SomeOtherClass.heavyComputation();
  JButton BAD_IDEA = new JButton("你好");
}

(请注意,在注释定义中执行此操作可能会混淆 javac,这与事实上,上面的代码实际上编译为静态初始化程序。)

此外,这种限制的原因更多的是风格上的而不是技术上的,很多人会喜欢看到它放松

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. You can define e.g.

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.)

Also, the reason for this restriction is more stylistic than technical, and a lot of people would like to see it be relaxed.

万人眼中万个我 2024-08-13 02:19:19

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

我认为这些字段必须是最终的,因为这些字段可能会被许多不同的实现者访问,允许它们更改可能会出现问题(如同步)。还要避免它被重新实现(隐藏)。

只是我的想法。

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.

究竟谁懂我的在乎 2024-08-13 02:19:19

我认为字段为 Final 的要求过于严格,并且是 Java 语言设计者的错误。有时,例如树处理,您需要在实现中设置对接口类型的对象执行操作所需的常量。在实现类上选择代码路径是一件很麻烦的事情。我使用的解决方法是定义一个接口函数并通过返回一个文字来实现它:

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

但是,使用此语法会更简单、更清晰并且不易出现异常实现:

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

I consider the requirement that the fields be final as unduly restrictive and a mistake by the Java language designers. There are times, e.g. 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";
    ...
}
鹤仙姿 2024-08-13 02:19:19

规范、合同...用于字段访问的机器指令使用对象地址加字段​​偏移量。由于类可以实现许多接口,因此无法使非最终接口字段在扩展该接口的所有类中具有相同的偏移量。因此,必须实现不同的字段访问机制:两次内存访问(获取字段偏移量、获取字段值),而不是一次加上维护一种虚拟字段表(类似于虚拟方法表)。我猜他们只是不想让 jvm 的功能变得复杂,而这些功能可以通过现有的东西(方法)轻松模拟。

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

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).

In scala we can have fields in interfaces, though internally they are implemented as I explained above (as methods).

讽刺将军 2024-08-13 02:19:19

static

Java 中任何 static 的内容(变量或方法)都可以作为 Classname.variablename 或 < code>Classname.methodname 或直接。不强制仅使用对象名称来调用它。

在接口中,不能声明对象,而static可以仅通过类名调用变量,而无需对象名。

final

它有助于维护变量的恒定值,因为它不能在其子类中被覆盖。

static:

Anything (variable or method) that is static in Java can be invoked as Classname.variablename or Classname.methodname or directly. 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.

final:

It helps to maintain a constant value for a variable as it can't be overridden in its subclasses.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文