java - 在 Java 中使用枚举来表示 ResourceBundle 中的键

标签 java enums resourcebundle

这几天一直在琢磨这个想法,不知道有没有人想过这样做。我想尝试创建一个 ResourceBundle,我可以使用枚举访问它的值。这种方法的好处是我的键将被很好地定义,并且希望我的 IDE 可以选择类型并为我自动完成变量名称。换句话说,我正在寻找一种改进的 ListResourceBundle。

本质上,这就是我所追求的......

我有一个枚举,它由像这样设置的各种包组成:

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);
    }
}

所以我的总体目标是让代码看起来像这样:

public static void main(String[] args) {
    Bundles.CLIENT.getEnumResourceBundle().getString(Keys.KEY1);
    Bundles.CLIENT.getEnumResourceBundle().getString(Keys.KEY2);

    // or Bundles.CLIENT.getString(Keys.KEY1);
}

我还想为格式化替换(%s、%d、...)提供支持。

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

更新: 我有一个想法,也许我也可以尝试更改 EnumResourceBundle#getString(E) 以取而代之,但这并不能保证它是枚举中指定的有效键,或与此相关的任何枚举。再一次,我不确定在子 EnumResourceBundle 中使用父枚举 Key 时该方法如何工作,所以 Key 可能是更好的选择。

最佳答案

我以前做过类似的事情,但我用另一种方法来处理它,它非常简单。

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

我使用了一个资源包,然后翻译看起来像(根据内存):

<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!

如果你想确保传递的类是正确的枚举,你可以为这些枚举定义一个共享接口(interface),或者你可以将它变成一个在类类型上定义了 T 的类,然后生成它的实例对于您希望能够翻译的每个枚举。然后,您可以通过执行 new EnumFormatter() 来为任何枚举创建一个翻译器类。使 format() protected 将允许您通过在 EnumFormatter 中实现为每个枚举类型提供特定的可执行格式。

使用类的想法甚至可以让您更进一步,当您创建类时,您可以指定它所针对的枚举和属性文件。然后它可以立即扫描属性文件并确保枚举中的每个值都有一个映射 - 如果缺少一个则抛出异常。这将有助于确保尽早检测到属性文件中的任何缺失值。

关于java - 在 Java 中使用枚举来表示 ResourceBundle 中的键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20771575/

相关文章:

python 通过字符串值获取枚举不起作用

java - Java 中的资源包是否支持运行时字符串替换?

java - 为什么ArrayList能够去掉这个呢?

在位域整数与结构之间选择?

java - 在与主线程不同的另一个线程中启动 swing gui,以在计算时更新 jtextarea

java - 通过常量特定数据在枚举常量中查找

java - 从 ResourceBundle 中获取整数时,整数会被格式化为逗号

Java:如何在运行时将数据库中的属性添加到 ResourceBundle?

java - 解析选项字符串的正则表达式

java - 我正在尝试从广播接收器发出 API 请求,有人能提到正确的方法吗?