VoroX
VoroX

Reputation: 247

ClassCastExcpetion after using Double.intValue() in lambda expression

So, I have a strange problem:

I have a JSlider and a JSpinner, the Slider uses int values while the spinner accepts double values. Now I want to 'connect' them by using change listeners:

slider.addChangeListener(e -> spinner.setValue(slider.getValue()));
spinner.addChangeListener(e -> slider.setValue(((Double) spinner.getValue()).intValue()));

But for some weird reason I get a ClassCastException:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double
at rt.Main.lambda$rotateTo$29(Main.java:318)
at javax.swing.JSpinner.fireStateChanged(JSpinner.java:458)
at javax.swing.JSpinner$ModelListener.stateChanged(JSpinner.java:386)
at javax.swing.AbstractSpinnerModel.fireStateChanged(AbstractSpinnerModel.java:119)
at javax.swing.SpinnerNumberModel.setValue(SpinnerNumberModel.java:447)
at javax.swing.JSpinner.setValue(JSpinner.java:354)
at rt.Main.lambda$rotateTo$28(Main.java:317)
at javax.swing.JSlider.fireStateChanged(JSlider.java:432)
at javax.swing.JSlider$ModelListener.stateChanged(JSlider.java:350)
at javax.swing.DefaultBoundedRangeModel.fireStateChanged(DefaultBoundedRangeModel.java:364)
at javax.swing.DefaultBoundedRangeModel.setRangeProperties(DefaultBoundedRangeModel.java:302)
at javax.swing.DefaultBoundedRangeModel.setValue(DefaultBoundedRangeModel.java:168)
at javax.swing.JSlider.setValue(JSlider.java:531)
at rt.Main.lambda$rotateTo$29(Main.java:318)
at javax.swing.JSpinner.fireStateChanged(JSpinner.java:458)
at javax.swing.JSpinner$ModelListener.stateChanged(JSpinner.java:386)
at javax.swing.AbstractSpinnerModel.fireStateChanged(AbstractSpinnerModel.java:119)
at javax.swing.SpinnerNumberModel.setValue(SpinnerNumberModel.java:447)
at javax.swing.JSpinner.setValue(JSpinner.java:354)
at javax.swing.plaf.basic.BasicSpinnerUI$ArrowButtonHandler.actionPerformed(BasicSpinnerUI.java:654)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
at java.awt.Component.processMouseEvent(Component.java:6539)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6304)
at java.awt.Container.processEvent(Container.java:2239)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2297)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4535)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476)
at java.awt.Container.dispatchEventImpl(Container.java:2283)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)

I noticed the following:

If anyone has an Idea why this happens please tell me!

Edit: While trying around some more I found out that slider.setValue(((Number) spinner.getValue()).intValue()) does work, but I would still like to now why? I checked the class returned again and it still is: java.lang.Double! Any help appreciated

Upvotes: 0

Views: 153

Answers (2)

user85421
user85421

Reputation: 29700

The first listener

slider.addChangeListener(e -> spinner.setValue(slider.getValue()));

is setting the value of the spinner to an Integer - slider.getValue() returns an int that is boxed since spinner.setValue() requires an Object.

Probably* you are using a SpinnerNumberModel which accepts any Number for its properties (see javadoc). Since the value of the spinner was changed (programmatically by first listener), its listener is also called, causing the exception since it now have an Integer as value.

Simple test showing that the spinner gets an Integer:

JSlider slider = new JSlider(0, 0, 9, 5);
JSpinner spinner = new JSpinner(new SpinnerNumberModel(5.0, 0.0, 9.0, 1.0));

slider.addChangeListener(e -> spinner.setValue(slider.getValue()));
spinner.addChangeListener(e -> slider.setValue(((Number) spinner.getValue()).intValue()));

JOptionPane.showMessageDialog(null, new Object[] { slider, spinner });
System.out.println(spinner.getValue().getClass());

move the slider and press OK - it will set the spinner value to an Integer.

* missing such minimal complete example in question


Correct solution, IMHO:

slider.addChangeListener(e -> spinner.setValue((double)slider.getValue()));
spinner.addChangeListener(e -> slider.setValue(((Number) spinner.getValue()).intValue()));

I left the cast to Number as metallurg suggested since the model is designed to work with Number.

Upvotes: 1

mentallurg
mentallurg

Reputation: 5207

Spinner return Integer. Slider expects Double. You can convert Integer to Doble as following: spinner.addChangeListener(e -> slider.setValue(((Number)spinner).doubleValue()));

Integer is a subclass of Number. That's why it is allowed to cast it to Number. The Number has method doubleValue().

Upvotes: 1

Related Questions