4

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?

0

2 Answers 2

9

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");)

Sign up to request clarification or add additional context in comments.

5 Comments

Why does it disable the generic type check for the hotelOffers list? The list doesn't use the type parameter of the Hotel object. It will always be List<HotelOffer>.
Might want to add that by using Hotel<String> = .. it will use the type check.
Does the compiler transitively disable the generic type check on every member of the object when using the raw type?
@marstran sorry, looked up the wrong section of the JLS. I'll add it later,
Here is an explanation for that behavior from Angelika Langer.
1

You're trying to add a BaseOffer object (superclass) in a List of FlightOffer (subclass) objects.

https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

Flight flightObject = new Flight();
flightObject.flightOffers.add(new FlightOffer());    // that's correct

1 Comment

I think the weird part here is that the second example actually compiles (although with a warning).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.