如何方便Netbeans Designer使用hashmap加载使用枚举反向查找的JPanel? [英] How to facilitate Netbeans Designer to load JPanel-s that use an enum reverse-lookup using hashmap?
问题描述
这是一个多萝西·迪克斯,当我发现事情的根源时撰写这个问题不过,我决定发布它,因为它让我们办公室里的每个人都陷入僵局,我可以在google或stackoverflow搜索中找不到任何帮助。这是一个很好的例子,一旦你提出正确的问题,你可能会看到光。
虽然标题可能听起来很复杂,一个似乎没有答案的真正简单的问题。这个中心是一个枚举
:
状态
public enum Status
{
INVALID(INVALID ,
ISSUED(发行),
取消(已取消);
private final String displayName;
private final static Map< String,Status> displayMap = new HashMap(4);
私人状态(字符串显示){
this.displayName = display;
mapDisplayName(this.displayName,this);
}
public String getDisplayName(){
return displayName;
}
public static状态parseString(String statusStr){
return displayMap.get(statusStr);
}
private static void mapDisplayName(final String displayName,final Status state){
displayMap.put(displayName,state);
}
}
当然的想法是使用 displayMap
作为反向查找。与$ getDisplayName()
方法无关。
此枚举的 getDisplayName( )
调用在子面板中用于初始化与组合框一起使用的静态数组,例如:
public class JPanelStatus extends javax.swing.JPanel {
private final String [] STATUS_LABELS = {
Status.ISSUED .getDisplayName(),
Status.CANCELLED .getDisplayName()
};
public JPanelStatus(){
initComponents();
:
jComboBoxStatus.setModel(new DefaultComboBoxModel<>(STATUS_LABELS));
:
}
:
}
其中在主要的JPanel中引用。当我在Netbeans Designer中查看这个 JPanelStatus
子面板时,工作正常。但是,当我加载主窗体时,它会失败,并且异常(例如,预览设计
]功能
显示初始化失败:
java.lang.NoClassDefFoundError:无法初始化类au.com.project.State
在au.com.project.client.JPanelStatus。< init>(JPanelStatus.java:35)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance (NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
在java.lang.reflect.Constructor.newInstance(Constructor.java:423)
... ...
Netbeans IDE日志添加了以下额外信息: p
信息:无法初始化类au.com.project.State
/ pre>
通过一个消除过程 - Co发布不相关的代码 - 一旦我在State枚举中注释了HashMap
put()
调用,我发现表单将加载。
这很有趣。我说。它看起来像一个副作用,从
put()
。而离开它是 - 一个小的 Spock ,它很快给了我一样的错误从没有JPanel和没有Netbeans的命令行。
错误是由我造成的,尝试从Enum构造函数中使用HashMap。它不会写成。
所以我改变了标题来命中真正的问题 - 实际上,如何使用HashMap对枚举进行反向查找?
解决方案问题来自于HashMap如何在
Status
枚举中声明如何初始化枚举。
Java枚举中的第一件事必须是值列表,如下所示:INVALID,ISSUED和CANCELED。每个人都需要知道的是,在对象创建(Class或Enum)期间,首先运行的是一个 Java 。 Init是愚蠢的,通过声明性代码线性运行,先到先得。
枚举的前3个x语句调用构造函数 - 这意味着语句:
private final static Map< String,Status> displayMap = new HashMap(4);
尚未执行,
displayMap
是 null 。另外,一个static {}
块在相同的1-2-3 -...序列中执行,也不起作用。
遗憾的是,Netbeans / Designer堆栈跟踪或IDE日志都没有报告NullPointerException - 单元测试。一旦你有一个NPE,它集中精神。
解决方案:displayMap displayMap 在初始构造函数调用时未初始化不能
static final
,因为您不能在构造函数中初始化静态成员。必须在第一次通话时使用以下示例中的一些变体来初始化:
状态
/ strong>public enum Status
{
INVALID(INVALID),
发行(已发行),
取消(已取消);
private static Map< String,Status> displayMap;
私人状态(字符串显示){
this.displayName = display;
mapDisplayName(this.displayName,this);
}
:
private static void mapDisplayName(final String displayName,final Status state){
if(null == displayMap){
displayMap =新的HashMap(7);
}
displayMap.put(displayName,state);
}
}
然后它运行顺利。
警告:
不要分配
null
在displayMap声明 - 这是有效的:
- 如果(null == displayMap)在第一次调用Enum构造函数时,{...} 块成功分配了HashMap。
- 在处理所有枚举值声明之后。
- Init将为声明的变量调用任何初始化。
- 如果
displayMap = null;
被声明它将替换使用新的空HashMap填充HashMap,带有3个x值。
可能相关问题:
- 使用每个键/常数有多个值的Java枚举反向查询 ... I感觉到HashMap会更容易地提供多个字符串的反向查找。
This has become a Dorothy Dix as I found the root of the matter while I was composing this question. Nevertheless, I decided to post it because it had everyone in our office stumped and I could find nothing helpful in the google or stackoverflow searches. This is a good example of once you ask the right question, you may see the light.
While the title might sounds complicated, it is a really simple problem that seemed to have no answer. At the centre of this is an enum
:
Status
public enum Status
{
INVALID ( "INVALID" ),
ISSUED ( "Issued" ),
CANCELLED ( "Cancelled");
private final String displayName;
private final static Map<String,Status> displayMap = new HashMap( 4 );
private Status( String display ){
this.displayName = display;
mapDisplayName( this.displayName, this );
}
public String getDisplayName(){
return displayName;
}
public static Status parseString( String statusStr ) {
return displayMap.get( statusStr );
}
private static void mapDisplayName( final String displayName, final Status state ){
displayMap.put( displayName, state );
}
}
The idea of course is to use the displayMap
as a reverse-lookup. Nothing to do with the getDisplayName()
method at all.
This enum's getDisplayName()
call is used in a sub-panel to initialise a static array used with a combobox, like:
public class JPanelStatus extends javax.swing.JPanel {
private final String[] STATUS_LABELS = {
Status.ISSUED .getDisplayName(),
Status.CANCELLED .getDisplayName()
};
public JPanelStatus(){
initComponents();
:
jComboBoxStatus.setModel( new DefaultComboBoxModel<>( STATUS_LABELS ) );
:
}
:
}
Which is referenced in the main JPanel. When I view this JPanelStatus
sub-panel in the Netbeans Designer, it works fine. As does the [Preview Design
] function.
However when I load the main form, it fails and the exception show an initialisation failure:
java.lang.NoClassDefFoundError: Could not initialize class au.com.project.State
at au.com.project.client.JPanelStatus.<init>(JPanelStatus.java:35)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
... ... ...
The Netbeans IDE log added the following extra information :-p
INFO: Could not initialize class au.com.project.State
Through a process of elimination -- Commenting-out unrelated code -- I discovered the form will load once I comment-out the HashMap put()
call in the State enum.
"That is interesting.", I say. It looked like a side-effect from the put()
. And in away it is -- A small Spock which quickly gave me the same error from the command line without the JPanel and without Netbeans.
The error is caused by me, trying to use a HashMap from within the Enum constructor. It won't work as written.
So I changed the title to hit at the true problem -- Which is actually, how to use a HashMap to do a reverse-lookup for an enum?
The problem comes from how the HashMap is declared within the Status
enum due to HOW enums are initialised.
The first thing in a Java Enum must be the list of values, here: "INVALID", "ISSUED", and "CANCELLED". The next thing everyone needs to know is that there is a secret Java stage that runs first during Object creation (Class or Enum). Init is dumb, is runs linearly through the declarative code first-come, first-served.
The first 3 x statements of an enum call the constructor -- That means the statement:
private final static Map<String,Status> displayMap = new HashMap( 4 );
Has NOT yet been executed, and displayMap
is null. Also, a static { }
block is executed in that same 1-2-3-... sequence and does not work either.
Unfortunately none of the Netbeans/Designer stack-trace or IDE log reported a NullPointerException -- The unit test does. Once you have a NPE, it focuses the mind. displayMap
is uninitialised when the first constructor call is made.
Solution: The displayMap cannot be static final
, because you may not initialise static members in a constructor. It must be initialised on the first call, using some variation of the example shown:
Status
public enum Status
{
INVALID ( "INVALID" ),
ISSUED ( "Issued" ),
CANCELLED ( "Cancelled");
private static Map<String,Status> displayMap;
private Status( String display ){
this.displayName = display;
mapDisplayName( this.displayName, this );
}
:
private static void mapDisplayName( final String displayName, final Status state ){
if( null == displayMap ){
displayMap = new HashMap( 7 );
}
displayMap.put( displayName, state );
}
}
And then it all runs quite smoothly.
Caveat:
Do NOT assign null
in the displayMap declaration -- That was counter productive:
- The
if( null == displayMap ){...}
block successfully assigns the HashMap during the first call to the Enum constructor. - After all the enum values declarations are processed.
- Init will call any initialises for declared variables.
- If
displayMap = null;
is declared it replaces the populated HashMap, with 3 x values, with a new empty HashMap. grrr
Possibly related question:
- Reverse lookup for Java Enums with more than one value per key/constant? ... I felt that a HashMap would deliver the reverse-lookup of multiple strings a lot more easily.
这篇关于如何方便Netbeans Designer使用hashmap加载使用枚举反向查找的JPanel?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!