Results 1 to 8 of 8
  1. #1
    castiel is offline Member
    Join Date
    Aug 2009
    Posts
    26
    Rep Power
    0

    Default Generics and wildcards confusion

    Hey I was reading this tutorial:

    Wildcards (The Java™ Tutorials > Bonus > Generics)

    and I don't get why the following throws a compile-time error.


    Java Code:
    public void addRectangle(List<? extends Shape> shapes) {
        shapes.add(0, new Rectangle()); // Compile-time error!
    }
    "The type of the second parameter to shapes.add() is ? extends Shape-- an unknown subtype of Shape. Since we don't know what type it is, we don't know if it is a supertype of Rectangle; it might or might not be such a supertype, so it isn't safe to pass a Rectangle there. "


    If shapes is a list of unknown types which extend Shape, and it is known that Rectangle extends shape, then why is there a compile time error?

    Cheers,
    newbie

  2. #2
    Junky's Avatar
    Junky is offline Grand Poobah
    Join Date
    Jan 2011
    Location
    Dystopia
    Posts
    3,798
    Rep Power
    7

    Default

    Let me test your undestanding. The following code compiles but can you tell me what the problem with it is?
    Java Code:
        public void doStuff(List<?> things) {
            XX foo = (XX) things.get(0);
        }

  3. #3
    castiel is offline Member
    Join Date
    Aug 2009
    Posts
    26
    Rep Power
    0

    Default Reply to junky

    I'm guessing that it won't compile as the datatype is unknown and you can't typecast it to XX as you don't know whether ? is a subtype of XX or of type XX itself.

  4. #4
    castiel is offline Member
    Join Date
    Aug 2009
    Posts
    26
    Rep Power
    0

    Default sorry misread that

    i read it as it doesn't compile...so how does that work then?

  5. #5
    castiel is offline Member
    Join Date
    Aug 2009
    Posts
    26
    Rep Power
    0

    Default Get the problem junky i think

    I think i get what the problem will be as i outlined in the previous message, i understand that it would work if 'things' contained a list of items which "could" be cast to XX but if it didn't then it would fail. right?

  6. #6
    Junky's Avatar
    Junky is offline Grand Poobah
    Join Date
    Jan 2011
    Location
    Dystopia
    Posts
    3,798
    Rep Power
    7

    Default

    The code does compile as each of those three lines are syntactically correct. The compiler is generally dumb as it doesn't look at more than a single line of code at once. A more common problem people encounter is
    Java Code:
    public int doStuff() {
        if(true) {
            return 42;
        }
    }
    That does not compile as it is missing a return statement. To you and me we can see that it HAS to return 42 because it enters the if statement. Compiler says NO. All it knows is that it gets to the end of the method and there is no return statement.

    So getting back to my code, it compiles. However at run time if I pass a List containing anything other than XX objects you will get a ClassCastException at runtime.

    For the code you asked about the reverse is true. The compiler doesn't really care that Rectangle extends Shape. All it knows is that there is a potential that code can be written that will fail. For example, if that code DID compile then the following will also compile:
    Java Code:
    public void addRectangle(List<? extends Shape> shapes) {
        shapes.add(0, new Rectangle());
        shapes.add(0, new Cow());
        shapes.add(0, new Cheesecake());
        shapes.add(0, new Foo());
    }
    Even though those other classes don't(shouldn't) extend Shape. Therefore the compiler avoids potentially bad code.

  7. #7
    castiel is offline Member
    Join Date
    Aug 2009
    Posts
    26
    Rep Power
    0

    Default Moral of story is compiler is stupid lol

    So basically the compiler never does any form of investigation on relationships between classes, hence even though Rectangle DOES extend Shape, it has a cry. Thanks for clearing that up, your examples were really good.

    If I hadn't read your explanation of:

    Java Code:
    public void addRectangle(List<? extends Shape> shapes) {
        shapes.add(0, new Rectangle());
        shapes.add(0, new Cow());
        shapes.add(0, new Cheesecake());
        shapes.add(0, new Foo());
    }
    I would have assumed that the compiler would only throw errors for those statements in which the object being created DID NOT extend Shape..


    Thanks

  8. #8
    Junky's Avatar
    Junky is offline Grand Poobah
    Join Date
    Jan 2011
    Location
    Dystopia
    Posts
    3,798
    Rep Power
    7

    Default

    I just blathered on a bit and realised I could explain it much simpler with a code snippet.
    Java Code:
    public void addRectangle(List<? extends Shape> shapes) {
        shapes.add(0, new Rectangle()); // Compile-time error!
    }
    
    List<Circle> shapeList = new ArrayList<Circle>();
    addRectangle(shapeList);
    Hopefully that really hits home the potential disaster.

Similar Threads

  1. Type wildcards in Generic
    By gvm in forum New To Java
    Replies: 1
    Last Post: 10-22-2010, 04:39 PM
  2. Confusion here @@' Help!
    By pleasurelyours in forum New To Java
    Replies: 7
    Last Post: 06-09-2010, 03:42 PM
  3. Confusion in line
    By JavaJunkie in forum New To Java
    Replies: 1
    Last Post: 06-13-2009, 10:46 PM
  4. Tic Tac Toe confusion
    By jigglywiggly in forum New To Java
    Replies: 15
    Last Post: 04-12-2009, 01:47 AM
  5. Generics and Wildcards
    By ajeeb in forum Advanced Java
    Replies: 2
    Last Post: 01-30-2009, 11:00 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •