关于java:枚举中的泛型类字段

Generic class field in enum

本问题已经有最佳答案,请猛点这里访问。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 clazz = Dictionaries.FIRST_DICTIONARY.clazz();

这个设计显然是不可能的,我想不出实现它的方法。有什么办法吗?我可以访问整个代码,所以我可以修改所有内容,包括接口(甚至删除它)。

我简化了所有这些,重点是每个字典都是一个数据库表,我有一个共同的DAO(而不是每个字典的DAO),现在我必须对我想要避免的每次读取的结果进行强制转换。我知道普通的刀不是一个好主意(或者根本不是刀)。

Optional entity = dao.getByValue(Dictionaries.FIRST_DICTIONARY, value);

在DAO本身或clazz()方法中,即使对于任何动态类型转换,我也无法找到一种方法。我觉得我错过了一些明显的东西。

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


正如jorn vernee所解释的,enum类型不允许这样做。

最简洁的解决方案,允许您编写

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

将是

1
2
3
4
5
6
public interface Dictionaries<T extends DictionaryModel> {
    Dictionaries<FirstDictionary>  FIRST_DICTIONARY  = () -> FirstDictionary.class;
    Dictionaries<SecondDictionary> SECOND_DICTIONARY = () -> SecondDictionary.class;

    Class<T> clazz();
}

但是,你可以再确认getByValue是否真的需要接受一个enum常数作为论据,而不是首先接受一个Class常数。


当前无法使用枚举。您给出的示例也在jep 301中给出:

1
2
3
4
5
6
7
8
9
10
11
12
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

但这不是语言的一部分

在此之前,您必须重构代码才能使用类,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
    }
}

现在你可以这样做了:

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