【问题标题】:Generic class field in enum [duplicate]枚举中的通用类字段[重复]
【发布时间】:2018-02-22 14:46:34
【问题描述】:
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;
    }
}

我有这个枚举。 FirstDictionarySecondDictionary 实现了 DictionaryModel,这是一个标记接口,用于使用此解决方案。

现在我很想这样做:

Class&lt;FirstDictionary&gt; clazz = Dictionaries.FIRST_DICTIONARY.clazz();

这种设计显然是不可能的,我想不出实现这一点的方法。有没有办法做到这一点?我可以访问整个代码,所以我可以修改所有内容,包括界面(甚至删除它)。

我简化了所有这些,关键是每个字典都是一个数据库表,我为它们有一个公共 DAO(而不是每个字典的 DAO),现在我必须转换我想要的每次读取的结果避免。我知道通用 DAO 不是一个好主意(或根本不是 DAO)。

Optional&lt;DictionaryModel&gt; entity = dao.getByValue(Dictionaries.FIRST_DICTIONARY, value);

对于任何动态转换,在 DAO 本身或 clazz() 方法中,我似乎都没有办法。我觉得我在这里遗漏了一些明显的东西。

我很欣赏任何想法,甚至完全改变设计。

【问题讨论】:

    标签: java generics java-8


    【解决方案1】:

    由于explained by Jorn Verneeenum 类型不允许这样做。

    最简洁的解决方案,让您编写类似的东西

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

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

    但您可能会重新考虑 getByValue 是否真的需要接收 enum 常量作为参数,而不是首先接受 Class&lt;T extends DictionaryModel&gt;

    【讨论】:

    • 两个很好的答案,我接受这个,因为毕竟我使用了这个解决方案,很乐意接受这两个。
    • 您好,是否可以使用两种方法而不是一种方法进行这种初始化?还是应该使用抽象类?
    • @Jessy 因为 lambda 表达式仅适用于函数式接口,即具有一种抽象方法的接口,您必须使用匿名内部类来实现具有两种方法的接口。
    【解决方案2】:

    目前这对于枚举是不可能的。你给出的例子也在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();
    

    【讨论】:

      猜你喜欢
      • 2017-03-12
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      • 2016-01-02
      • 1970-01-01
      • 2017-03-24
      • 2023-04-01
      相关资源
      最近更新 更多