5

Consider this java class:

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;


public class NumberSet {

    private Collection<? extends Number> numbers;

    public NumberSet(Collection<? extends Number> numbers) {
        this.numbers = numbers;
    }

    public NumberSet(NumberSet other) {

        //copy other.numbers to this.numbers
        numbers = new LinkedList<>();
        for (Iterator<? extends Number> it = other.numbers.iterator(); it.hasNext();) {
            numbers.add(it.next()); // Here's Syntax Error near `it.next()`
        }

    }
}

There is This Syntax Error inside for loop:

actual argument Number cannot be converted to CAP#1 by method invocation conversion
where E is a type-variable:
    E extends Object declared in interface Collection
where CAP#1 is a fresh type-variable:
    CAP#1 extends Number from capture of ? extends Number

I Understand the meaning of PECS but I want to implement a copy-constructor for this class. the copied instance would be used Just as an snapshot of other. any Idea?

Mostafa Nazari
  • 616
  • 7
  • 21
  • 1
    @BrianAgnew I really don't understand how one can mark this question as a duplicate of `What is PECS`? If someone knew the term `PECS`, they wouldn't post a question in the first place. – Chetan Kinger Jun 16 '15 at 16:21
  • 1
    I've re-opened it since I agree with you. I think the PECS question/answer does address this, but I take your point completely – Brian Agnew Jun 16 '15 at 16:23
  • 1
    @BrianAgnew Thanks for the reopening the question. I am editing the title so that it is more accessible. – Chetan Kinger Jun 16 '15 at 16:29
  • @ChetanKinger I was not at my computer until now. Thanks all for participation. I knew the meaning of `PECS`, but The problem is still a mystery for me, I would change the question body, ASAP, to clear all ambiguities. – Mostafa Nazari Jun 17 '15 at 06:08
  • @MostafaNazari Wow, you just changed the entire question. Yet the solution remains the same. Use `? super` instead of `? extends`. At this point, I would like to ask you : If you have understood what `PECS` is and you know you are supposed to use `? super`, what is still a mystery? The linked answer on `PECS` explains why you can't put when using `? extends` – Chetan Kinger Jun 17 '15 at 06:39
  • I have done this code, by doing this: use `LinkedList numbers = new LinkedList<>();` before `for` to hide generic collection `this.numbers`, and after copying finished, use `this.numbers = numbers;`. but I'm looking for better solution @ChetanKinger @BrianAgnew – Mostafa Nazari Jun 17 '15 at 06:43
  • I am voting to close this question as `unclear` since it's beyond me to comprehend what the OP is asking. – Chetan Kinger Jun 17 '15 at 06:45
  • @ChetanKinger Using `? super` here is not possible. the problem is: how to make a copy of `Collection extends Number>` ? – Mostafa Nazari Jun 17 '15 at 06:50
  • @MostafaNazari If you are adamant about sicking to `? extends`, then you can't `add` elements to the `Collection extends Number>`. What you can simply do is assign `numbers=others`. If you don't want to do that, then open up the `JVM` sourcecode and modify it to allow addition using `? extends`. Good luck. – Chetan Kinger Jun 17 '15 at 08:59

1 Answers1

5

Change :

 Collection<? extends Number> dst 

To :

 Collection<? super Number> dst

Addition is not allowed using ? extends. There is something known as the Get and Put principle. Quoting from the Generics and Collections book from Philip Wadler :

The Get and Put Principle: use an extends wildcard when you only get values out of a structure, use a super wildcard when you only put values into a structure, and don’t use a wildcard when you both get and put

Also take a look at PECS for a more common explanation of this phenomenon. (However, I prefer the GET and PUT principle over the Producer and Consumer principle as it is less confusing)

Community
  • 1
  • 1
Chetan Kinger
  • 15,069
  • 6
  • 45
  • 82