涉及JavaFX和泛型的误导性堆栈跟踪

涉及JavaFX和泛型的误导性堆栈跟踪,java,generics,javafx,javafx-8,Java,Generics,Javafx,Javafx 8,在打开带有提示符类型的组合框和使用Java1.8u40连接的StringConverter时,我遇到了以下错误。这可以追溯到执行FXML的团队留下的示例字符串,与控制器中的通用类型组合框相冲突。我们通过确保在initialize()中用正确类型的项替换虚拟列表来修复此问题 然而,虽然我理解这个问题以及如何解决它,但我无法理解堆栈跟踪。。。错误发生在atController$1.toString(Controller.java:1) 为什么会在第1行报告,控制器本身不是通用的,只有它的字段 有没

在打开带有提示符类型的组合框和使用Java1.8u40连接的StringConverter时,我遇到了以下错误。这可以追溯到执行FXML的团队留下的示例字符串,与控制器中的通用类型组合框相冲突。我们通过确保在initialize()中用正确类型的项替换虚拟列表来修复此问题

然而,虽然我理解这个问题以及如何解决它,但我无法理解堆栈跟踪。。。错误发生在at
Controller$1.toString(Controller.java:1)

  • 为什么会在第1行报告,控制器本身不是通用的,只有它的字段
  • 有没有编译器生成的魔法
  • FXML构建过程如何构建正确类型的组合框,因为泛型只存在于编译类型
原始误差

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at Controller$1.toString(Controller.java:1)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.updateDisplayText(ComboBoxListViewSkin.java:388)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.access$100(ComboBoxListViewSkin.java:57)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin$2$1.updateItem(ComboBoxListViewSkin.java:425)
    at javafx.scene.control.ListCell.updateItem(ListCell.java:471)
    at javafx.scene.control.ListCell.indexChanged(ListCell.java:330)
    at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
    at com.sun.javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1957)
    at com.sun.javafx.scene.control.skin.VirtualFlow.getCell(VirtualFlow.java:1797)
    at com.sun.javafx.scene.control.skin.VirtualFlow.getCellBreadth(VirtualFlow.java:1888)
    at com.sun.javafx.scene.control.skin.VirtualFlow.getMaxCellWidth(VirtualFlow.java:2508)
    at com.sun.javafx.scene.control.skin.VirtualContainerBase.getMaxCellWidth(VirtualContainerBase.java:94)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin$3.computePrefWidth(ComboBoxListViewSkin.java:457)
    at javafx.scene.Parent.prefWidth(Parent.java:904)
    at javafx.scene.layout.Region.prefWidth(Region.java:1419)
    at com.sun.javafx.scene.control.skin.ComboBoxPopupControl.sizePopup(ComboBoxPopupControl.java:199)
    at com.sun.javafx.scene.control.skin.ComboBoxPopupControl.positionAndShowPopup(ComboBoxPopupControl.java:173)
    at com.sun.javafx.scene.control.skin.ComboBoxPopupControl.show(ComboBoxPopupControl.java:154)
    at com.sun.javafx.scene.control.skin.ComboBoxBaseSkin.handleControlPropertyChanged(ComboBoxBaseSkin.java:127)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.handleControlPropertyChanged(ComboBoxListViewSkin.java:159)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$61(BehaviorSkinBase.java:197)
    at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(MultiplePropertyChangeListenerHandler.java:55)
    at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
    at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.beans.property.ReadOnlyBooleanWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:178)
    at javafx.beans.property.ReadOnlyBooleanWrapper$ReadOnlyPropertyImpl.access$100(ReadOnlyBooleanWrapper.java:148)
    at javafx.beans.property.ReadOnlyBooleanWrapper.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:144)
    at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
    at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:144)
    at javafx.scene.control.ComboBoxBase.setShowing(ComboBoxBase.java:185)
    at javafx.scene.control.ComboBoxBase.show(ComboBoxBase.java:391)
    at com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior.show(ComboBoxBaseBehavior.java:242)
    at com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior.mouseReleased(ComboBoxBaseBehavior.java:197)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:350)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$351(GlassViewEventHandler.java:385)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:384)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
小例子 我使用Integer表示其他一些特定于业务的类型,太复杂了,无法粘贴到这里,值列表实际上是动态的,并且是从数据库加载的

FXML

虽然这个答案并不能解决OP最初的问题,但我还是把它留给了一个有着相同stacktrace的人,他不知道哪里出了问题


您正在控制器中声明一个
组合框
,当您在FXML中将字符串值传递给它时,会出现异常

java.lang.ClassCastException:java.lang.String不能转换为java.lang.Integer

如果您想要一个包含整数值的组合框,那么您需要将整数值传递给您的组合框

 <FXCollections fx:factory="observableArrayList">
     <Integer fx:value="1" />
     <Integer fx:value="2" />
     <Integer fx:value="3" />
 </FXCollections>

