I'm puzzled by what I had to do to get this code to work. It seems as if the compiler optimized away a type conversion that I needed, or there's something else I don't understand here.
I have various objects that are stored in the database that implement the interface Foo
. I have an object, bar
, which holds data I'm using to retrieve my Foo
objects. bar
has these methods:
Class getFooClass()
Long getFooId()
I pass the class and ID to a method with this signature, which delegates to hibernate which retrieves the subject based on its class and ID:
public <T> T get(Class<T> clazz, Serializable id);
There are different implementers of Foo
, and some of these hibernate objects have a Long
id, and others have an Integer
id. Although this method accepts either, farther down it had better have the right one. So when I tried to call get()
on an object with an Integer
id, as follows, I understandably got an error complaining that I had provided a Long
where an Integer
was required:
get(bar.getFooClass(), bar.getFooId());
There's no hibernate problem here, I just need to provide an Integer
where an Integer
id is required and a Long
where a Long
id is required. So I added a method to bar
, hasLongId()
, and tried this: (at this point you may be thinking this isn't a good design, but that's not my question right now)
get(bar.getFooClass(),
bar.hasLongId() ? bar.getFooId() : bar.getFooId().intValue());
And it still complained that I had provided a Long
. That seemed strange. Then I tried this:
get(bar.getFooClass(),
bar.hasLongId() ? bar.getFooId()
: new Integer(bar.getFooId().intValue()));
Same error! How can this be? So I stepped through in the debugger, and yes, it stepped through intValue()
and also through the Integer
constructor, but then in the get method, the passed parameter was in fact a Long
—the same Long
object that was returned from getFooId()
.
I don't understand what's happening, so I just try various things:
Integer intId = bar.getFooId().intValue();
get(bar.getFooClass(), bar.hasLongId() ? bar.getFooId() : intId);
// same error
and
Serializable id = bar.hasLongId() ? bar.getFooId()
: new Integer(bar.getFooId().intValue());
get(bar.getFooClass(), id);
// same error
And finally:
Serializable id;
if (bar.hasLongId()) {
id = bar.getFooId();
} else {
id = bar.getFooId().intValue();
}
get(bar.getFooClass(), id);
This one works. So apparently it has something to do with the ternary operator. But why? Can someone explain what happened here?
getFooId()
return aNumber
instead of the extra method and type conversion? – Sestos