神秘消失的对象参考

时间:2014-08-16 05:21:47

标签: java netbeans-platform

在具有多个模块的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的相同实例。

1 个答案:

答案 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
    }
}
相关问题