0

I will try to simplify my compilation problem.
I have a Car Object and two successors called Honda & Toyota.
I have another Object called CarContainer which is defined as follows:

public class CarContainer<T> {} // doesn't do anyhthing

I want to create a list of car containers of many types of cars objects.
In this example it will hold an array of that type of cars.

List<CarContainer<? extends Car[]>> obs = new ArrayList<>();

This works fine -

CarContainer<Honda[]> hondaCarContainer = new CarContainer<>();
CarContainer<Toyota[]> toyotaCarContainer = new CarContainer<>();
Collections.addAll(obs, hondaCarContainer, toyotaCarContainer);

But when I try to generate the container using a method

private static <T> CarContainer<T[]> getCarContainer(T car) {
    return null;
}

and calling

Collections.addAll( obs, 
                    getCarContainer(new Honda()), 
                    getCarContainer(new Toyota()));

My code doesn't compile.

(though this does

Collections.addAll(obs, getCarContainer(new Honda()));

and unbelivably this also

    CarContainer<Honda[]> carContainer = getCarContainer(new Honda());
    Collections.addAll(obs, carContainer, getCarContainer(new Toyota()));

which is the same. )

How is it solvable?

Holger
  • 285,553
  • 42
  • 434
  • 765
Bick
  • 17,833
  • 52
  • 146
  • 251

3 Answers3

1

I can compile and run your code without any problem, (win7 jdk7):

public class MyTest {

public static void main(String[] args) {
    new MyTest();
}

public MyTest() {
    List<CarContainer<? extends Car[]>> obs = new ArrayList<>();

    Collections.addAll( obs,
            getCarContainer(new Honda()),
            getCarContainer(new Toyota()));

    System.out.println(obs.size());
}

private <T> CarContainer<T[]> getCarContainer(T car) {
    return null;
}

class Car{}

class Honda extends Car {}

class Toyota extends Car {}

class CarContainer<T> {}
}

It outputs "2" in console.

cn123h
  • 2,302
  • 1
  • 21
  • 16
1

This will compile.

public class MyTest {

public static void main(String[] args) {
    new MyTest();
}

public MyTest() {
    List<CarContainer<? extends Car[]>> obs = new ArrayList<>();
    CarContainer<Honda[]> c = getCarContainer(new Honda());
    CarContainer<Toyota[]> c2 = getCarContainer(new Toyota());

    Collections.addAll(obs,
            c, c2);

    System.out.println(obs.size());
}

private <T> CarContainer<T[]> getCarContainer(T car) {
    return null;
}

class Car{}

class Honda extends Car {}

class Toyota extends Car {}

class CarContainer<T> {}

}

It seems that JDK developers changed type inference rules to support lambdas.

http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

Yegor Chumakov
  • 450
  • 4
  • 11
0

cm123h's answer compiles and runs fine for me in eclipse Luna using jdk8_20.

I might change your getCarContainer method to

private <T extends Car> CarContainer<T[]> getCarContainer(Class<T> car) {
    return null;
}

as there's no reason to instantiate an object just to get its type at compile-time, but that's being nitpicky.

Community
  • 1
  • 1
Steve K
  • 4,863
  • 2
  • 32
  • 41