Re: Compiler bug? "reference to addAll is ambiguous"
"Tom Hawtin" <usenet@tackline.plus.com> wrote in message
news:4697a38b$0$1613$ed2619ec@ptn-nntp-reader02.plus.net...
Oliver Wong wrote:
<errorMessage>
Rewriting\src\java\gov\sc\eip\report\birt\ChangesRowGenerator.java:116:
reference to addAll is ambiguous, both method
addAll(java.util.Collection<? extends E>) in
java.util.Collection<capture#420 of ? super
gov.sc.eip.report.birt.items.ChangeRow> and method
addAll(java.util.Collection<? extends E>) in java.util.List<capture#420
of ? super gov.sc.eip.report.birt.items.ChangeRow> match
</errorMessage>
I assume E extends ChangeRow.
There is no actual "E" in my code. I think the "E" comes from Sun's
implementation onf java.util.List.class and java.util.collection.class.
The variable "rows" involed here is declared as "List<? super ChangeRow>
rows", so I guess "E" is "? super ChangeRow" and so the method addAll's
generic type is "? extends (? super ChangeRow)" (not sure if that even
makes sense). But anyway, I think, from a language-specification point of
view, the error doesn't really have anything to do with generics.
However, from a practical-implementation point of view, if this is indeed
a bug in the compiler and not in my understanding, I can imagine how
throwing generics in the mix might have introduced this bug.
And anyway, aren't these both interfaces, and thus provide zero
implementation, and thus it doesn't really matter which of these two
methods are being called, since they will eventually point to the exact
same implementation depending on what underlying concrete type is
involved?
It doesn't matter if the (non-private, non-static) method is being
called is defined in an interface or a class (other than the instruction
is invokeinterface vs invokevirtul).
Right, but what I meant is that we have a class hierarchy like:
public interface Collection<E> {
public void addAll(Collection<? extends E> stuffToAdd);
}
public interface List<E> extends Collection {
public void addAll(Collection<? extends E> stuffToAdd);
}
public class ArrayList<E> implements List<E> {
/* etc. */
}
so that when you have code like:
public void myMethod(List<? super ChangeRow> rows) {
rows.addAll(getSomeData());
}
public List<? super ChangeRow> getSomeData() {
List<ChangeRow> returnValue = new ArrayList<ChangeRow>();
return returnValue;
}
there should be no reason to ask whether the .addAll() refers to the one
in Collection, or the one in List. I've got a
multiple-interface-inheritance situation, and *not* a
multiple-implementation-inheritance situation; thus the "diamond problem"
does not come up, and thus there should be no ambiguity about which method
I'm invoking when I call .addAll().
<veryShortSnippet>
rows.addAll(getRowForGenericChange(changeSet.getCountyChange(),
CommonFieldNamesEnum.COUNTY.getCode()));
</veryShortSnippet>
That rules out the only tenuous explanation I could think of (that it
was something wacky to do with inner classes).
Right, the code is structurally very straightforward (it's essentially
a CRUD web app). No inner classes anywhere to be seen.
"rows" is a parameter past into the method of type "List<? super
ChangeRow>". As you can see, I'm not doing any weird casting to bypass
the overwriting (e.g. I'm not doing something like
"((Collection)rows).addAll(whatever)", which in my opinion should work
even if I did do that anyway).
The obvious work around is to assign rows to a Collection<? super
ChangeRow> variable. (I assume ChangeRow has no generic parameters.)
I'll give that a try and ask my coworker to compile again and see what
happens.
- Oliver