Two Questions: JSpinner and datatype

R

Rhino

1. If I create a JSpinner with a SpinnerNumberModel and specify the numbers
in the model explicitly as short, why can't I rely on the getValue() from
the JSpinner always returning shorts? In other words, if I define it all
with shorts, what actions on my part will result in getValue() returning an
Integer or something other than Short? For some reason, the results from
getValue() are sometimes Short but sometimes Integer and I don't understand
why. I'm trying to figure out how to make getValue() return ONLY Short (or,
failing that, to return only Integer.) This is the statement that defined
the model:

SpinnerNumberModel seasonNumberModel = new SpinnerNumberModel((short)1,
(short)1, (short)20, (short)1);

2. If a given method can return various sorts of integer numbers, like
Short, Integer, and Long, what is the simplest way to determine the exact
type that is being returned by the method? I'm just trying to cover the
worst-case scenario that factors beyond my control may make it impossible
to predict whether getValue() is going to return Integer or Short from my
JSpinner. If that turns out to be true, I'd like to know the best way to
determine if a given value is a short, int, long or anything else. I think
I used to know how to do that several years ago but I'm darned if I can
remember that technique now.
 
L

Lew

Rhino said:
1. If I create a JSpinner with a SpinnerNumberModel and specify the numbers
in the model explicitly as short, why can't I rely on the getValue() from
the JSpinner always returning shorts? In other words, if I define it all

Because that is not the defined behavior of the model.
with shorts, what actions on my part will result in getValue() returning an
Integer or something other than Short? For some reason, the results from

I don't know, but I bet if you look at the source for
'SpinnerNumberModel' you'll find out. My guess is that it uses the
subtype of 'Number' that most closely matches the returned value.

Given the model class's contract, there's nothing you can do directly
to change what it returns. You get a 'Number' and that's the best you
can predict.
getValue() are sometimes Short but sometimes Integer and I don't understand
why. I'm trying to figure out how to make getValue() return ONLY Short (or,
failing that, to return only Integer.) This is the statement that defined
the model:

SpinnerNumberModel seasonNumberModel = new SpinnerNumberModel((short)1,
(short)1, (short)20, (short)1);

This call feeds integers to the constructor. Did you look at the
Javadocs for the constructor? You are taking 'int' values, casting
them to 'short', then the language is widening them back to 'int'
arguments. There is no constructor overload for that class that takes
'short' parameters.

All you are guaranteed from 'SpinnerNumberModel' is that the returned
value of 'getValue()' is a 'Number'. (The signature says 'Object',
but the Javadocs tell you that it will be a 'Number'.) If you want
different behavior, set your own model.
2. If a given method can return various sorts of integer numbers, like
Short, Integer, and Long, what is the simplest way to determine the exact
type that is being returned by the method? I'm just trying to cover the

Don't.

Just use the return type, which for 'SpinnerNumberModel' is an
'Object' that can be downcast to 'Number'.
worst-case scenario that factors beyond my control may make it impossible
to predict whether getValue() is going to return Integer or Short from my
JSpinner. If that turns out to be true, I'd like to know the best way to
determine if a given value is a short, int, long or anything else. I think
I used to know how to do that several years ago but I'm darned if I can
remember that technique now.

'instanceof'?

What difference does it make? Just use 'Number'. Use its
'longValue()', 'intValue()', etc., methods if you must.

You're making a mountain out of a molehill. Read the Javadocs for the
classes and methods you're using! They will tell you what guarantees
you can count on, and that's all you get to count on. Live with it.
 
R

RedGrittyBrick

1. If I create a JSpinner with a SpinnerNumberModel and specify the numbers
in the model explicitly as short, why can't I rely on the getValue() from
the JSpinner always returning shorts? In other words, if I define it all
with shorts, what actions on my part will result in getValue() returning an
Integer or something other than Short? For some reason, the results from
getValue() are sometimes Short but sometimes Integer and I don't understand
why. I'm trying to figure out how to make getValue() return ONLY Short (or,
failing that, to return only Integer.) This is the statement that defined
the model:

