由于之间没有关系static
方法和类的类型参数,它们描述了实例如何参数化,你必须使static
方法本身通用。棘手的部分是让声明正确地描述所有需要的约束。并作为这个答案 https://stackoverflow.com/a/47431082/2711488已经解释过了,你需要添加一个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
方法,可以访问实际类型,作为方法提供enum type https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html#getDeclaringClass--将由实施提供。您只需在该方法中声明该方法的存在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();
}
//no needed to implement it, inherited by java.lang.Enum
Class<T> getDeclaringClass();
ID getId();
String getDescriptionKey();
}
然而,明显的缺点是你需要一个目标实例来调用该方法,即Statuses status = Statuses.SOME_CONSTANT.fromId(42);