This is an order of operations issue. It would also help to know
whether the error you got was a compile-time error or a runtime error.
(I'm not sure if you said or not.)
If it was a compile-time error, read this, but you might want to read
it anyway:
Sometimes you can use
(Type)object
without having to put an extra set of parentheses around the whole
thing, like if you are saying
Type1 object2 = (Type1)object1;
but since the casting operation happens in the order it does, to do
most other operations on the casted object, you will need another set
of parentheses, like in the following example:
if(object1 instanceof Type1)
if(((Type1)object1).booleanFunction())
doSomething();
Another common case is getting an item out of a list:
if(list.get(index) instanceof Type1)
((Type1)list.get(index)).doSomething();
OTHERWISE, if it was a runtime error, read this (and you might want to
read it anyway):
The && operator evaluates the expressions on both sides. Even if the
first side is false (and therefore it would logically return false
regardless of the second side's value) the second side will still be
evaluated. Thus, in a case such as
if(object1 instanceof Type1 &&
((Type1)object1).someBooleanFunction())
doSomething();
the Java Virtual Machine will come across an error if the object is not
of the required type, because it will try to evaluate the second
expression.
The way to solve this is to do either this
if(object1 instanceof Type1)
if(((Type1)object1).booleanFunction())
doSomething();
or, if you are feeling bold and know or are ready to learn the ternary
operator:
if(object1 instanceof Type1 ? ((Type1)object1).booleanFunction() :
false)
doSomething();
I hope this helps.
jupiter - 31 Dec 2006 03:58 GMT
> This is an order of operations issue. It would also help to know
> whether the error you got was a compile-time error or a runtime
> error.
> (I'm not sure if you said or not.)
Hi, Andrew, and yes, compile time.
> If it was a compile-time error, read this, but you might want to
> read
[quoted text clipped - 19 lines]
> if(((Type1)object1).booleanFunction())
> doSomething();
I guess the "order it does" is last on the to-do list, eh?
> Another common case is getting an item out of a list:
>
> if(list.get(index) instanceof Type1)
> ((Type1)list.get(index)).doSomething();
It's good to see this in another form, especially a common one.
The order of execution with cast is something I've never paid much
attention until now.
> OTHERWISE, if it was a runtime error, read this (and you might
> want to
[quoted text clipped - 11 lines]
> ((Type1)object1).someBooleanFunction())
> doSomething();
So this cast fails at runtime. Got it.
> the Java Virtual Machine will come across an error if the object
> is not
[quoted text clipped - 6 lines]
> if(((Type1)object1).booleanFunction())
> doSomething();
Thanks .... good to know.
> or, if you are feeling bold and know or are ready to learn the
> ternary
[quoted text clipped - 6 lines]
>
> I hope this helps.
Nice, I've never seen ternary used like that.
Thanks Andrew.
Daniel Pitts - 31 Dec 2006 05:59 GMT
> This is an order of operations issue. It would also help to know
> whether the error you got was a compile-time error or a runtime error.
[quoted text clipped - 55 lines]
>
> I hope this helps.
Actually, you are wrong about the &&... && is a short-circuting
operator, & is not.
<sscce>
public class Test {
private static boolean aCalled = false;
private static boolean bCalled = false;
public static void main(String[] args) {
if (a() && b()) {
System.out.println("a() and b() returned true");
}
System.out.println("aCalled:" + aCalled + ", bCalled: " +
bCalled);
aCalled = false;
bCalled = false;
if (a() & b()) {
System.out.println("a() and b() returned true");
}
System.out.println("aCalled:" + aCalled + ", bCalled: " +
bCalled);
}
public static boolean a() {
aCalled = true;
return false;
}
public static boolean b() {
bCalled = true;
return false;
}
}
</sscce>
<output>
aCalled:true, bCalled: false
aCalled:true, bCalled: true
</output>
The trouble with the code the OP presented was indeed the compile
error.
(MyType)expression will cast the result of "expression" to MyType,
where as ((MyType)object).member will cast object to MyType, and then
access member.
Hope this helps,
Daniel.
> Can somebody explain in English
Will you accept geeklish?
> why the cast of obj to
> AccountBalance works here?
[quoted text clipped - 10 lines]
> return true;
> }
The object member operator ('.') has higher precedence than the
cast operator ('(...)'). The second form tries to call getBalance()
before casting obj to the AccountBalance type.
> In the second snippet the compiler complains of "incompatible
> operand types, AccountBalance and double"
The error message is certainly not descriptive.
Regards,
Patrick
------------------------------------------------------------------------
S P Engineering, Inc. | Large scale, mission-critical, distributed OO
| systems design and implementation.
pjm@spe.com | (C++, Java, Common Lisp, Jini, middleware, SOA)
jupiter - 31 Dec 2006 04:01 GMT
>> Can somebody explain in English
>
> Will you accept geeklish?
Bring it on!
>> why the cast of obj to
>> AccountBalance works here?
[quoted text clipped - 16 lines]
> getBalance()
> before casting obj to the AccountBalance type.
Nice explanation. Is that actually geekish? I've heard much
worse, hehe.
>> In the second snippet the compiler complains of "incompatible
>> operand types, AccountBalance and double"
>
> The error message is certainly not descriptive.
Sorry for the lack of documentation; it was comparing doubles (or
was supposed to be until the cast failed.)
Thanks, Patrick.
Lew - 31 Dec 2006 14:57 GMT
"jupiter" <jupiter49byebyeSpam@msn.com> writes:
>> if(obj instanceof AccountBalance &&
>> (AccountBalance)obj.getBalance() == this.balance) {
>> return true;
>> }
>> ... the compiler complains of
>> "incompatible operand types, AccountBalance and double"
> The error message is certainly not descriptive.
Seems descriptive enough to me. It says that the operands, in this case of ==,
are of incompatible types. The right side is clearly the "double" of the
comparison, so the left side clearly must be the "AccountBalance". This it
clearly is, because the cast makes it so. Therefore, clearly, the operands are
incompatible, just as the error message clearly describes. The message, in
fact, is entirely descriptive. Certainly.
As for the error itself, one should be at least a little bit aware of operator
precedence (*not* "order of operations", which can change), and other Java
language fundamentals, if one is to be a Java programmer. One should be
completely aware that there exist rules of operator precedence, and what the
term means.
That said, it is good practice to use a few extra parentheses to clarify the
order as expressions get more complex, since some of the precedence rules may
be non-obvious even to the experienced.
A closely related topic is operator associativity. What is the interpretation of
a == b? c == d? x : y : e == f? z : null;
just to invent one mildly pathological case. Parentheses would help
readability here, too.
- Lew
> (AccountBalance)obj.getBalance() == this.balance) {
>
> In the second snippet the compiler complains of "incompatible
> operand types, AccountBalance and double
Error on line 17: floating-point type used to record currency data. Your
bank account balance is now reduced by 0.00000325364 cent due to
round-off error. Have a nice day.
jupiter - 06 Jan 2007 04:02 GMT
>> (AccountBalance)obj.getBalance() == this.balance) {
>>
[quoted text clipped - 4 lines]
> data. Your bank account balance is now reduced by 0.00000325364
> cent due to round-off error. Have a nice day.
I got a slightly different number. Let's compromise.