inconsistent compiler behavior with generics example

R

Roger Levy

I have this new function that I wrote inside Eclipse (OS X, Java
1.5.0) and it both compiles and runs in Eclipse, and compiles using
javac within OS X. But it fails to compile through either (1) javac
on Linux (version 1.6.0), or (2) Apache ant on either OS X or Linux.
Here's the program and I'm appending the compile-time error message.

Thanks

Roger

***

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

public class Blah {

public static <E,L1 extends Collection<E>, L2 extends
Collection<L1>> L2 asListOfLists(E[][] array) {
List<List<E>> result = new ArrayList<List<E>>();
for(E[] a : array ) {
result.add(Arrays.asList(a));
}
return (L2) result;
}

public static void main(String[] args) {
System.out.println(asListOfLists(new Integer[][] { { 1,2 },
{ 3,4 }} ));
}

}

Error:

$ javac -d . Blah.java
lBlah.java:19: incompatible types; inferred type argument(s)
java.util.Collection<java.lang.Integer>,java.lang.Object do not
conform to bounds of type variable(s) L1,L2
found : <L1,L2>L2
required: java.lang.Object
System.out.println(asListOfLists(new Integer[][] { { 1,2 },
{ 3,4 }} ));
^
Note: Blah.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
 
L

Lew

Roger said:
I have this new function that I wrote inside Eclipse (OS X, Java
1.5.0) and it both compiles and runs in Eclipse, and compiles using
javac within OS X. But it fails to compile through either (1) javac
on Linux (version 1.6.0), or (2) Apache ant on either OS X or Linux.
Here's the program and I'm appending the compile-time error message.

Thanks

Roger

***

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

public class Blah {

public static <E,L1 extends Collection<E>, L2 extends
Collection<L1>> L2 asListOfLists(E[][] array) {
List<List<E>> result = new ArrayList<List<E>>();
for(E[] a : array ) {
result.add(Arrays.asList(a));
}
return (L2) result;
}

public static void main(String[] args) {
System.out.println(asListOfLists(new Integer[][] { { 1,2 },
{ 3,4 }} ));
}

}

Error:

$ javac -d . Blah.java
lBlah.java:19: incompatible types; inferred type argument(s)
java.util.Collection<java.lang.Integer>,java.lang.Object do not
conform to bounds of type variable(s) L1,L2
found : <L1,L2>L2
required: java.lang.Object
System.out.println(asListOfLists(new Integer[][] { { 1,2 },
{ 3,4 }} ));
^
Note: Blah.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error

- Autoboxing and arrays don't mix.
- Generics and arrays don't mix.
- You cannot declare an array of genericized type, really.
- You cannot cast to a genericized type, really.

Instead of relying on autoboxing, which notoriously doesn't treat Integer[]...
well at all, declare the constants directly as the object type and see what
happens.

Integer.valueOf(1), not 1.

Then abandon the idea of directly creating a genericized array, or of casting
to the generic type.
 
P

Piotr Kobzda

Roger Levy wrote:

[...]
public static <E,L1 extends Collection<E>, L2 extends
Collection<L1>> L2 asListOfLists(E[][] array) {
List<List<E>> result = new ArrayList<List<E>>();
for(E[] a : array ) {
result.add(Arrays.asList(a));
}
return (L2) result;
}

Regardless of what your compilers are saying, here is incompatibility of
local 'result' type and the method's return type (L2) -- List<List<E>>
_is not_ compatible with each type that is a Collection<Collectoion<E>>,
it's not even compatible with each type compatible with List<List<E>>,
for instance, cast to LinkedList<LinkedList<E>> will fail here.

Try the following:

public static <E> List<List<E>> asListOfLists(E[][] array) {
List<List<E>> result = new ArrayList<List<E>>();
for(E[] a : array) {
result.add(Arrays.asList(a));
}
return result;
}


piotr
 
R

Roger Levy

Roger Levy wrote:

[...]
public static <E,L1 extends Collection<E>, L2 extends
Collection<L1>> L2 asListOfLists(E[][] array) {
List<List<E>> result = new ArrayList<List<E>>();
for(E[] a : array ) {
result.add(Arrays.asList(a));
}
return (L2) result;
}

Regardless of what your compilers are saying, here is incompatibility of
local 'result' type and the method's return type (L2) -- List<List<E>>
_is not_ compatible with each type that is a Collection<Collectoion<E>>,
it's not even compatible with each type compatible with List<List<E>>,
for instance, cast to LinkedList<LinkedList<E>> will fail here.



Ah, yes, of course you're right. I was thinking about this
improperly. Thank you!
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top