java - 在构造函数中使用反射设置最终字段

java - Set final fields with reflection in Constructor

我正在尝试制作一个多语言应用程序,其中包含多个 *.properties 文件中的消息。我已经开始做这样的事情了:


    public Language(@NotNull Map<String, String> info) {
        Validate.notNull(info, "Language information cannot be null");

        this.PLUGIN_PREFIX = info.get("PLUGIN_PREFIX");
        this.ARGUMENT_CODE = info.get("ARGUMENT_CODE");
        // etc...
    }

现在,有很多消息,我不想每次都输入相同的内容(加上我可能会出现错别字,这可能是个问题...)。

我第一个想到的解决方案是循环遍历所有类似的字段(大写,最终,非静态等),然后使用反射将字段名称作为键来设置它作为价值。显然编译器不会让我,因为它认为 final 字段还没有被初始化。

像这样:

    public Language(@NotNull Map<String, String> info) {
        Validate.notNull(info, "Language information cannot be null");

        Field[] fields = /* TODO get fields */ new Field[0];
        
        for (Field f : fields) f.set(f.getName(), info.get(f.getName()));
    }

有什么办法可以做到吗?或者有更好的解决方案吗?

编辑:快速命名约定问题,这些最终的“常量”应该大写吗?

通常,您不会将文本消息直接存储在常量中,而是只存储消息键。然后您使用这些键来获取地图中的实际文本消息。

可以直接使用地图,但是在Java中有ResourceBundle。可以直接从 .properties 文件加载 ResourceBundle。

我的-bundle_en.properties:

my.message=Hello, world!

my-bundle_fr.properties:

    my.message=Bonjour tout le monde!
    
    my-bundle_de.properties:
    
    my.message=Hallo Welt!
    
    

Something.java:

public static final MY_MESSAGE = "my.message";
    
ResourceBundle bundle = ResourceBundle.getBundle("my-bundle");
String text = bundle.getMessage(MY_MESSAGE);
    System.out.println(text);