使用Java中的枚举表示ResourceBundle中的键

使用Java中的枚举表示ResourceBundle中的键,java,enums,resourcebundle,Java,Enums,Resourcebundle,我已经对这个想法进行了几天的修改,我想知道是否有人想过这样做。我想尝试创建一个ResourceBundle,我可以使用枚举访问这些值。这种方法的好处是可以很好地定义我的键,并且希望我的IDE能够识别类型并为我自动完成变量名。换句话说,我想要的是一种精致的ListResourceBundle 本质上,这就是我想要的 我有一个enum,它由各种bundle组成,如下所示: interface Bundle { String getBundleName(); EnumResourceB

我已经对这个想法进行了几天的修改,我想知道是否有人想过这样做。我想尝试创建一个ResourceBundle,我可以使用枚举访问这些值。这种方法的好处是可以很好地定义我的键,并且希望我的IDE能够识别类型并为我自动完成变量名。换句话说,我想要的是一种精致的ListResourceBundle

本质上,这就是我想要的

我有一个enum,它由各种bundle组成,如下所示:

interface Bundle {
    String getBundleName();
    EnumResourceBundle<??????> getEnumResourceBundle();
}

enum Bundles implements Bundle {
    BUNDLE1("com.example.Bundle1", Keys.class);

    private final String bundleName;
    private final EnumResouceBundle<??????> bundle;

/**
 * I understand here I need to do some cast with ResourceBundle.getBundle(bundleName);
 * in order to have it back-track through parents properly. I'm fiddling with this
 * right now using either what I specified earlier (saving bundleName and then
 * retrieving the ResourceBundle as needed), and saving a reference to the 
 * ResourceBundle.
 */
    private <E extends Enum<E> & Key> Bundles(String bundleName, Class<E> clazz) {
        this.bundleName = bundleName;
        this.bundle = new EnumResourceBundle<??????>(clazz);
    }

    @Override
    public String getBundleName() {
        return bundleName;
    }

    @Override
    public EnumResourceBundle<??????> getEnumResourceBundle() {
        return bundle;
    }
}

interface Key {
    String getValue();
}

enum Keys implements Key {
    KEY1("This is a key"),
    KEY2("This is another key");

    private final String value;

    private Keys(String value) {
        this.value = value;
    }

    @Override
    public String getKey() {
        return value;
    }
}

class EnumResourceBundle<E extends Enum<E> & Key> extends ResourceBundle {
    // Can also store Object in case we need it
    private final EnumMap<E, Object> lookup;

    public EnumResourceBundle(Class<E> clazz) {
        lookup = new EnumMap<>(clazz);
    }

    public String getString(E key) {
        return (String)lookup.get(key);
    }
}
我还想为格式化替换(%s,%d,…)提供支持

我意识到不可能从类中回溯类型,这对我没有帮助,因为我已经实例化了Bundles#bundle,所以我想知道是否可以以某种方式声明EnumResourceBundle,其中泛型类型是一个实现了键接口的enum。任何想法、帮助或想法都将不胜感激。在使用命名常量之前,我真的很想看看是否能让它像这样工作

更新:
我有一个想法,也许我也可以尝试将EnumResourceBundle#getString(E)改为使用一个键,但这不能保证它是在enum或任何enum中指定的有效键。再说一次,我不确定在子EnumResourceBundle中使用父enum键时该方法如何工作,所以可能键是一个更好的选择。

我以前做过类似的事情,但我采用了另一种方法,而且非常简单

我刚刚创建了一个接受枚举的枚举转换器类,然后将枚举名称映射到属性文件中的值

我使用了单个资源包,然后翻译看起来就像(从内存中):

如果要确保传递的类是正确的枚举,您可以为这些枚举定义一个共享接口,也可以将其生成一个在类类型上定义了T的类,然后为要转换的每个枚举生成它的实例。然后,只需执行new EnumFormatter(),就可以为任何枚举创建转换器类。使
format()
受保护将允许您通过在EnumFormatter中实现为每种枚举类型提供特定的可执行格式


使用类的思想甚至可以让您更进一步,当您创建类时,您可以指定它的枚举和属性文件。然后,它可以立即扫描属性文件,并确保枚举中的每个值都有一个映射,如果缺少一个值,就会抛出一个异常。这将有助于确保及早发现属性文件中丢失的任何值。

Ya,我也想过做类似的事情。但按照我的方法,不同的翻译将位于基于类的系统中,而不是属性文件中。我想再等一会儿,看看还有没有人有什么想法。今天我将进行更多的实验,看看是否可以尝试解决这个问题。
当你说“创建类”时,你是说为每个lang文件创建一个类吗?我尝试了一次迭代,在类中定义bundle以及它应该使用的键。你说的基于类的系统是什么意思?一般来说,在代码中嵌入翻译是个坏主意,您希望将它们放在单独的文件中,这样做的人就可以轻松地处理它们。docs.oracle.com/javase/tutorial/i18n/resbundle/list.html抱歉,当我尝试返回时,它是过早发布的。我理解这是不好的,我更愿意这样做(属性文件更容易编辑),但是通过配置它们来使用像FOO(“这是一个FOO”)这样的枚举,其中FOO是键,“这是一个FOO”是我的值(不同的版本会用自己的翻译覆盖该值,它似乎定义得更明确。我可能最终会使用FOO->FOO.toString()作为键,并将其作为属性文件中的字符串键。
public static void main(String[] args) {
    Bundles.CLIENT.getEnumResourceBundle().getString(Keys.KEY1);
    Bundles.CLIENT.getEnumResourceBundle().getString(Keys.KEY2);

    // or Bundles.CLIENT.getString(Keys.KEY1);
}
<T extends enum>String translate(T e) {
   return resources.getString(e.getClass().getName()+"."+e.getName());
}

<T extends enum>String format(T e, Object... params) {
   return MessageFormat.format(translate(e), params);
}
com.example.MyEnum.FOO = This is a foo
com.example.MyEnum.BAR = Bar this!