繁体   English   中英

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

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

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

任何人都知道为什么 Java 设计者要使接口中的字段成为staticfinal吗?

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

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

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

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

interface Foo {
    String bar();
}

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

您必须为要编译的匿名内部类提供接口的完整实现。

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

final原因

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

static原因

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

这里有几个要点:

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

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

(请注意,在注释定义中执行此操作可能会混淆 javac ,这与上述实际上编译为静态初始值设定项的事实有关。)

此外,这种限制的原因更多的是文体而不是技术,很多人希望看到它放松

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

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

只是我的想法。

我认为字段是 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";
    ...
}

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

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

static

Java 中任何static (变量或方法)都可以作为Classname.variablenameClassname.methodname或直接调用。 仅使用对象名称调用它不是强制性的。

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

final

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

暂无
暂无

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

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