0

This is a very simple example of Java Generics. My issue here is why doesn't the compiler show compile error in intellij 13 with Java 7 without running the code, when the class is expecting a type that implements Vehicle and not a type that implements AirUnit when adding my list of AirUnits in an arraylist that expect a Vehicle in the HighWay Class.

Vehicle:

public interface Vehicle {
     void goForward();
}

AirUnit:

public interface AirUnit {
 void fly();
}

The Highway class that takes an array of vehicles and run them and prints their toString().

import java.util.ArrayList;

public class HighWay<T extends Vehicle> {

    private ArrayList<T> vehicles;

    public HighWay(ArrayList<T> vehiclesOnTheRoad){
        this.vehicles = vehiclesOnTheRoad;
    }


    public void moveTheVehicles(){
        for(T vehicle: vehicles){
            System.out.println(vehicle);
        }
    }
}

The Client

import java.util.ArrayList;

            public class Client {

                public static void  main(String[] args) {
                    Vehicle car = new Car();
                    Vehicle bike = new Bike();
                    AirUnit plane = new Plane();

                    ArrayList<Vehicle> vehicles = new ArrayList();
                    ArrayList<AirUnit> airUnites = new ArrayList();
                    airUnites.add(plane);

                    vehicles.add(car);
                    vehicles.add(bike);


                    // should show compile error because HighWay is expecting something
                    // that implements Vehicle but it is now showing any errors
                    // until I run the app and it breaks in the loop.
                    HighWay<Vehicle> highWay = new HighWay(airUnites);
                    highWay.moveTheVehicles();
                }
            }
SamTheGoodOne
  • 1,395
  • 2
  • 12
  • 19

2 Answers2

1

The problem is that the compiler tests the type when you declare which type of HighWay you are instantiating. If you told it what type you were using, it would complain then, e.g.

HighWay<Car> highWay = new HighWay<> (airUnites);

would cause an error because airUnites isn't a list of Cars, or

HighWay<Plane> highWay = new HighWay<> (airUnites);

would also fail because Plane doesn't extend Vehicle so doesn't match the constraint you specified. But because you're not specifying the type of HighWay you create, it turns off the generic type checking. It should be producing a warning because of this, telling you that you should be specifying the type, although you may have the warnings disabled (check your compiler settings in your IDE to see if this is the case -- I'm not sure how to do it because I don't use IntelliJ).

Jules
  • 14,841
  • 9
  • 83
  • 130
0

It's because you're not declaring which generic type you will use when you declare highWay:

HighWay highWay = new HighWay(airUnites);

This creates a non-generic type where everything uses Object and it's up to you to use it correctly. It's best thought of as saying:

HighWay<Object> highWay = new HighWay<>(airUnites);
MrLore
  • 3,759
  • 2
  • 28
  • 36
  • I tried this: `code`HighWay highWay = new HighWay(airUnites);`code` it does not give me error but it does when doing this: `code`HighWay highWay = new HighWay(airUnites);`code` – SamTheGoodOne Apr 20 '14 at 16:13
  • @SamTheGoodOne You need to declare the type parameter on both sides, e.g. `HighWay highWay = new HighWay(airUnites);` or `HighWay highWay = new HighWay<>(airUnites);` for Java 7. – MrLore Apr 20 '14 at 16:14
  • I get it now, I actually tried it but did not try to add a type in the end of the declaration. Now Im getting a compile error. Thanks for your note. – SamTheGoodOne Apr 20 '14 at 16:15