为什么抛出ClassCastException?

时间:2016-08-15 15:39:25

标签: java swing classcastexception

我一直在研究GUI,但发现了一个问题。我启动程序的时间大约有10%,我得到了一个ClassCastException,但代码没有挂起,也没有奇怪的执行。它只是像平常一样运行。更奇怪的是堆栈跟踪从不引用我编写的任何代码。我试图通过在try-catch中包装所有内容来确认这一点,果然,错误仍然被抛出并且从未被捕获。因为它从来没有真正影响代码,我想它不会造成任何伤害,但我仍然宁愿不发布有我不理解的错误的代码。

这是简化的代码,我可以让它仍然重复错误:

import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class ErrorTracker extends JFrame{

    private JButton addRow;
    private JScrollPane pane;
    private JPanel scrollPanel, panel;
    private JFrame frame; 

    public static void main (String[] args) {
        /**
         * The error only occurs sometimes, so I'm running it 20 times to
         * make the odds of repeating the error pretty good.
         */
        for(int i = 0; i < 20; i++)
            new ErrorTracker();
    }

    public ErrorTracker() {
        /**
         * Proof that the error somehow occurs outside of all the code... 
         * The line "An error took place" is never outputted. 
         **/
        try {
            initialize();
        } catch (Exception e) {
            System.out.println("An error took place");
        }
    }

    public void initialize () {
        frame = new JFrame("Apparently this is defective");

        JPanel bigPanel = new JPanel(new GridBagLayout());

        frame.add(bigPanel);

        addRow = new JButton("...");

        scrollPanel = new JPanel();
        scrollPanel.add(addRow);

        pane = new JScrollPane(scrollPanel);
        bigPanel.add(pane);

        frame.setVisible(true);

        panel = new JPanel();
        panel.add(addRow);
    }
}

我知道99%的确定添加addRow两次至少是其中一些原因,因为取出add(addRow)行中的任何一行都可以解决问题。在任何人建议改变之前,不要担心。我会。但是,这个问题主要是为了理解为什么会出现这种错误。摆脱frame.setVisible(true);也消除了这个问题,所以我想象当绘制GUI时,它就是在它自己的Thread中完成的,这对于将两个JPanel s添加相同的元素真的很生气我会解释为什么我的代码不在堆栈跟踪中,我认为...),但我不太清楚这个过程是否足以确定。

这是堆栈跟踪:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException
    at javax.swing.LayoutComparator.compare(Unknown Source)
    at javax.swing.LayoutComparator.compare(Unknown Source)
    at java.util.TimSort.countRunAndMakeAscending(Unknown Source)
    at java.util.TimSort.sort(Unknown Source)
    at java.util.Arrays.sort(Unknown Source)
    at java.util.ArrayList.sort(Unknown Source)
    at java.util.Collections.sort(Unknown Source)
    at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(Unknown Source)
    at javax.swing.SortingFocusTraversalPolicy.getFocusTraversalCycle(Unknown Source)
    at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(Unknown Source)
    at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(Unknown Source)
    at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(Unknown Source)
    at java.awt.FocusTraversalPolicy.getInitialComponent(Unknown Source)
    at java.awt.Window.getMostRecentFocusOwner(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.SequencedEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

有谁知道为什么会抛出这个错误?我是否正确在另一个线程中,如果没有,为什么堆栈跟踪不会引用我的代码?另外,为什么它只会在某些时候抛出错误?

1 个答案:

答案 0 :(得分:0)

首先你猜对了,问题是因为你添加了两次addRow。第二次添加的面板不会在框架中显示。 Swing中的一个组件必须只有一个父组件,它不能同时给两个父组件。如果要更改组件的父级,则必须先将其从父级中删除,然后将其添加到其他组件,并使两个父项无效以查看结果。

发生类强制转换异常是因为父内部混淆了