Java 神秘消失的对象引用

Java 神秘消失的对象引用,java,netbeans-platform,Java,Netbeans Platform,在具有多个模块的netbeans平台项目中,有一个TopComponent对象。此TopComponent的一个私有属性引用了另一个对象。此TopComponent的一个组件是TopComponent中带有事件处理代码的按钮 在按下按钮之前,该属性引用了正确的对象,但一旦按下按钮(在事件处理代码的开头),该属性的值就为null 我的对象引用发生了什么 据我所知,我还没有编写任何代码将其设置为null。根据调试器,我的所有代码似乎都工作正常。我不知道如何使调试器在变量被清除时停止。我在TopCom

在具有多个模块的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
        }
    }

}
package org.sil.jflavourviewer;
//导入语句
/**
*显示某些内容的顶部组件。
*/
@ConvertAsProperty(dtd=“-//org.sil.jflavourviewer//jflavourviewer//EN”,
自动存储(错误)
@TopComponent.Description(preferredID=“JFlavourViewerTopComponent”,
//iconBase=“SET/PATH/TO/ICON/HERE”,
persistenceType=TopComponent.PERSISTENCE\u始终)
@注册(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”)
公共最终类JFlavourViewerTopComponent扩展了TopComponent实现了LookupListener
{
公共JFlavourViewerTopComponent()
{
初始化组件();
setName(NbBundle.getMessage(JFlavourViewerTopComponent.class,“CTL_JFlavourViewerTopComponent”);
setDisplayName(“项目查看器”);
setToolTipText(“以下是活动项目中的项目”);
categoriesListModel=新的DefaultListModel();
categoryList.setModel(categoriesListModel);
lookupContent=newinstancecontent();
lookup=新的AbstractLookup(lookupContent);
associateLookup(查找);
}
/**这种方法的内容是
*始终由表单编辑器重新生成。
*/                       
私有组件(){
//一些swing组件已初始化
btnAddItem=newjavax.swing.JButton();
//组件设置和布局
org.openide.awt.Mnemonics.setLocalizedText(btnAddItem,org.openide.util.NbBundle.getMessage(JFlavourViewerTopComponent.class,“JFlavourViewerTopComponent.btnAddItem.text”);//NOI18N
btnAddItem.addActionListener(新java.awt.event.ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent evt){
已执行的btnadditemaction(evt);
}
});
//更多组件设置和布局
}                        
//下面是“添加”按钮的事件处理代码
私有void btnAddItemActionPerformed(java.awt.event.ActionEvent evt)
{                                           
//此时this.activeProject已为空
JFlavourItemBean newItem=新的JFlavourItemBean();
this.activeProject.addItem(newItem);
//由于引发NullPointerException,因此不会执行该方法的其余部分
}                                          
//摆动可变偏差
私有javax.swing.JButton btnAddItem;
私有查找。结果=null;
私有DefaultListModel类别ListModel;
私有JFlavourProjectBean activeProject=null;
私有InstanceContent查找内容;
私有抽象查找;
@凌驾
公共无效组件已打开()
{
结果=Utilities.actionsGlobalContext().lookupResult(JFlavourProjectBean.class);
result.addLookupListener(this);
}
@凌驾
公共无效组件已关闭()
{
结果:移除超链接器(本);
}
void writeProperties(java.util.Properties p)
{
//
}
void readProperties(java.util.Properties p)
{
//
}
//这是通过侦听全局查找来设置this.activeProject的代码
//此方法运行后,将成功设置此.activeProject
@凌驾
公共无效结果已更改(LookupEvent le)
{

集合我研究了如何向变量添加断点,该变量在修改时触发(
Ctrl+Shift+F8
->
断点类型: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
    }
}
@覆盖
公共无效结果已更改(LookupEvent le)
{

CollectionI建议发布您的代码,以便我们检查逻辑。一行代码相当于1000字。您可能正在隐藏引用(将变量声明为类级实例,但将实例分配给局部变量)-代码将告诉…好的,我发布了一些代码并链接到了更多。根据SO规则,我需要发布复制错误所需的最短代码。如果我找不到w怎么办