Java Generics Bug in Eclipse 3.6? [message #642330] |
Tue, 30 November 2010 14:55  |
Eclipse User |
|
|
|
This code compiles under jdk1.6.0_22:
package mypackage
import java.util.List;
import java.util.concurrent.Callable;
public class CommandExecutor {
public static <V> List<V> execute(List<Callable<V>> tasks, int threads) {
// do something with callables
return null;
}
public static void execute(List<Runnable> tasks, int threads) {
// do something with runnables
}
}
Eclipse Version: 3.6.1.r361_v20100909-9gF78GrkFqw7GrsZnvz0JWNTeb6fue6896L Build id: M20100909-0800 claims that both execute methods have the same erasure:
and claims this is an error and puts a red x on the file but Eclipse 3.5 has no issues with the above code.
Is this an Eclipse 3.6 bug, or is there some compatibility setting I need to use in 3.6? I tried switching to Java 1.6 compliance from 1.5 compliance but it made no difference and I saw nothing under the Java Compiler Errors/Warnings preferences that seemed relevant. I was planning to submit a bug, but figured I should ask here first since I'm new to 3.6. Thanks.
Jim
|
|
|
|
|
|
Re: Java Generics Bug in Eclipse 3.6? [message #642515 is a reply to message #642487] |
Wed, 01 December 2010 11:01   |
Eclipse User |
|
|
|
Il 01/12/2010 15:46, james.mckinley@cengage.com ha scritto:
> Callable and Runnable are concrete types though, why wouldn't the
> compiler be able to know which method to call? Is it that if a method or
> class is written using generics (i.e. List) then the compiler can never
> differentiate between specific types of that class (i.e. List<String>
> vs. List<Integer>) when used as arguments? That seems overly restrictive
> to me, if the execute functions above were truly written with List<E> as
> the first argument then of course I understand the problem, but I
> would've thought it perfectly valid if concrete types were used.
> If I write:
>
>
> public static void test(List<String> arg) {
> // do stuff
> }
>
>
> and then call it with the wrong type of list
>
>
> public static void main(String[] args) {
> List<Integer> list = new ArrayList<Integer>();
> test(list);
> }
>
>
> the compiler (and eclipse) will properly flag this call of the test
> method in main as invalid since String and Integer are different types,
> so it seems to me it should be able to tell in the case of the
> CommandExecutor above as well. What am I missing? Thanks again.
IMHO I think you should go through some deeper documentation about
generics. Generics are a way to let you write typesafe code, but once
the code is compiled they are erased, in order to produce bytecode which
is backward-compatible with Java<5. Under this point of view
List<String> and List<Integer> are both just List once compiled, this is
why the compiler rejects your code, although from a plain compilation
point of view it would be possible to differentiate between a call to
test(List<String>) and test(List<Integer>).
However, please note that if you write this:
public class Test
{
public static void test(List<String> a)
{
for(Object element : a)
System.out.println(element);
}
public static void main(String[] args)
{
List<Integer> b = new ArrayList<Integer>();
test((List) b);
}
}
This code is perfectly compiling and working, although you are actually
calling test(List<String>) by passing it a List<Integer>. The compiler
warns you about the potential error, but this highlights a bit how
things work under the cover. Suppose it would be legal to have another
test(List<Integer>), the picture would be even more complicated.
I think the Java Language Specification has introduced some constraints
here to avoid ambiguities. The Eclipse and Oracle compilers are now
complying better with the specification.
Maybe someone will be able to provide you a more theoretical and
exhaustive explanation.
HTH
Mauro.
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.04269 seconds