在 Java 中,是否可以从构造函数帮助器初始化 final 字段?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2859577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Java, can a final field be initialized from a constructor helper?
提问by csj
I have a final non-static member:
我有一个最终的非静态成员:
private final HashMap<String,String> myMap;
I would like to initialize it using a method called by the constructor. Since myMap is final, my "helper" method is unable to initialize it directly. Of course I have options:
我想使用构造函数调用的方法对其进行初始化。由于 myMap 是最终的,我的“助手”方法无法直接初始化它。我当然有选择:
I could implement the myMap initialization code directly in the constructor.
我可以直接在构造函数中实现 myMap 初始化代码。
MyConstructor (String someThingNecessary)
{
myMap = new HashMap<String,String>();
myMap.put("blah","blahblah");
// etc...
// other initialization stuff unrelated to myMap
}
I could have my helper method build the HashMap, return it to the constructor, and have the constructor then assign the object to myMap.
我可以让我的辅助方法构建 HashMap,将它返回给构造函数,然后让构造函数将对象分配给 myMap。
MyConstructor (String someThingNecessary)
{
myMap = InitializeMyMap(someThingNecessary);
// other initialization stuff unrelated to myMap
}
private HashMap<String,String> InitializeMyMap(String someThingNecessary)
{
HashMap<String,String> initializedMap = new HashMap<String,String>();
initializedMap.put("blah","blahblah");
// etc...
return initializedMap;
}
Method #2 is fine, however, I'm wondering if there's some way I could allow the helper method to directly manipulate myMap. Perhaps a modifier that indicates it can only be called by the constructor?
方法#2 很好,但是,我想知道是否有某种方法可以让辅助方法直接操作 myMap。也许一个修饰符表明它只能被构造函数调用?
MyConstructor (String someThingNecessary)
{
InitializeMyMap(someThingNecessary);
// other initialization stuff unrelated to myMap
}
// helper doesn't work since it can't modify a final member
private void InitializeMyMap(String someThingNecessary)
{
myMap = new HashMap<String,String>();
myMap.put("blah","blahblah");
// etc...
}
采纳答案by Yishai
Method #2 is your best option. The problem is that if you have an assignment in a private method there is nothing preventing other code in the class outside the constructor calling it, which would then create an issue with an attempted second assignment to the final field.
方法#2 是您最好的选择。问题是,如果您在私有方法中进行了赋值,则不会阻止构造函数之外的类中的其他代码调用它,这会导致尝试对最终字段进行第二次赋值时出现问题。
Java has no construct of a separate method that can only be called during construction.
Java 没有构造单独的方法,只能在构造过程中调用。
For completeness, we can make a third option, where you assign the map at initialization and then have the helper method fill it:
为了完整起见,我们可以做第三个选项,在初始化时分配映射,然后让辅助方法填充它:
private final HashMap<String, String> myMap = new HashMap<String, String();
And then:
进而:
MyConstructor (String someThingNecessary)
{
initializeMyMap(someThingNecessary);
// other initialization stuff unrelated to myMap
}
// helper doesn't work since it can't modify a final member
private void initializeMyMap(String someThingNecessary)
{
myMap.clear();
myMap.put("blah","blahblah");
// etc...
}
And if you really want to be confusing you can use an initializer instead of a constructor, but you should not do that, so unless you really need to know, I won't expand on that.
如果你真的想混淆你可以使用初始化器而不是构造器,但你不应该这样做,所以除非你真的需要知道,否则我不会扩展。
回答by Simon
Option #2 is the most resuable option, because you can share it among all constructors. What we would need here, are collection initializers of c#. :)
选项#2 是最可重用的选项,因为您可以在所有构造函数之间共享它。我们在这里需要的是 c# 的集合初始值设定项。:)
(BTW: #3 won't compile)
(顺便说一句:#3 不会编译)
回答by cjerdonek
How about implementing a private constructor that initializes your HashMap, and then have your main constructor(s) call that private constructor?
如何实现一个私有构造函数来初始化你的 HashMap,然后让你的主构造函数调用那个私有构造函数?
For example--
例如 -
// Helper function to initialize final HashMap.
private MyConstructor()
{
myMap = new HashMap<String,String>();
myMap.put("blah","blah");
}
MyConstructor (String someThingNecessary)
{
// Initialize the HashMap.
this();
// Other initialization code can follow.
}
You can modify the signature of the private helper constructor as needed (e.g. to provide parameter data or to make the signature distinct from any public constructors).
您可以根据需要修改私有辅助构造函数的签名(例如,提供参数数据或使签名与任何公共构造函数不同)。