Java 通用签名接口中的静态方法

Java 通用签名接口中的静态方法,java,generics,interface,static,java-8,Java,Generics,Interface,Static,Java 8,从Java8开始,您可以在接口中实现缺省或静态方法,如下所示 public interface DbValuesEnumIface<ID, T extends Enum<T>> { T fromId(ID id); ID getId(); static String getDescriptionKey(){ return "this is a test"; } } 公共接口DbValuesEnumIface{ T fromId(ID

从Java8开始,您可以在接口中实现缺省或静态方法,如下所示

public interface DbValuesEnumIface<ID, T extends Enum<T>> {
   T fromId(ID id);

   ID getId();
   static String getDescriptionKey(){
      return "this is a test";
   }
}
公共接口DbValuesEnumIface{
T fromId(ID);
ID getId();
静态字符串getDescriptionKey(){
返回“这是一个测试”;
}
}
我想用静态方法声明上述内容,该方法具有一个使用实现类定义的边界的签名,因为该方法的实现对于所有人都应该是相同的,唯一不同的是声明的泛型,如下所示:

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>
公共接口DbValuesEnumIface{
公共静态T fromId(ID){
if(id==null){
返回null;
}
对于(T en:T.values()){
如果(en.getId().equals(id)){
返回en;
}
}
}
ID getId();
字符串getDescriptionKey();
}
...
公共枚举状态实现DbValuesEnumIface
因为T和ID不是静态的,不能从静态上下文引用,所以会中断


因此,应该如何修改上述内容以成功编译,如果不可能,则应如何实现上述内容以达到预期目的,同时避免实现类中的代码重复。

您可以将
静态
更改为
默认值
,它将成功编译


default EvaluationStatuses fromId(Integer id)

据我所知,没有简单的方法,首先您需要将方法更改为
default
,您可以阅读更多关于为什么不能在静态上下文中使用泛型的内容

但即使您将其更改为
default
,事情仍然不起作用,因为您需要将枚举的实例或类类型传递给该方法,如下所示:

public default T fromId(ID id, Class<T> t) {
        if (id == null) {
            return null;
        }
        for (T en : t.getEnumConstants()) {
            // dome something
        }
        return null;
}
使您的
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>
公共接口DbValuesEnumIface

由于
静态
方法与类的类型参数之间没有关系,类的类型参数描述了实例是如何参数化的,因此必须使
静态
方法本身具有通用性。棘手的部分是正确地获得声明来描述所有需要的约束。如前所述,您需要一个
参数,否则,实现没有机会获得实际的类型参数:

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();
}

然而,明显的缺点是需要一个目标实例来调用该方法,即
Statuses status=Statuses.SOME_CONSTANT.fromId(42)

不完全确定这个问题是否需要特别针对Java 8和接口。同样的规则一般也适用于类,当涉及到试图使用为类定义的类型参数的
静态
方法时,检查在接口中使用静态方法的能力是特定于Java8的,并且通过使用带有泛型的接口出现了问题。因此,相应地添加了标签。如果DbValuesEnumIface是一个我只是在子类中扩展的类,那么可能仍然会出现“``中断,因为T和ID不是静态的,不能从静态上下文中引用”``如果这就是您的意思的话。在这个例子中,作为一个接口,它可能有一些独特的纠结,这就是为什么要添加这个信息。没有纠结。类或接口。泛型类型参数遵循相同的规则。静态是静态的,实例是实例。此外,
T.values
,其中
T
是一个类或方法类型参数(不管
static
),违反了该语言的语法规则。当问题不是语言不可知时,请给出一个特别考虑语言规则的例子?更重要的是,一个讨论编译错误的问题肯定会消除所有与直接问题IMO无关的编译错误。实际上,有一个特定于接口的差异。对于普通类,您可以调用
超类
静态
方法,如
SubClass.method(…)
,这提高了可以使用继承的参数化(例如
类子类扩展超类
)的期望,但令人失望的是,这不起作用。相反,接口的
静态
方法不是从一开始就继承的。因此,您不能执行
status.fromId(…)
,而只能执行
DbValuesEnumIface.fromId(…)
,这显然需要明确提示
status
是要搜索的类。@Holger“接口的静态方法一开始并不是继承的”。虽然您可以使用默认方法(有人可能会认为这会导致相同的问题),Java可以解决冲突,但静态方法的处理方式却有所不同。接口中右边的一个应该是T fromId(ID)。我确实尝试将static更改为default,但它无法识别for(ten:T.values())中的values()方法。不过,您可能在这里了解到了一些情况,我将进一步研究这种方法。@Leon它无法识别values方法,因为
t
是一个类型参数,而不是引用。这与接口、默认方法或静态方法本身无关。也许先阅读泛型语法,然后再看更复杂的主题,比如这个?非常彻底的回答,我会阅读提供的链接以及你的建议。如果今天没有更好的答案,我一定会接受这个答案。谢谢。如果您有
参数,您已经有了所需的,那么没有理由将方法从
静态
更改为
默认
。您只需声明
必须是
枚举
,并实现所需的接口,讽刺的是,您在最后一行中演示了如何执行这些操作。hm。。但这意味着在接口级别声明的泛型和
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();
}
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();
}