为什么会抛出ClassCastException?
我一直在使用GUI,但发现了一个问题。大约10%的时间启动该程序,我得到一个ClassCastException,但代码不会挂起并且不会执行奇怪。它只是正常运行。什么是weirder是堆栈跟踪从不参考我写的任何代码。我试图通过将所有内容都包含在try-catch中来证实这一点,并且确信,错误仍然被抛出并且从未被捕获。由于它从来没有真正影响代码,我想这不会造成任何伤害,但我仍然宁愿不发布有我不了解的错误的代码。为什么会抛出ClassCastException?
这里是简化的,因为我可以得到它仍重复错误代码:
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)
有谁知道为什么被抛出这个错误?我在另一个线程中是否正确,如果没有,为什么堆栈跟踪不会引用我的代码?另外,它为什么只在某些时候抛出错误?
首先你猜对了,问题是因为你添加了两次addRow。偶然地,第二次添加的面板不会显示在框架中。 Swing中的组件必须只有一个父对象,它不能在同一时间给予两个父对象。如果您想更改组件的父项,则必须先将其从其父项中删除,然后将其添加到其他项中,然后使双亲无效以查看结果。
类抛出的异常发生是因为父内部是混淆的
您的类扩展了'JFrame'。不需要私人成员“框架”。 – pzaenger
这是错误吗? http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8013775 – khelwood
@ khelwood我认为这是错误!这是否意味着发生这种情况,因为在我的主线程中使用Swing线程正在使用的组件的'addRow'可见的混乱之后,向'JPanel'添加'addRow'?我会继续点击“解决了我的问题”这个副本,但我很乐意确保我完全掌握了第一个 –