Использовать enum как общий тип моего класса, но не удалось создать экземпляр - PullRequest
0 голосов
/ 02 октября 2019

У меня есть Enum:

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 в качестве универсального типа? Если да, то есть ли обходной путь для достижения того, чего я хочу достичь?

Ответы [ 2 ]

1 голос
/ 02 октября 2019

Это потому, что Java не принимает тип перечисления в качестве универсального типа?

Любой тип перечисления является допустимым типом и может участвовать в формировании параметра типа (например, MyClass<T extends MyTypes>). ) и параметризация типа (например, MyClass<MyTypes> myInstance).

То, что вы сделали

MyClass<FOO> myInstanceWithFoo = new MyClass();

, никогда не бывает ошибочным, поскольку FOO является экземпляром (или объектом) MyTypes. Это не тип, и не может рассматриваться как таковой.

Если так, есть ли обходной путь для достижения того, чего я хочу достичь?

Нетнужно, чтобы MyClass было общим. Он объявляет поле MyTypes, которое может быть MyTypes.FOO или MyTypes.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();
  }
}
0 голосов
/ 03 октября 2019

Я предполагаю, что вы путаете FOO как подтип с MyClass, когда он фактически является экземпляром.

С помощью "обычных" обобщений вы указываете тип, который будет заполнителем:

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

который создается

GenericClass<String> gen = new GenericClass<>(); // String is a subclass of Object

, затем он компилируется в

public class GenericClass {
   private String generic;
}

Обратите внимание, что для String нет значения. Строкового экземпляра нет. Чтобы сделать это, нам либо нужен установщик или конструктор:

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, поэтому снова нам понадобится либо установщик, либо конструктор:

public class MyClass<T extends MyTypes> {
    private T theType;

    public MyClass(T theType) {
        this.theType = theType;
    }

}

, и чтобы убедиться, что у нас есть экземпляр FOO, мы передаем его конструктору

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

Надеюсь, это имеет смысл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...