英文:
Java enum get null in static method of my enum class
问题
I got a enum class to store my message and I want to use a static method in it to put them to a hashmap.
But NullPointerException just happened.
How can I fix it?
Msg.java
public enum Msg {
//Common
Message1("this"),
Message2("is"),
Message3("not"),
Message4("cool");
private String message;
private static HashMap<Msg, String> Msgmap;
private static HashMap<Msg, String> getMsgmap(){
return Msgmap;
}
Msg(String msg) {
this.message = msg;
if(getMsgmap() == null) {
setupMessageMap();
}
}
private static void setupMessageMap() {
Msgmap = new HashMap<Msg, String>();
for(Msg msg : values()){
Msgmap.put(msg, msg.message);
}
}
}
If I replace
for(Msg msg: values()){
langmap.put(msg, msg.message);
}
with
System.out.println(Message1.message);
will also throw NullPointerException
But if I try to print my enum strings in constructor.
It will just work.
英文:
I got a enum class to store my message and I want to use a static method in it to put them to a hashmap.
But NullPointerException just happened.
How can I fix it?
Msg.java
public enum Msg {
//Common
Message1("this"),
Message2("is"),
Message3("not"),
Message4("cool");
private String message;
private static HashMap<Msg, String> Msgmap;
private static HashMap<Msg, String> getMsgmap(){
return Msgmap;
}
Msg(String msg) {
this.message = msg;
if(getMsgmap() == null) {
setupMsgMap();
}
}
private static void setupMessageMap() {
Msgmap = new HashMap<Msg, String>();
for(Msg msg :values()){
Msgmap.put(msg, msg.message);
}
}
}
If I replace
for(Msg msg:values()){
langmap.put(msg, msg.message);
}
with
System.out.println(Message1.message);
will also throw NullPointerException
But if I try to print my enum strings in constructor.
It will just works.
答案1
得分: 1
如果可以的话,我建议你使用最终的不可变字段。这样,你就不必担心线程安全的问题。
一些你应该知道的信息:
- 枚举的构造函数会被调用与枚举常量的数量相同次数。
- 对于至少有一个常量的枚举,不可能编写在构造函数之前被调用的静态块。
- 在这种情况下,你可以在静态块中初始化静态字段。
以下是基于@charlie-armstrong的代码的我的版本:
enum Message { // 类名为 "Message"
Message1("this"),
Message2("is"),
Message3("not"),
Message4("cool"); // 行以分号结束
private static final HashMap<Message, String> Msgmap = new HashMap<>(); // 在这里初始化Msgmap
static {
for (Message msg : values()) { // 循环遍历所有枚举常量
Msgmap.put(msg, msg.message); // 将它们全部添加到HashMap中
}
}
private final String message;
Message(String msg) {
this.message = msg;
// 我不在构造函数中设置Msgmap,因为它仍然在这里初始化自己,所以我们不能立即将它添加到HashMap中
}
public static Map<Message, String> getMsgmap() {
return Msgmap;
}
}
英文:
If you can, i recommend you to use final immutable fields. This way you don't have to worry about thread safety.
Some information you should know:
- Enum constructor is called as many times as many constants the enum has.
- For enums which have at least one constant, it is impossible to write static block which will be called before constructor.
- In this case you can init static fields in static block.
Below is my version, based on @charlie-armstrong code:
enum Message { //the class is named "Message"
Message1("this"),
Message2("is"),
Message3("not"),
Message4("cool"); //line ends in a semicolon
private static final HashMap<Message, String> Msgmap = new HashMap<>(); //Msgmap is initialized here
static {
for (Message msg : values()) { //loop through all the enum constants
Msgmap.put(msg, msg.message); //add them all to the HashMap
}
}
private final String message;
Message(String msg) {
this.message = msg;
//I don't set up Msgmap in the constructor, because it is still initializing itself here, so we can't possibly add it to a HashMap yet
}
public static Map<Message, String> getMsgmap() {
return Msgmap;
}
}
答案2
得分: 0
以下是您的代码的翻译:
public enum Msg { //应该叫做“Message”,因为它在Message.java中
//Common
Message1("this"), //消息1
Message2("is"), //消息2
Message3("not"), //消息3
Message4("cool"), //语法错误,行应该以分号(;)结束
private String message; //私有字符串变量
private static HashMap<Msg, String> Msgmap; //Msgmap从未初始化
private static HashMap<Msg, String> getMsgmap(){
return Msgmap;
}
Msg(String msg) { //再次强调,应该命名为“Message”,而不是“Msg”
this.message = msg;
if(getMsgmap() == null) { //这将始终为true,因为Msgmap从未初始化
setupMsgMap(); //这将运行4次(每个枚举值运行一次)
}
}
private static void setupMessageMap() {
langmap = new HashMap<Lang, String>(); //语法错误(您没有声明或推断类型),而且Lang类没有提供给我们,我假设您想使用Msg类而不是Lang类
for(Lang lang:values()){ //在此处发生NullPointerException。我们仍在初始化第一个枚举常量,但您要求编译器循环遍历所有枚举常量。但它们还没有初始化,实际上它们还不存在。
langmap.put(lang, lang.lang);
}
}
}
以下是更新后的代码:
public enum Message { //类名为“Message”
Message1("this"), //消息1
Message2("is"), //消息2
Message3("not"), //消息3
Message4("cool"); //行以分号结束
private String message; //私有字符串变量
private static HashMap<Message, String> Msgmap = new HashMap<>(); //在此处初始化Msgmap
public static HashMap<Message, String> getMsgmap() {
return Msgmap;
}
Message(String msg) {
this.message = msg;
//我不在构造函数中设置Msgmap,因为它仍在此处初始化,所以我们不可能将其添加到HashMap中
}
public static void setupMsgMap() { //这需要在初始化之后从外部调用
for (Message msg : values()) { //循环遍历所有枚举常量
Msgmap.put(msg, msg.message); //将它们全部添加到HashMap中
}
}
}
英文:
Okay, there are many issues with your code. I will first give you a commented version of your code, showing everything that's wrong, and then I will provide a version that does work. Here is your code:
public enum Msg { //should be called "Message", since it is in Message.java
//Common
Message1("this"),
Message2("is"),
Message3("not"),
Message4("cool"), //syntax error, the line should end in a semicolon (;)
private String message;
private static HashMap<Msg, String> Msgmap; //Msgmap is never initialized
private static HashMap<Msg, String> getMsgmap(){
return Msgmap;
}
Msg(String msg) { //again, should be named "Message", not "Msg"
this.message = msg;
if(getMsgmap() == null) { //this will always be true, because Msgmap is never initialized
setupMsgMap(); //this will run 4 times (once for every enum value)
}
}
private static void setupMessageMap() {
langmap = new HashMap<Lang, String>(); //syntax error (you didn't declare or infer a type), and the Lang class has not been provided to us, I assume you meant to use the Msg class instead
for(Lang lang:values()){ //NullPointerException occurs here. We're still initializing the first enum constant, but you're asking the compiler to loop through ALL the enum constants. They aren't initialized yet though; they don't actually exist yet.
langmap.put(lang, lang.lang);
}
}
}
Here's my updated code:
public enum Message { //the class is named "Message"
Message1("this"),
Message2("is"),
Message3("not"),
Message4("cool"); //line ends in a semicolon
private String message;
private static HashMap<Message, String> Msgmap = new HashMap<>(); //Msgmap is initialized here
public static HashMap<Message, String> getMsgmap() {
return Msgmap;
}
Message(String msg) {
this.message = msg;
//I don't set up Msgmap in the constructor, because it is still initializing itself here, so we can't possibly add it to a HashMap yet
}
public static void setupMsgMap() { //this will need to be called from outside AFTER initialization
for (Message msg : values()) { //loop through all the enum constants
Msgmap.put(msg, msg.message); //add them all to the HashMap
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论