枚举中的通用类字段

5
public enum Dictionaries {
    FIRST_DICTIONARY(FirstDictionary.class),
    SECOND_DICTIONARY(SecondDictionary.class);

    private Class<? extends DictionaryModel> clazz;

    private Dictionary(Class<? extends DictionaryModel> clazz) {
        this.clazz = clazz;
    }

    public Class<? extends DictionaryModel> clazz() {
        return this.clazz;
    }
}

我有这个枚举类型。`FirstDictionary` 和 `SecondDictionary` 实现了 `DictionaryModel` 接口,这是为了使用这个解决方案而创建的标记接口。
目前我希望能够这样做:
```java Class clazz = Dictionaries.FIRST_DICTIONARY.clazz(); ```
显然,在当前设计中这是不可能的,我也想不到实现它的方法。是否有任何方法可以做到这一点?我可以修改整个代码,包括接口(甚至删除它)。
我简化了所有内容,关键是每个字典都是一个数据库表,我有一个通用的 DAO(而不是每个字典一个 DAO),现在我必须强制转换每次读取的结果,我希望避免这样做。我知道通用DAO不是一个好主意(或者根本就不需要DAO)。
```java Optional entity = dao.getByValue(Dictionaries.FIRST_DICTIONARY, value); ```
我甚至无法找到任何动态转换的方法,在 DAO 本身或 `clazz()` 方法中。我感觉自己漏掉了什么很明显的东西。
我非常感谢任何想法,即使是完全改变设计的想法。
2个回答

6

正如Jorn Vernee所解释的那样enum类型不允许这样做。

最简洁的解决方案是允许您编写类似于以下内容的代码:

Class<FirstDictionary> clazz = Dictionaries.FIRST_DICTIONARY.clazz();

would be

public interface Dictionaries<T extends DictionaryModel> {
    Dictionaries<FirstDictionary>  FIRST_DICTIONARY  = () -> FirstDictionary.class;
    Dictionaries<SecondDictionary> SECOND_DICTIONARY = () -> SecondDictionary.class;

    Class<T> clazz();
}

但是您可能需要重新考虑是否需要将getByValue方法的参数设置为枚举常量,而不是在一开始就接受Class<T extends DictionaryModel>


两个很好的答案,我选择接受这一个,因为毕竟我使用了这个解决方案,也很乐意接受另一个。 - Shadov
你好,这种初始化方式是否可以使用两种方法来实现?还是我应该使用抽象类? - Spialdor
2
@Jessy,由于lambda表达式仅适用于函数式接口,即只有一个抽象方法的接口,因此您必须使用匿名内部类来实现具有两个方法的接口。 - Holger

4

目前枚举类型无法实现此功能。你提供的示例也在JEP 301中提到:

enum Argument<X> { // declares generic enum
   STRING<String>(String.class), 
   INTEGER<Integer>(Integer.class), ... ;

   Class<X> clazz;

   Argument(Class<X> clazz) { this.clazz = clazz; }

   Class<X> getClazz() { return clazz; }
}

Class<String> cs = Argument.STRING.getClazz(); //uses sharper typing of enum constant

但是目前这不是语言的一部分。

在那之前,您需要重构代码来使用类,例如:

interface DictionaryModel {}
class FirstDictionary implements DictionaryModel {}
class SecondDictionary implements DictionaryModel {}

// Following a model similar to how enums are implemented, but with sharper typing:
abstract class Dictionaries<T extends DictionaryModel> {
    public static final Dictionaries<FirstDictionary> FIRST_DICTIONARY 
        = new Dictionaries<>(FirstDictionary.class) {};
    public static final Dictionaries<SecondDictionary> SECOND_DICTIONARY 
        = new Dictionaries<>(SecondDictionary.class) {};

    private final Class<T> clazz;

    private Dictionaries(Class<T> clazz) {
        this.clazz = clazz;
    }

    public Class<T> clazz() {
        return this.clazz;
    }
}

现在你可以做到这一点:
Class<FirstDictionary> clazz = Dictionaries.FIRST_DICTIONARY.clazz();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接