【问题标题】:Use enum as generic type of my class but failed to create instance使用枚举作为我的类的泛型类型但未能创建实例
【发布时间】:2019-10-03 05:28:23
【问题描述】:

我有枚举:

public enum MyTypes {FOO, BAR}

我用泛型定义了一个类:

public MyClass<T extends MyTypes> {
  private T theType;
  ...
}

以上代码编译成功。

接下来,我尝试创建一个 MyClass 的实例,类型为 Foo 作为泛型参数:

// Compilation error: Cannot resolve symbol FOO
MyClass<FOO> myInstanceWithFoo = new MyClass();

是不是因为 Java 不接受 enum 类型作为泛型类型?如果是这样,是否有解决方法来实现我想要实现的目标?

【问题讨论】:

    标签: java generics enums


    【解决方案1】:

    是不是因为 Java 不接受枚举类型作为泛型类型?

    任何枚举类型都是有效类型,并且可以参与形成类型参数(例如MyClass&lt;T extends MyTypes&gt;)和参数化类型(例如MyClass&lt;MyTypes&gt; myInstance)。

    你做了什么

    MyClass<FOO> myInstanceWithFoo = new MyClass();
    

    永远不会正确,因为FOOMyTypes 的实例(或对象)。它不是一个类型,不能这样对待。

    如果是这样,是否有解决方法来实现我想要实现的目标?

    MyClass 没有必要是通用的。它声明了一个MyTypes 字段,可以是MyTypes.FOOMyTypes.BAR(当然也可以是null)。

    class MyClass {
      private MyTypes myType;
    
      public MyClass(MyTypes myType) {
        this.myType = myType;
      }
    }
    

    每个MyTypes 实例都知道如何从自己创建MyClass

    enum MyTypes {
      FOO, BAR;
    
      public MyClass createMyClass() {
        return new MyClass(this);
      }
    }
    

    如何创建它们的示例是

    class Example {
      public static void main(String[] args) {
        MyClass myInstanceWithFoo = MyTypes.FOO.createMyClass();
        MyClass myInstanceWithBar = MyTypes.BAR.createMyClass();
      }
    }
    

    【讨论】:

    • 谢谢。除了您的回答之外,如果 MyTypes 来自我无法修改以在其中添加 createMyClass() 函数的第 3 方库怎么办?
    • @Leem.fin 然后直接初始化它们:new MyClass(MyTypes.FOO)
    • @Leem.fin 你为什么不接受?有什么可以改进的吗?
    【解决方案2】:

    我猜你将 FOO 混淆为 MyClass 的子类型,而实际上它是一个实例。

    使用“普通”泛型,您可以指定占位符的类型:

    public class GenericClass <T extends Object> { // a bit contrived here
        private T generic;
    }
    

    实例化的

    GenericClass&lt;String&gt; gen = new GenericClass&lt;&gt;(); // String is a subclass of Object

    然后编译成

    public class GenericClass {
       private String generic;
    }
    

    请注意,字符串没有值。没有 String 实例。 为此,我们需要一个 setter 或构造函数:

    public class GenericClass<T extends Object> {
        private T generic;
    
        public GenericClass(T generic) {
            this.generic = generic;
        }
    
    }
    
    GenericClass<String> gen = new GenericClass<>("Passing in a String because T was a String");
    

    GenericClass<Integer> gen2 = new GenericClass<>(2); // T is integer so we can only pass integers - 2 will be the instance.
    

    因此,对于作为泛型类型的 Enum,我们声明的是 MyType 类型。该值将是 FOO,所以我们需要一个 setter 或一个构造函数:

    public class MyClass<T extends MyTypes> {
        private T theType;
    
        public MyClass(T theType) {
            this.theType = theType;
        }
    
    }
    

    为了确保我们有一个 FOO 实例,我们将它传递给构造函数

    MyClass<MyTypes> myInstanceWithFoo = new MyClass<>(MyTypes.FOO);
    

    希望这是有道理的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多