规范声明接口意在定义一个类能做什么并包含一组必需实现的方法,但同时接口也可以有常量。
在 Java 中允许这样做的目的是什么?
常量在接口中存在的意义是什么,它们如何在接口中使用?据我所知,它们只能作为方法的参数,但我并不认为这样做有很大的意义,因为接口并没有说明一个类将如何实现其方法。
常量也是接口的一部分。设计中使用常量值来避免魔数,即对实现有特定含义但似乎突然出现的数字。
有许多情况下,数字值会影响代码的行为。例如,考虑一个GUI按钮的接口。如何绘制这个按钮取决于具体的实现,但它是什么样的按钮是形成接口的合同的一部分:它是普通的推按钮、有图像还是复选框?这个行为可以使用常量修改,常用的方式是按位或值:int buttonType = PUSHBUTTON|IMAGEBUTTON
。
setButtonType(EnumSet<ButtonType> types)
方法而不是常量方法setButtonType(int typesMask)
,即使是内部方法,也会更易读。 - Petr Janečekname()
,然后调用 YourEnum.valueOf(valFromProperties)
。或者尝试一些 ordinal()
处理,但如果你不非常小心的话,那可能会更糟糕。无论如何,让我们不要在这里争论了,你和我都有各自的优缺点,每个人都可以决定走哪条路。 - Petr JanečekMyEnum.HELLO.name()
返回的只是 "HELLO"。额外的字段(我会使用 int
)用于将其“序列化”到属性中也是可行的,如果必须这样做,我绝对会采用这种方式,而不是使用位字段。话虽如此,两种方法都可以接受。 - Petr Janeček想象一下一个使用图片或声音等资源的应用程序。您可以为您的资源定义一个公共接口。
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
。
这些常量可在接口外使用。
例如,它们可以被实现接口的类所使用。如果需要在实现类之间使用单个定义,则这可能非常有用。
举例来说,考虑一个定义了一些按位或样式常量的接口,这些常量可以在所有子类中一致地使用。只需要单个定义,只需要学习一组。
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);
}
EnumSet
应该是首选(Effective Java,第2版,第32项)。 - Petr Janeček我认为Java 5之后常量的一个用途是,当常量是方法契约的一部分时(Java 5引入了enum
,它们优于位掩码,并且可以在接口上声明),
考虑这样一个接口:
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);
}
接口常量的一个可能用途是确保这些常量在所有实现类中都可见。当然,您可以将所有这些内容放入一个类中,并在这些实现类中使用相同的类,但在规范级别定义常量要容易得多。
这样想吧; 即使这些常量不定义“实现”,它们也存在于任何实现需要它们的情况下。
它们可以用于为方法的返回参数/输入参数赋予符号意义。这在预枚举时代是如此。
interface
,那么为GET
和POST
等定义常量可能会很有用。话虽如此,请非常小心 常量接口反模式。 - Boris the Spider