ClassCastException with Java compiler, but not with Eclipse compiler???? [message #1499633] |
Fri, 05 December 2014 04:27  |
Eclipse User |
|
|
|
Hi.
I have a curious thing.
See the small attached java file.
public static void test(List<Long> list) {
for (Object keyId : list) {
Long id;
if (keyId instanceof String)
id = new Long((String) keyId);
else
id = (Long) keyId;
System.out.println(id);
}
}
public static void main(String[] args) {
List list = new ArrayList<Object>();
list.add("1234");
list.add(1000L);
test(list);
}
(No comments, I know this code is *BAD*)
Theses few lines compiles without problems (except warning)
If I compile this with Eclipse, and run it, no problem. All works.
But if I compile this with javac, and run it, I get a ClassCastException.
I'm seeking for a way to have Eclipse compiler behave 100% like javac compiler.
And so, to compile to a code that will throw the ClassCastException too....
Any hint ?
Thanks for your help.
|
|
|
Re: ClassCastException with Java compiler, but not with Eclipse compiler???? [message #1500316 is a reply to message #1499633] |
Fri, 05 December 2014 16:54   |
Eclipse User |
|
|
|
That's a really weird thing you're trying to achieve.
First: The only compilers generating the code that trows CCE are javac 1.5 and javac 1.6.
Starting with version 1.7, javac agrees with ecj and no exception is raised.
Background: the CCE in javac-1.5-compiled code stems from the head of the loop:
for (Object keyId : list) {
The compiler knows that list contains Long instances (that's how it's declared) hence the javac 1.5 compiler feels obliged to cast the result of Iterator.next() - which at bytecode level has type Object - to the declared Long. Perfectly legal, but unnecessary, because the program is not interested in knowing that keyId is a Long.
Modern compilers optimize the code as to avoid casts that are definitely unnecessary.
If you really want to see the exception (which makes sense as it makes your program fail fast, rather than propagating erroneous values), you could try to change the loop header to:
for (Long keyId : list) {
Now the compilers no longer regard the cast as unnecessary and all will create the code that throws CCE at runtime.
However, with this modification, the compiler will also detect that the subsequent code is bogus:
----------
1. ERROR in /tmp/TestCast.java (at line 10)
if (keyId instanceof String)
^^^^^^^^^^^^^^^^^^^^^^^
Incompatible conditional operand types Long and String
----------
2. ERROR in /tmp/TestCast.java (at line 11)
id = new Long((String) keyId);
^^^^^^^^^^^^^^
Cannot cast from Long to String
----------
Having a CCE at the loop header means, the subsequent code will never be entered with a String value. Hence the if-then part is nonsense, and a good compiler will detect that, unless you trick the compiler with declaring keyId as Object.
best,
Stephan
|
|
|
|
|
|
|
Re: ClassCastException with Java compiler, but not with Eclipse compiler???? [message #1504616 is a reply to message #1504604] |
Tue, 09 December 2014 07:04   |
Eclipse User |
|
|
|
Yes, fully agree about getting error during code edition....
But as I said, I can't change code.....
What i was looking for is a way to get Eclipse have same compilation behavior as JavaC 1.6.....And so that when I run my test, I get the exception throwed.....
It's a very huge software, with this kind of errors potentially in multiple places, on which several peoples are involved.
At the moment, Eclipse only display a warning for such bad code.
And if the <evil> programmer does such bad programming, and ignore the warning, all will runs fine on Eclipse, he will never see that a problem will occurs on the final software version, compiled with JavaC....
So, understanding your answers, I don't have any way to get Eclipse behavior 100% same as JavaC on this point....So we will teach to the team to avoid this kind of programmation, and hope they will do it....
Thanks for your help!
|
|
|
|
Powered by
FUDForum. Page generated in 0.05441 seconds