【问题标题】:Java Parameter and return types for enum that implements interface实现接口的枚举的 Java 参数和返回类型
【发布时间】:2012-09-06 18:53:22
【问题描述】:

经过大量搜索,我发现了很多与普通课程相关的问题,但没有一个与枚举真正相关。

这很好用:

package list;

public interface Testing { 
    //treat as a tag interface.
}
package list;

public class Foo implements Testing {
}
package list;

import java.util.ArrayList;
import java.util.List;

public class Bar {
    public Bar(){
        List<Foo> myList = new ArrayList<Foo>();
        myList.add(new Foo());
        testList(myList);
        testMethod(new Foo());
    }

    public void testMethod(Testing myInstance){
        //do nothing
    }

    public <Testing> void testList(List<Testing> myList){
        //do nothing
    }
}

但是,我的问题在于理解当我尝试做同样的事情时会发生什么 Enums 代替 Foo

这里的例子是有一个接口定义,它被定义为接受一个接口参数,实际上,它是由一个实现接口的枚举实现的:

我有两个接口:

public interface MyEnumInterface {
  //implemented by Enums
}
import java.util.List;

public interface SecondInterface {
    public MyEnumInterface testMe(String myString);
    public <MyEnumInterface> List<MyEnumInterface> testingList();
    public List <MyEnumInterface> enumTestOne(String anotherString);
    public List <MyEnumInterface> enumTestTwo(String anotherString);
}

两个emum如下:

public enum MyEnum implements MyEnumInterface{
    VALUE_ONE,
    VALUE_TWO,
    VALUE_THREE;
}
public enum MyEnum2 implements MyEnumInterface{
    VALUE_A,
}

还有一个测试java类:

import java.util.ArrayList;
import java.util.List;

class MyClass implements SecondInterface{

    public MyClass(){
        single(testMe(""));
        enumTestOne("");
        enumTestTwo("");
    }
    public MyEnum testMe(String someParam){
            return MyEnum.VALUE_ONE;
    }

    public List<MyEnumInterface> enumTestOne(String anotherString) {
        List<MyEnum> returnL = new ArrayList<MyEnum>();
        returnL.add(MyEnum.VALUE_ONE);
        returnL.add(MyEnum.VALUE_THREE);
        return returnL;
    }

    public List<MyEnumInterface> enumTestTwo(String anotherString) {
        List<MyEnum2> returnL = new ArrayList<MyEnum2>();
        returnL.add(MyEnum2.VALUE_A);
        return returnL;
    }


    public List<MyEnum> testingList(){
        List<MyEnum> returnL = new ArrayList<MyEnum>();
        returnL.add(MyEnum.VALUE_ONE);
        returnL.add(MyEnum.VALUE_THREE);
        return returnL;
    }


    public void single(MyEnumInterface val){
        System.out.println("Value is " + val);
    }


    public static void main(String[] args){
        MyClass clazz = new MyClass();
    }
}

我正在与 enumTestOne(..) 的返回类型被编码为 List 但接口指定一个 List 的问题作斗争。当它是 Enum 'MyEnum' 的单个实例时,它工作正常,但是当它是一个值列表时,它似乎失败了:

"错误:类 MyClass 中的方法列表不能应用于给定类型; 必需:列表 找到:列表 原因:实参List无法通过方法调用转换为List”

我不确定解决这个问题的方法 - 我已经尝试添加您在上面看到的声明,以便它显示 public &lt;MyEnumInterface&gt; List&lt;MyEnumInterface&gt; testingList(); 但这给了我关于未经检查的演员表的“警告”,同时继续失败

这一切都源于我对泛型以及它们与枚举的关系缺乏更深入的了解。

我看到了一些有趣的声明 &lt;? extends Enum&lt;E&gt; &amp; SecondInterface&gt; 但这扩展了我的理解。请帮忙!

顺便说一句,我认为返回类之前的泛型声明用于指定“T”用于类型侵蚀目的是否正确?

【问题讨论】:

    标签: java interface enums


    【解决方案1】:

    泛型本质上是invariant。所以List&lt;String&gt; 不是List&lt;Object&gt; 的子类型

    您必须更改方法以包含 MyEnumInterface 列表,而不是单独的枚举类。

    public List<MyEnumInterface> enumTestOne(String anotherString) {
        List<MyEnumInterface> returnL = new ArrayList<MyEnumInterface>();//Change
        returnL.add(MyEnum.VALUE_ONE);
        returnL.add(MyEnum.VALUE_THREE);
        return returnL;
    }
    
    public List<MyEnumInterface> enumTestTwo(String anotherString) {
        List<MyEnumInterface> returnL = new ArrayList<MyEnumInterface>();//Change
        returnL.add(MyEnum2.VALUE_A);
        return returnL;
    }
    

    【讨论】:

    • 感谢 AmitD 的解释,但我真的在寻求类似于 Andersschuller 在下面发布的解决方案 - 试图将实现定义为返回特定类型的实例而不是接口声明。
    【解决方案2】:

    如果要允许实现类定义使用MyEnumInterface 的哪个实现,可以将接口方法的返回类型指定为任何MyEnumInterfaceList

    public List<? extends MyEnumInterface> enumTestOne(String anotherString);
    public List<? extends MyEnumInterface> enumTestTwo(String anotherString);
    

    这些方法的实现可以定义具体的返回类型。

    public List<MyEnum> enumTestOne(String anotherString) {
        List<MyEnum> returnL = new ArrayList<MyEnum>();
        returnL.add(MyEnum.VALUE_ONE);
        returnL.add(MyEnum.VALUE_THREE);
        return returnL;
    }
    
    public List<MyEnum2> enumTestTwo(String anotherString) {
        List<MyEnum2> returnL = new ArrayList<MyEnum2>();
        returnL.add(MyEnum2.VALUE_A);
        return returnL;
    }
    

    顺便说一句,您可以在“反向”中使用super 执行相同的操作。这指定可以使用作为给定类型的超类型的任何类型。

    public void addToList(List<? super MyEnum> list) {
        list.add(MyEnum.VALUE_ONE);
    }
    
    addToList(new ArrayList<MyEnum>());
    addToList(new ArrayList<MyEnumInterface>());
    

    另见

    Java Generics (Wildcards)

    Why is SomeClass not equivalent to SomeClass in Java generic types?

    【讨论】:

    • 非常感谢 Anderschuller,被选为示例和“另见”:不是第一个,但解决方案完全是我所追求的。谢谢。
    • 我完全错过了泛型中使用“扩展”来表示子类以及子接口/接口实现。
    猜你喜欢
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多