从Java 8开始,您可以在Interfaces中实现默认或静态方法,如下所示
public interface DbValuesEnumIface<ID, T extends Enum<T>> {
T fromId(ID id);
ID getId();
static String getDescriptionKey(){
return "this is a test";
}
}
我想用静态方法声明上面的方法,该签名使用实现类定义的边界,因为方法的实现应该对所有人都是相同的,唯一不同的应该是声明的泛型,如下:
public interface DbValuesEnumIface<ID, T extends Enum<T>> {
public static T fromId(ID id) {
if (id == null) {
return null;
}
for (T en : T.values()) {
if (en.getId().equals(id)) {
return en;
}
}
}
ID getId();
String getDescriptionKey();
}
...
public enum Statuses implements DbValuesEnumIface<Integer,Statuses>
因为T和ID不是静态的而无法从静态上下文中引用而中断。
那么,如何修改上述内容以便成功编译,如果不可能,那么应该如何实现上述目标以实现预期目的,同时避免在实现类中实现代码重复。
答案 0 :(得分:5)
由于static
方法和类的类型参数(描述实例的参数化方式)之间没有关系,因此必须使static
方法本身具有通用性。棘手的部分是使声明正确描述所有需要的约束。正如this answer已经解释过的那样,你需要一个Class
参数,否则,实现没有机会得到实际的类型参数:
public interface DbValuesEnumIface<ID, T extends Enum<T>> {
public static
<ID, T extends Enum<T>&DbValuesEnumIface<ID,T>> T fromId(ID id, Class<T> type) {
if (id == null) {
return null;
}
for (T en : type.getEnumConstants()) {
if (en.getId().equals(id)) {
return en;
}
}
throw new NoSuchElementException();
}
ID getId();
String getDescriptionKey();
}
请注意,static
方法的类型参数独立于类的类型参数。为清楚起见,您可以考虑给他们不同的名称。
现在,给您enum Statuses implements DbValuesEnumIface<Integer,Statuses>
示例,您可以使用Statuses status = DbValuesEnumIface.fromId(42, Statuses.class);
请注意,对于default
方法,可以访问实际类型,因为实现将提供method providing the enum
type。您只需在interface
:
public interface DbValuesEnumIface<ID, T extends Enum<T>&DbValuesEnumIface<ID,T>> {
public default T fromId(ID id) {
if (id == null) {
return null;
}
for (T en : getDeclaringClass().getEnumConstants()) {
if (en.getId().equals(id)) {
return en;
}
}
throw new NoSuchElementException();
}
Class<T> getDeclaringClass();//no needed to implement it, inherited by java.lang.Enum
ID getId();
String getDescriptionKey();
}
然而,明显的缺点是您需要一个目标实例来调用该方法,即Statuses status = Statuses.SOME_CONSTANT.fromId(42);
答案 1 :(得分:2)
据我所知,没有简单的方法,首先您需要将方法更改为default
,您可以阅读更多here为什么您不能在静态上下文中使用泛型
但即使你把它改为default
,事情仍然无法发挥作用,因为你需要将枚举的实例或类类型传递给该方法,如下所示:
public default T fromId(ID id, Class<T> t) {
if (id == null) {
return null;
}
for (T en : t.getEnumConstants()) {
// dome something
}
return null;
}
现在你在fromId
内遇到了另一个问题 - 你唯一知道的是T
扩展了enum
- 而不是你的枚举,因此getId
(这似乎是你的枚举)编译器根本不知道。
除了声明界面之外,我不知道一个简单的方法来完成这项工作,例如:
interface IID {
public int getId();
}
让enum
实现它:
static enum My implements IID {
A {
@Override
public int getId() {
// TODO Auto-generated method stub
return 0;
}
};
}
并将声明更改为:
public interface DbValuesEnumIface<ID, T extends Enum<My> & IID>
答案 2 :(得分:1)
您可以从static
更改为default
,它将成功编译。
default EvaluationStatuses fromId(Integer id)