虽然这个答案并不是OP最初问题的解决方案,但我还是把它留给了一个有着相同stacktrace的人,他不知道出了什么问题


您正在控制器中声明一个
组合框
,当您在FXML中将字符串值传递给它时,会出现异常

java.lang.ClassCastException:java.lang.String不能转换为java.lang.Integer

如果您想要一个包含整数值的组合框,那么您需要将整数值传递给您的组合框

 <FXCollections fx:factory="observableArrayList">
     <Integer fx:value="1" />
     <Integer fx:value="2" />
     <Integer fx:value="3" />
 </FXCollections>

这似乎是一个编译器问题,特别是Eclipse中使用的内部编译器Luna SR1

如果使用JDK编译器编译相同的示例,则在第14行正确报告错误

javac Controller.java
javac ComboBoxTypeMismatch.java
java -cp . ComboBoxTypeMismatch

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at Controller$1.toString(Controller.java:14)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.updateDisplayText(ComboBoxListViewSkin.java:388)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.access$100(ComboBoxListViewSkin.java:57)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin$2$1.updateItem(ComboBoxListViewSkin.java:425)
    at javafx.scene.control.ListCell.updateItem(ListCell.java:471)

这似乎是一个编译器问题,特别是Eclipse中使用的内部编译器Luna SR1

如果使用JDK编译器编译相同的示例,则在第14行正确报告错误

javac Controller.java
javac ComboBoxTypeMismatch.java
java -cp . ComboBoxTypeMismatch

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at Controller$1.toString(Controller.java:14)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.updateDisplayText(ComboBoxListViewSkin.java:388)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.access$100(ComboBoxListViewSkin.java:57)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin$2$1.updateItem(ComboBoxListViewSkin.java:425)
    at javafx.scene.control.ListCell.updateItem(ListCell.java:471)
有没有编译器生成的魔法

事实上,这就是原因:

通常,每个文件应该有一个类。这意味着每个.java文件在编译后都会生成一个.class文件

现在,您的文件Controller.java至少包含两个类:
Controller
和一个匿名类:
newstringconverter(){…}。因此,在编译Controller.java时,输出必须存储在两个文件中

java编译器命名第二个文件的约定是:enclosuringclass$n.class,其中n是封闭类中的第n个匿名类

如果进入bin目录,您将看到两个文件:Controller.class和Controller$1.class(可能还有更多)

为什么在第1行报告这一点,控制器本身不是通用的,只是 它的领域

正如您所说,这似乎是一个特定的编译器版本问题

FXML构建过程如何构建正确格式的组合框 类型作为泛型仅存在于编译类型

什么是泛型药?在代码中声明了
组合框

有没有编译器生成的魔法

事实上,这就是原因:

通常,每个文件应该有一个类。这意味着每个.java文件在编译后都会生成一个.class文件

现在,您的文件Controller.java至少包含两个类:
Controller
和一个匿名类:
newstringconverter(){…}。因此,在编译Controller.java时,输出必须存储在两个文件中

java编译器命名第二个文件的约定是:enclosuringclass$n.class,其中n是封闭类中的第n个匿名类

如果进入bin目录,您将看到两个文件:Controller.class和Controller$1.class(可能还有更多)

为什么在第1行报告这一点,控制器本身不是通用的,只是 它的领域

正如您所说,这似乎是一个特定的编译器版本问题

FXML构建过程如何构建正确格式的组合框 类型作为泛型仅存在于编译类型


什么是泛型药?在您的代码中,您声明的
组合框

您的StringConverter对我来说没有任何意义。您想在这里实现什么?这只是一个包含StringConverter的自包含示例,其细节并不重要。真正的应用程序是数万行自定义类型…为什么要将StringConverter附加到一个值已经是字符串的组合框上?字符串值是一个团队仅将FXML设计作为原型留下的示例。。。实际的开发人员希望使用正确的类型,这些类型是数据库中的动态类型,而不是静态类型。问题的重点是理解堆栈跟踪“第1行”和泛型…我不太确定您的项目结构,但当我尝试复制相同的问题时,我得到了一个异常
Controller$1.toString(Controller.java:20)
,而不是
第1行
您的StringConverter对我来说没有任何意义。您想在这里实现什么?这只是一个包含StringConverter的自包含示例,其细节并不重要。真正的应用是
javac Controller.java
javac ComboBoxTypeMismatch.java
java -cp . ComboBoxTypeMismatch

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at Controller$1.toString(Controller.java:14)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.updateDisplayText(ComboBoxListViewSkin.java:388)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.access$100(ComboBoxListViewSkin.java:57)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin$2$1.updateItem(ComboBoxListViewSkin.java:425)
    at javafx.scene.control.ListCell.updateItem(ListCell.java:471)