SpinnerNumberModel seasonNumberModel = new SpinnerNumberModel((short)1,
(short)1, (short)20, (short)1);

The relevant 1.6 API signature is SpinnerNumberModel(int value, int
minimum, int maximum, int stepSize) - there isn't a constructor for
shorts, so your shorts are being extended to ints by the compiler before
the constructor gets to use them.

2. If a given method can return various sorts of integer numbers, like
Short, Integer, and Long, what is the simplest way to determine the exact
type that is being returned by the method?

Your description has both 'short' and 'Short' types which is confusing.
Reference types can be tested for using the instanceof operator.

------------------------------8<------------------------------------
public class ShortIntegers {
public static void main(String[] args) {
SpinnerNumberModel snm = new SpinnerNumberModel(
(short)1, (short)1, (short)20, (short)1);
Object o = snm.getValue();
if (o instanceof Short) { System.out.println("Short"); }
if (o instanceof Integer) { System.out.println("Integer"); }
System.out.println(o);
}
}
------------------------------8<------------------------------------
Integer
1

I'm just trying to cover the
worst-case scenario that factors beyond my control may make it impossible
to predict whether getValue() is going to return Integer or Short from my
JSpinner. If that turns out to be true, I'd like to know the best way to
determine if a given value is a short, int, long or anything else.

Which factors are beyond your control?
 
E

Eric Sosman

1. If I create a JSpinner with a SpinnerNumberModel and specify the numbers
in the model explicitly as short, why can't I rely on the getValue() from
the JSpinner always returning shorts? In other words, if I define it all
with shorts, what actions on my part will result in getValue() returning an
Integer or something other than Short? For some reason, the results from
getValue() are sometimes Short but sometimes Integer and I don't understand
why. I'm trying to figure out how to make getValue() return ONLY Short (or,
failing that, to return only Integer.) This is the statement that defined
the model:

SpinnerNumberModel seasonNumberModel = new SpinnerNumberModel((short)1,
(short)1, (short)20, (short)1);

This is just like `new SpinnerNumberModel(1, 1, 20, 1)' -- the
fact that your promoted-to-int arguments happen to be in range for
`short' (or even for `byte') doesn't influence the constructor's
behavior, nor that of the constructed SpinnerNumberModel.

Also, even if the supposed range of the SpinnerNumberModel is
1 through 20 with an integer step, setValue(new Double(98.6)) is
still possible and will work.

It's a little odd that you use getValue() instead of getNumber(),
but that shouldn't matter a lot.
2. If a given method can return various sorts of integer numbers, like
Short, Integer, and Long, what is the simplest way to determine the exact
type that is being returned by the method? I'm just trying to cover the
worst-case scenario that factors beyond my control may make it impossible
to predict whether getValue() is going to return Integer or Short from my
JSpinner. If that turns out to be true, I'd like to know the best way to
determine if a given value is a short, int, long or anything else. I think
I used to know how to do that several years ago but I'm darned if I can
remember that technique now.

You can use getClass() or instanceof on the returned Object().
If you really want to be draconian, you could do

Number num = seasonNumberModel.getNumber();
if (! (num instanceof Short)) {
// Accept no substitutes:
num = Short.valueOf(num.shortValue());
}
 
R

Rhino

The relevant 1.6 API signature is SpinnerNumberModel(int value, int
minimum, int maximum, int stepSize) - there isn't a constructor for
shorts, so your shorts are being extended to ints by the compiler
before the constructor gets to use them.
Sorry, my mistake. I've amended my code to supply ints instead of shorts.
2. If a given method can return various sorts of integer numbers,
like Short, Integer, and Long, what is the simplest way to determine
the exact type that is being returned by the method?

Your description has both 'short' and 'Short' types which is
confusing. Reference types can be tested for using the instanceof
operator.

