2

I got a function that expects a LinkedList of objects, is it possible to pass and use a LinkedList of a sub-class of those objects?

public abstract class Car {...} //just for example

public class Audi extends Car {...}

public void showCars (LinkedList<Car> cars) {    //example function
    for (Car i : cars) {            
        System.out.println(i);
    }
}

public void test () {
    LinkedList<Audi> audis = new LinkedList<Audi>();

    audis.add(new Audi(...));    //just for example so that the list is not empty
    showCars(audis);              //this says that its expecting a LinkedList<Cars>
                                 //but got LinkedList<Audi>
}

It says that showCars expects LinkedList<Cars> but got LinkedList<Audi>. This is just a very simple code outline which hopefully shows my problem.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Thenex
  • 23
  • 3

2 Answers2

2

There are two ways of doing this:

Change the accepting method signature

The method you call should accept a list of Cars or its subclasses for this to work, and you have to define it that way. Change your showCars method signature to the following:

public void showCars (LinkedList<? extends Car> cars)

You can read https://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html for more information.

Change the type of the list you pass as parameter

Based on the rightful comment from @JohnBollinger, there is another way. You can declare your list as a list of cars, and send it to your method, instead of a list of Audis:

public abstract class Car {...} //just for example

public class Audi extends Car {...}

public void showCars (LinkedList<Car> cars) {    //example function
    for (Car i : cars) {            
        System.out.println(i);
    }
}

public void test () {
    LinkedList<Car> audis = new LinkedList<>();

    audis.add(new Audi(...));    //just for example so that the list is not empty
    showCars(audis);              //this says that its expecting a LinkedList<Cars>
                                 //but got LinkedList<Audi>
}

Remember than a list with a Class generic type will accept also objects of its subclasses.This would preserve the original method signature and leave the responsibility on the caller to provide the properly typed LinkedList. This would also be the proper way to do this when the method you are calling is provided by a library or other source you have no access to.

HaroldH
  • 533
  • 1
  • 4
  • 10
  • 1
    It's probably also worth mentioning that `LinkedList` is not a subclass of `LinkedList` even though `Audi extends Car` which is why we need wildcards. – Code-Apprentice Aug 13 '21 at 22:18
  • 2
    ... but if the method requires a list with the specific parameter type `Car`, then that is what you must present. Consider that if the method expects a `LinkedList` then it may assume that it can add a `Volvo` to that list, but it would be incorrect for it to do so if the argument were really a `LinkedList`. – John Bollinger Aug 13 '21 at 22:18
-2

You can try something like that:

public void test () {
    LinkedList<? extends Car> audis = new LinkedList<Audi>();
    LinkedList pleaseDontDoIt = audis;
    pleaseDontDoIt.add(new Audi());
    showCars(pleaseDontDoIt);
}

but this is totally unsafe

Kasangras
  • 27
  • 5
  • Java will warn you of an unchecked cast doing this. It is a bad practice, which -may- be required when interacting with pre-1.5 java libraries, but generally warnings should not be ignored. – HaroldH Aug 13 '21 at 22:37
  • Yep it is unsafe cast. I mentioned it under the code. – Kasangras Aug 13 '21 at 22:39