在这种情况下您无能为力,即使在更复杂的示例中,放置公共代码的最佳位置可能是所有枚举都可以使用的实用程序类,或者将包含在枚举中的单独类中通过组合(每个枚举都有一个该类的实例,可能称为关键字)。
如果该toString
方法的代码很复杂,并且您不想在每个枚举中重新声明它,或者将其移动到包含的对象中,那么 Java 8 有一个您可以使用的机制。在这个例子中它是多余的。您可以定义一个您的枚举都将使用的接口。状态(关键字)必须仍然存在于您的枚举中,因为接口不能有状态,但从 Java 8 开始,您可以提供方法的默认实现:
public interface Common {
String getKeyword();
String toString() default {
return getKeyword();
}
String toDescriptiveString() default {
char firstLetter = getKeyword().charAt(0);
boolean vowel =
firstLetter == 'a' || firstLetter == 'e' ||
firstLetter == 'i' || firstLetter == 'o' ||
firstLetter == 'u' || firstLetter == 'x';
// the letter x is pronounced with an initial vowel sound (eks)
return (vowel?"an ":"a ") + getKeyword() + " address";
}
}
您的枚举将实现此接口:
public enum AddressSubType implements Common {
DOM("dom"), INTL("intl"), POSTAL("postal");
private final String keyword;
private AddressSubType(String keyword) {
this.keyword = keyword;
}
@Override
public String getKeyword() {
return keyword;
}
@Override
public String toString() {
return Common.super.toString();
}
}
public enum EmailSubType implements Common {
INTERNET("internet"), X400("x.400");
private final String keyword;
private EmailSubType(String keyword) {
this.keyword = keyword;
}
@Override
public String getKeyword() {
return keyword;
}
@Override
public String toString() {
return Common.super.toString();
}
}
注意方法中奇怪的新语法toString
。接口中默认方法的规则是方法解析总是优先于类方法而不是接口。因此,即使我们提供了toString
in的默认实现Common
,枚举中的那个将优先,Object
如果枚举中没有一个,则 in 将优先。因此,如果您想使用接口中的默认方法取代其中一种方法Object
(例如toString
,或hashCode
,或equals
),那么您必须使用这种新interface.super.method()
语法显式调用它。
不过,我们不必为该toDescriptiveString
方法跳过任何额外的环节。那是一个全新的 in interface Common
,它不是由我们的枚举提供的,因此它们获得了接口提供的默认实现。(如果他们想用自己的方法覆盖它,他们可以,就像任何其他继承的方法一样。)
当然,我们可以像使用对象的任何其他方法一样使用默认方法:
public class Test {
public static void main(String[] args) {
for (AddressSubType a : AddressSubType.values()) {
System.out.println(a.toDescriptiveString());
}
for (EmailSubType e : EmailSubType.values()) {
System.out.println(e.toDescriptiveString());
}
}
}
打印出来:
一个dom地址
国际地址
邮政地址
一个互联网地址
x.400 地址
然而,在这种情况下,如果不是因为相当冗长的toDescriptiveString
方法,枚举类不会interface Common
比没有的更短。在向现有接口添加新功能时,接口中的默认方法将真正发挥作用,如果不破坏以前 Java 版本中接口的所有实现者,这是不可能的。
所有这些都基于尚未完成的Java SE 8 和 Lambda。您可以下载预发布版本,但请注意这是一项正在进行的工作。