------------------------------8<------------------------------------
public class ShortIntegers {
public static void main(String[] args) {
SpinnerNumberModel snm = new SpinnerNumberModel(
(short)1, (short)1, (short)20, (short)1);
Object o = snm.getValue();
if (o instanceof Short) { System.out.println("Short"); }
if (o instanceof Integer) { System.out.println("Integer"); }
System.out.println(o);
}
}
------------------------------8<------------------------------------
Integer
1
Sorry for not properly distinguishing between 'short' and 'Short' and
'int' and 'Integer'. I was a little confused myself. instanceof looks
like it will do what I want. Thanks!
Which factors are beyond your control?
According to Lew, getValue() in JSpinner could return various sorts of
Numbers. However, the code I use to handle the Number returned by
getValue() needs to know what it is getting back. At least I think it
does. I'm going to reread Lew's reply again now; something he said there
seemed to take me in the right direction but I just have to think on that
a bit more.
 
R

Rhino

Because that is not the defined behavior of the model.


I don't know, but I bet if you look at the source for
'SpinnerNumberModel' you'll find out. My guess is that it uses the
subtype of 'Number' that most closely matches the returned value.

Given the model class's contract, there's nothing you can do directly
to change what it returns. You get a 'Number' and that's the best you
can predict.


This call feeds integers to the constructor. Did you look at the
Javadocs for the constructor? You are taking 'int' values, casting
them to 'short', then the language is widening them back to 'int'
arguments. There is no constructor overload for that class that takes
'short' parameters.
Casting the input parameters to short was my naive attempt to force
SpinnerNumberModel to use shorts instead of ints. It's now obvious to me
that this would never work.
All you are guaranteed from 'SpinnerNumberModel' is that the returned
value of 'getValue()' is a 'Number'. (The signature says 'Object',
but the Javadocs tell you that it will be a 'Number'.) If you want
different behavior, set your own model.
I may do that but it's probably not necessary in this case.
Don't.

Just use the return type, which for 'SpinnerNumberModel' is an
'Object' that can be downcast to 'Number'.


'instanceof'?

What difference does it make? Just use 'Number'. Use its
'longValue()', 'intValue()', etc., methods if you must.

You're making a mountain out of a molehill. Read the Javadocs for the
classes and methods you're using! They will tell you what guarantees
you can count on, and that's all you get to count on. Live with it.
Fair enough. I did look at the Javadocs but didn't read the main comments
for the class very carefully and just went straight to the method
signatures so that's why I missed that "Numbers" are returned by the
class.

The classes I am writing are basically editing rows of a database table.
Three of the six columns of the table are defined as SMALLINT - I'm using
DB2 - and SMALLINT corresponds to short in Java. Each of those three
short columns contains only a small range of integers in the range of 1
to 3 or 1 to 20. While my main display of the data is in the form of a
JTable, I have written insert/update/delete dialogs for the table. Those
dialogs use JSpinners to present those numbers and limit what values
users can choose for them.

It seemed to make sense that if I gave the spinner number model shorts,
shorts would be returned by getValue(). I see now - thanks to your reply
- that I have misunderstood how this class is supposed to work.

I need to rethink the formats I am using for my data throughout my
classes. The data that comes in as a short is apparently going to be an
integer within the spinner and then need to be changed back to a short
for writing to the database during an insert or update.

Eventually, I may edit the data directly in the JTable; the
insert/udpdate/delete dialogs are just a "quick and dirty" temporary
expedient.

Thanks for helping me set more realistic expectations for the spinner
number model.
 
L

Lew

Rhino said:
It seemed to make sense that if I gave the spinner number model shorts,
shorts would be returned by getValue().

You could use the SpinnerNumberModel 'getNumber().shortValue()' method
chain and get a 'short' value directly.

If the actual values fall outside the 'short' range you could get
bizarre results, but that presumably is handled by how you set up the
spinner's values.
 
R

Rhino

