【问题标题】:For what purpose can you declare constants in a Java interface?出于什么目的可以在 Java 接口中声明常量?
【发布时间】:2013-05-28 07:11:07
【问题描述】:

规范声明接口旨在定义类可以做什么的约定,并包含一组实现所需的方法。但同时,接口可能有常量。

Java 出于什么目的允许使用它?

接口中常量的存在意义何在?如何在其中使用它们?据我了解,它们只能作为方法的论据。但我看不出有什么意义,因为接口没有说明如何类将实现其方法。

【问题讨论】:

  • 它们可以用作一种全局变量
  • 好问题...实际上,自从在 Java 5 中引入枚举后,AFAICT 就完全没有意义了。
  • 例如当接口实现 setFlags() 方法并且这些标志(及其数值)由接口(由接口的文档)预定义时
  • 它们对于您需要子类中的常量非常有用,例如,如果您有一个定义 http 请求的interface,则为GETPOST 等定义常量可能很有用。话虽如此,请务必小心Constant Interface Antipattern

标签: java oop interface


【解决方案1】:

常量也是接口的一部分。设计中使用常量值来避免幻数,即对实现具有一定意义但似乎突然冒出来的数字。

在很多情况下,数值会影响代码的行为。例如,考虑一个 GUI 按钮的界面。这个按钮的实际绘制方式取决于实现;但是什么样的按钮是构成界面的合同的一部分:它是普通的按钮,有图像,还是复选框?可以使用常量来修改此行为,这些常量通常由 OR'ing 值使用:例如,int buttonType = PUSHBUTTON|IMAGEBUTTON

【讨论】:

  • 请注意(从 Java 5 开始)接口也可以声明 enum,这通常更适合行为修改,因为它不允许任何未声明的选项并且是类型安全的。一个方法(甚至是内部的)如果是 setButtonType(EnumSet<ButtonType> types) 则更易读于常量方法 setButtonType(int typesMask)
  • 枚举通常不适合配置键。例如,当您想从属性文件中检索特殊属性时。这些通常是字符串,因此不使用枚举的绕道。
  • @ThomasJungblut 在这种情况下,您应该存储枚举的name(),然后调用YourEnum.valueOf(valFromProperties)。或者尝试一些ordinal() 处理,但如果你不是非常小心,那可能会更糟。无论如何,我们不要在这里争论,您和我的方法各有利弊,每个人都可以决定走哪条路。
  • @Slanec 按照惯例,它们的名称中有圆点,因此在语法上是不可能的。不过,您可以向枚举添加一个字符串字段。但这就是我所说的绕道的意思——应该只是一个补充。
  • 当然枚举中没有点。我的意思是属性键。例如。查看 Hadoop 或其他 Apache 项目的配置。
【解决方案2】:

常量可以在接口使用。

例如,它们可以被实现接口的类使用。如果跨实现类需要单个定义,这可能很有用。

例如,考虑一个接口,它定义了一些可以在所有子类中一致使用的按位或样式常量。这些只需要一个定义,并且只需要学习一个集合。

【讨论】:

  • 我明白这是可能的,但我不明白是出于什么目的。毕竟,这在某种程度上是通过接口实现的。
  • 常量值是数据,与实现分开。添加示例。
【解决方案3】:

想象一个使用图像或声音等资源的应用程序。您可以为您的资源定义一个通用接口。

interface MyResource {
    void load();
    void dispose();
    // ...
}

您的文件夹结构可能如下所示:

+ Root
|--+ Resources
   |--+ Images
   |--+ Sounds
   |--+ Data

您知道您的所有资源都将在Root/Resources/ 下。 这些信息不仅可以由您的资源共享和了解,还可以由您的其他应用程序组件共享和了解。

考虑到这一点,您的界面现在变为:

interface MyResource {
    public static final String RESOURCE_ROOT_PATH = "Root/Resources/";

    void load();
    void dispose();
    // ...
}

您的特定实现(例如图像)可能会根据所有资源的公共路径定义自己的根路径。

class MyImage implements MyResource {
    public static final String IMAGE_ROOT_PATH =
            MyResource.RESOURCE_ROOT_PATH + "Images/";

        ...
}

或者,您可以查看javax.swing.SwingConstants 之类的接口,它们用于在实现之间共享特定功能的常量。

但是,对于这种事情,我现在更愿意使用enum

【讨论】:

    【解决方案4】:

    让我们用一个例子来解释:

    public interface People {
        /**
         * Gets the population for the given type
         */
        public Population getPopulationForType(int populationType);
    }
    

    你觉得上面的合同容易理解吗?或者以下不是更好吗?

    public interface People {
        int BLACK_POPULATION_TYPE = 0;
        int ASIAN_POPULATION_TYPE = 1;
        int WHITE_POPULATION_TYPE = 2;
    
        /**
         * Gets the population for the given type
         */
        public Population getPopulationForType(int populationType);
    }
    

    您可以有一个 FrenchPeople、AmericanPeople 和 ChinesePeople 实现,但都应该返回所有三种可能类型的人的人口。

    【讨论】:

    • 这不是一个很好的例子,enum 会更适合这里。
    • 枚举是在 Java 5 中引入的。接口是在 Java 1.0 中引入的。可以想象类似的用例,其中枚举的意义不大。例如,您可以使用位掩码。
    • 当然,在 Java 5 之前,这种用法的接口常量很有意义。如果我们谈论的是 Java 5 之后的版本,那么应该首选EnumSet 而不是位掩码(Effective Java,第 2 版,第 32 条)。
    【解决方案5】:

    在 Java 5 之后(它带来了优于位掩码并且也可以在接口上声明的 enums)对我来说此类常量的一种用法是常量是方法契约的一部分。

    考虑这样的界面:

    public interface Element {
        Element NONE = new EmptyElement();
    
        /**
         *  Looks up an element using this element as a root.
         *  If the lookup fails, returns Element.NONE.
         */
        Element findElements(String searchBy);
    }
    

    常量是方法契约的一部分,因此我认为应该在接口中。这在 API 编程中很有用,因为您可以为 API 方法提供默认或特殊返回值,供所有人使用和检查。

    这种最常见的情况可以防止返回不明确的 null 值的问题(例如,HashMap#get() 方法将返回 null 丢失的键和 null 值),但还有更多它不仅仅是空值 - 我认为任何可以返回的特殊值都应该在接口上。

    【讨论】:

      【解决方案6】:

      接口常量的一种可能用途是确保常量在所有实现类中都是可见的。当然,您可以将所有这些放在一个类中并在这些实现类中使用同一个类,但在 规范 级别定义常量要容易得多。

      这样想;即使常量没有定义“实现”,它们也存在,以防任何实现需要它们。

      【讨论】:

        【解决方案7】:

        它们可用于为方法的返回参数/输入参数赋予符号意义。这已经是预枚举的日子了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-26
          • 2017-10-09
          • 2010-12-01
          相关资源
          最近更新 更多