在具有多个模块的netbeans平台项目中,有一个TopComponent对象。此TopComponent的一个私有属性引用另一个对象。 TopComponent的一个组件是TopComponent中带有事件处理代码的按钮。
在按下按钮之前,属性引用了正确的对象,但是一旦按下该按钮(在事件处理代码的开头),该属性的值为null!
我的对象参考发生了什么?
据我所知,我还没有编写任何会将其设置为null的代码。根据调试器,我的所有代码似乎都运行正常。我不知道如何使调试器在清除变量的位置停止。我在TopComponent对象上使用了一个固定的监视器,以确认在按下按钮之前,对象引用就在那里,并在按钮的事件处理代码的开头有一个断点,看它已经消失了。但是那之间会发生什么?我不知道,但不管它是什么,都搞砸了我的代码。
当声明为null时,属性被初始化,当来自另一个模块的查找触发设置它的方法时,它被赋予一个值。这种方法很好。
我非常确定它与TopComponent的实例相同,因为调试器为对象提供了相同的ID,我使用了固定的手表。
我错过了什么?
以下是相关课程
package org.sil.jflavourviewer;
// <snip> import statements
/**
* Top component which displays something.
*/
@ConvertAsProperties(dtd = "-//org.sil.jflavourviewer//JFlavourViewer//EN",
autostore = false)
@TopComponent.Description(preferredID = "JFlavourViewerTopComponent",
//iconBase="SET/PATH/TO/ICON/HERE",
persistenceType = TopComponent.PERSISTENCE_ALWAYS)
@TopComponent.Registration(mode = "explorer", openAtStartup = true)
@ActionID(category = "Window", id = "org.sil.jflavourviewer.JFlavourViewerTopComponent")
@ActionReference(path = "Menu/Window" /*, position = 333 */)
@TopComponent.OpenActionRegistration(displayName = "#CTL_JFlavourViewerAction",
preferredID = "JFlavourViewerTopComponent")
public final class JFlavourViewerTopComponent extends TopComponent implements LookupListener
{
public JFlavourViewerTopComponent()
{
initComponents();
setName(NbBundle.getMessage(JFlavourViewerTopComponent.class, "CTL_JFlavourViewerTopComponent"));
setDisplayName("Project Viewer");
setToolTipText("Here are the items in the active project");
categoriesListModel = new DefaultListModel<String>();
categoryList.setModel(categoriesListModel);
lookupContent = new InstanceContent();
lookup = new AbstractLookup(lookupContent);
associateLookup(lookup);
}
/** The content of this method is
* always regenerated by the Form Editor.
*/
private void initComponents() {
// <snip> Some swing components initialised
btnAddItem = new javax.swing.JButton();
// <snip> component settings and layout
org.openide.awt.Mnemonics.setLocalizedText(btnAddItem, org.openide.util.NbBundle.getMessage(JFlavourViewerTopComponent.class, "JFlavourViewerTopComponent.btnAddItem.text")); // NOI18N
btnAddItem.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAddItemActionPerformed(evt);
}
});
// <snip> more component settings and layout
}
// here is the event handling code for the "add" button
private void btnAddItemActionPerformed(java.awt.event.ActionEvent evt)
{
// At this point this.activeProject is already null
JFlavourItemBean newItem = new JFlavourItemBean();
this.activeProject.addItem(newItem);
// <snip> the rest of the method is not executed because the NullPointerException is thrown
}
// <snip> swing variable declerations
private javax.swing.JButton btnAddItem;
private Lookup.Result<JFlavourProjectBean> result = null;
private DefaultListModel<String> categoriesListModel;
private JFlavourProjectBean activeProject = null;
private InstanceContent lookupContent;
private AbstractLookup lookup;
@Override
public void componentOpened()
{
result = Utilities.actionsGlobalContext().lookupResult(JFlavourProjectBean.class);
result.addLookupListener (this);
}
@Override
public void componentClosed()
{
result.removeLookupListener(this);
}
void writeProperties(java.util.Properties p)
{
//<snip>
}
void readProperties(java.util.Properties p)
{
//<snip>
}
// this is the code that sets this.activeProject via listening to the global Lookup
// after this method runs this.activeProject is successfully set
@Override
public void resultChanged(LookupEvent le)
{
Collection<? extends JFlavourProjectBean> allProjects = result.allInstances();
if (!allProjects.isEmpty()) {
JFlavourProjectBean project = allProjects.iterator().next();
this.activeProject = project;
SortedSet<String> categories = project.getCategories();
categoriesListModel.clear();
for (Iterator<String> it = categories.iterator(); it.hasNext();) {
categoriesListModel.addElement(it.next());
}
tmpLabel.setText(project.getName());
} else {
activeProject = null;
// TODO what to display when no project is loaded
}
}
}
如果您需要,可以在此处看到整个文件而不会剪切JFlavourViewerTopComponent.java 将JFlavourProjectBean对象添加到其查找的内容是JFlavourProjectManagerTopComponent.java
如果您愿意,可以浏览到目前为止整个JFlavour项目的代码。如果我有10个声望,我会给你链接,但你可以从上面的2个链接中解决它。
我打算发布调试器的图像,但由于我没有足够的代表,我只需要描述它。
我在resultChanged方法结束时停止执行,并使这个&#39;这个&#39;一块固定的手表。关于this.activeProject的监视显示它正确填充。我继续执行,直到它等待输入。固定手表仍然显示正确设置的activeProject属性。然后我按下&#39;添加...&#34;按钮并在事件处理程序的第一行停止执行。现在关注this.activeProject显示&#39; null&#39;,固定监视也显示activeProject为null。
我已经确定使用Object的hashCode()方法,它正在处理整个TopComponent的相同实例。
答案 0 :(得分:0)
我研究了如何在变量被触发的变量中添加断点(Ctrl+Shift+F8
- &gt; Breakpoint Type: Field
)
这告诉我,当点击按钮时,执行会重新输入resultChanged方法(为什么?我不知道),这次查找中没有JFlavourProjectBean,所以它进入了else子句并将activeProject设置为null。
现在我已将此方法更改为:
@Override
public void resultChanged(LookupEvent le)
{
Collection<? extends JFlavourProjectBean> allProjects = result.allInstances();
if (!allProjects.isEmpty()) {
JFlavourProjectBean project = allProjects.iterator().next();
this.activeProject = project;
SortedSet<String> categories = project.getCategories();
categoriesListModel.clear();
for (Iterator<String> it = categories.iterator(); it.hasNext();) {
categoriesListModel.addElement(it.next());
}
tmpLabel.setText(project.getName());
} else {
// do nothing if no projects are in the lookup
}
}