I have those classes.
public class Flight {
public List<FlightOffer> flightOffers;
}
public class Hotel<T> {
public List<HotelOffer> hotelOffers;
public T address
}
public class FlightOffer extends BaseOffer{
}
public class HotelOffer extends BaseOffer{
}
public class BaseOffer{
public String id;
}
flightOffers and hotelOffers returns a list.
Flight flightObject = new Flight();
flightObject.flightOffers.add(new BaseOffer()); // not working
//(add (FlightOffer) List cannot be applied to (BaseOffer))
Hotel hotelObject = new Hotel<String>();
hotelObject.hotelOffers.add(new BaseOffer()); // working
but if i convert Flight
to Flight<T>
its working, why?
List<FlightOffer> flightOffers
defines quite clearly what you can add to the list: instances of FlightOffer
. flightOffers.add(new BaseOffer());
hence can't work since a BaseOffer
is not a FlightOffer
.
So why does hotelOffers.add(new BaseOffer());
work? Because you are disabling generic type checks by using the raw type Hotel
in Hotel hotelObject = new Hotel<String>();
.
You should get a warning about that as well which conveys another lesson: don't ignore the warnings. The compiler doesn't know that something will fail but more often than not it "guesses" correctly and warns you about that.
Edit:
Note what the JLS states on raw types (in the first box of section 4.8):
Another implication of the rules above is that a generic inner class of a raw type can itself only be used as a raw type.
That means that because Hotel
is a raw type, every generic type inside it can also only be a raw type, i.e. hotelOffers
is treated as if it were a raw List
which allows any type of object (thus even this should work in your code hotelObject.hotelOffers.add("I'm not a hotel offer");
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With