This is just like `new SpinnerNumberModel(1, 1, 20, 1)' -- the
fact that your promoted-to-int arguments happen to be in range for
`short' (or even for `byte') doesn't influence the constructor's
behavior, nor that of the constructed SpinnerNumberModel.
Yes, Lew and RedGrittyBrick have already set me straight on that. Let's
just say I was very naive about use of the SpinnerNumberModel and leave
it at that ;-)
Also, even if the supposed range of the SpinnerNumberModel is
1 through 20 with an integer step, setValue(new Double(98.6)) is
still possible and will work.

That's a bit surprising! It's not desireable in this case so I won't let
anyone do it programmatically but I suppose it might be desireable in
some cases.....
It's a little odd that you use getValue() instead of getNumber(),
but that shouldn't matter a lot.

My goodness! I missed the getNumber() method altogether! Maybe I'll
switch to that....
You can use getClass() or instanceof on the returned Object().
If you really want to be draconian, you could do

Number num = seasonNumberModel.getNumber();
if (! (num instanceof Short)) {
// Accept no substitutes:
num = Short.valueOf(num.shortValue());
}
Is there any way to do the same thing with a primitive? Mind you, I'm
having trouble thinking of a case when you'd need to! In the case of
SpinnerNumberModel, I now know that I'm getting a Number, which may
actually be a Short, Integer, Long, etc. and I can determine which I'm
getting via instanceof or getClass(). If a method is capable of returning
several different primitives - and I don't know of any that is offhand -
how could I tell if it was giving me an int, long, short, double or
whatever?
 
R

RedGrittyBrick

If a method is capable of returning [one of] several different primitives

That isn't possible in Java. The type of return value is part of a
method signature. If it is returning a primitive type, covariance
doesn't apply.
 
R

Roedy Green

1. If I create a JSpinner with a SpinnerNumberModel and specify the numbers
in the model explicitly as short, why can't I rely on the getValue() from
the JSpinner always returning shorts? In other words, if I define it all
with shorts, what actions on my part will result in getValue() returning an
Integer or something other than Short? For some reason, the results from
getValue() are sometimes Short but sometimes Integer and I don't understand
why. I'm trying to figure out how to make getValue() return ONLY Short (or,
failing that, to return only Integer.) This is the statement that defined
the model:

Here is the code for SpinnerNumberModel.setValue

public void setValue(Object value) {
if ((value == null) || !(value instanceof Number)) {
throw new IllegalArgumentException("illegal value");
}
if (!value.equals(this.value)) {
this.value = (Number)value;
fireStateChanged();
}

Note how it accepts any sort of Number, e.g. Short, Integer, Float,
Long ... and uses that for the internal representation. What ever you
put in will be what you get back out.
}
--
Roedy Green Canadian Mind Products
http://mindprod.com

Beauty is our business.
~ Edsger Wybe Dijkstra (born: 1930-05-11 died: 2002-08-06 at age: 72)

Referring to computer science.
 
L

Lew

Here is the code for SpinnerNumberModel.setValue

public void setValue(Object value) {
if ((value == null) || !(value instanceof Number)) {

It's interesting that they use a redundant check in that condition.

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.20.2

I believe I detect an error in the JLS in that section. They refer to the
type of the left-hand operand of the 'instanceof' operator as a
/RelationalExpression/, which it is not. At least not as I read the document.
The text explains what they mean there, so the rules are clear though the
syntax diagram not be.
 
J

John B. Matthews

Lew <[email protected]> said:
It's interesting that they use a redundant check in that condition.

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.20.2

I believe I detect an error in the JLS in that section. They refer
to the type of the left-hand operand of the 'instanceof' operator as
a /RelationalExpression/, which it is not. At least not as I read
the document.

I'm puzzled. It looks like RelationalExpression in

RelationalExpression instanceof ReferenceType

refers back through ShiftExpression, AdditiveExpression,
MultiplicativeExpression, and UnaryExpression to CastExpression
via UnaryExpressionNotPlusMinus. For example,

Object i = 1;
if ((Comparable)i instanceof Number) ...

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.16
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top