Generics error messages

R

Roedy Green

I wonder if anyone can shed light on what this error message means:


Name clash: The method addAll(Collection<E>) of type
SortedArrayList<E> has the same erasure as addAll(Collection<? extends
E>) of type ArrayList<E> but does not override it
SortedArrayList.java

the code looks like this:

public class SortedArrayList<E> extends ArrayList<E> implements
Cloneable {
....


public boolean addAll ( Collection<E> c )
{
sorted = false;
return super.addAll( c );
}


Is there distinction between <E> and <? extends E>?

If the underlying arrayList has a method addAll( Collection ) types
aside, why would not my method override it.?



--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
C

Chris Smith

Roedy Green said:
Is there distinction between <E> and <? extends E>?

Yes, but it's kind of subtle.

Let's say I've got a class Automobile and two classes Car and Truck that
both derive from Automobile. A Collection<Automobile> can contain
instances of Automobile, or Car, or Truck. I can, for example, add one
of each and then read them back out into references of type Automobile,
and this is all safe to do. A Collection<Car>, on the other hand, may
only contain Cars. It is an error to try to add a Truck to such a
collection. Note that the two generic classes Collection<Automobile>
and Collection<Car> are NOT related by inheritance, even though their
type parameters are related.

Note that up to this point, we've only been talking about the (pre-
erasure) runtime class of various collection objects. The references
used to refer to those collection objects can have a range of other
types. A reference of type Collection<Automobile> is somewhat limited.
It can ONLY refer to a Collection<Automobile>, and can NOT refer to a
Collection<Object> or a Collection<Car>. (Of course, an instance of
Collection<Automobile> can contain objects of class Car, but that's not
the same as having an object of class Collection<Car>.)

There are also wildcard types. A Collection<? extends Automobile> is a
reference type that can refer to any of a Collection<Automobile>,
Collection<Car>, or Collection<Truck>. Even though the three classes
are not related to each other by inheritance, they are all assignment
compatible with that wildcard type.

So what's the practical difference? Well, a reference of type
Collection<? extends Automobile> MIGHT be referring to an object of
class Collection<Truck>, so you can't safely add a Car to it. It also
might be referring to an object of Collection<Car>, so you can't add a
Truck to it. In fact, it turns out you can never add anything to a
collection of a lower-bound wildcard type, because you can never
guarantee that the object you're adding is compatible with the object's
actual type parameter. This is quite different from the simpler
Collection<Automobile>, where you know that the type parameter is
Automobile and therefore it's definitely safe to add a Car or Truck
object.

(Note that this can sometimes be counter-intuitive. Many people
initially expect that you would be able to add a Car object to a
Collection<? extends Automobile> but would not be able to add it to a
If the underlying arrayList has a method addAll( Collection ) types
aside, why would not my method override it.?

Because someone might pass a Collection<Car> to addAll, and then your
method would not be appropriate. Essentially, you're writing a more
specific method than the superclass; one that is pickier about its
parameters. You can't do that without an overload, and you can't
overload without changing the type erasure.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

jan V

Chris Smith said:
Yes, but it's kind of subtle.

[snip]

I'm sure many are grateful for your detailed explanation, but to me, the
length and complexity of the explanation is simple proof that Sun really
took a big step backwards by adding generics to Java.

Java used to be KISS. Adding inner classes was already a dangerous departure
from the KISS beauty and power of Java 1.0. The "geniuses" who crippled Java
with generics forgot why Java was created in the first place. Shame on them.
Java is quickly turning into what it was originally designed to improve on:
C++ !
 
T

Tim Tyler

jan V said:
I'm sure many are grateful for your detailed explanation, but to me, the
length and complexity of the explanation is simple proof that Sun really
took a big step backwards by adding generics to Java.

Java used to be KISS. Adding inner classes was already a dangerous departure
from the KISS beauty and power of Java 1.0. The "geniuses" who crippled Java
with generics forgot why Java was created in the first place. Shame on them.
Java is quickly turning into what it was originally designed to improve on:
C++ !

Generic types make Java a lot more complex.

The /way/ in which Sun added it makes it a lot more complex than was
necessary.

It is - nontheless - an improvement over Java without generic types, IMO.

The analogy with inner classes seems good to me. These were a disasterous
alternative to closures - done for the sake of backwards compatibility
of the class files.

The modern generic types are about equally messed up for much the same
reason (though the resulting class files don't seem to be very
backwards-compatible in practice at the moment).
 
T

Thomas Hawtin

Roedy said:
Is there distinction between <E> and <? extends E>?

Here's what you need to know.

// Illegal
List< Object> list = new ArrayList<String>();

// Legal
List<? extends Object> list = new ArrayList<String>();


// Legal
List< Object> list = new ArrayList<Object>();
list.add(new Integer(42));

// Illegal
List<? extends Object> list = new ArrayList<String>();
list.add(new Integer(42));


Seems quite simple to me.

You can't do that (straightforwardly) in C#2.0 or C++ (97).

Tom Hawtin
 
J

jan V

though the resulting class files don't seem to be very
backwards-compatible in practice at the moment.

"for the moment" ? ... clearly Sun will have to stick with how they've done
it for 1.5, because if not, then we're heading for a complete an utter
incompatibility chaos.. WITHIN Sun's sequence of implementations, and that
would be a disaster. I already think the -source and -target javac options
greatly complicate Java development.
 
J

jan V

Seems quite simple to me.
You can't do that (straightforwardly) in C#2.0 or C++ (97).

You know, recently I gained an insight into our industry which was triggered
by similar comments of the sort "Uh... I think it's simple."

The insight goes like this: programmers/engineers, let's say like yourself,
who are a good deal cleverer than Average (Programmer) Joe really are
problematic for the entire industry.

What?! Yes, just let me explain my theory...

Remember that software engineering research has highlighted massive
differences between average and great programmers (an order of magnitude or
more difference in speed and coding quality; which basically implies a
qualitative difference in brain power). The reason programmers like yourself
are problematic is because you can deal with vastly greater complexity than
average IT people.. which implies that the bulk of IT people are struggling
with anything "you lot" invent and write. This in turn means an unacceptable
percentage of all IT projects fail which in turn means [etc..etc..].

KISS, KISS, KISS !!

I advocate that "super programmers" who can juggle vastly more complex balls
than average guys can, should be banned, by management, from dragging the
average crowd into system complexity zones where the whole team will start
to drown.

Of course in real life it's almost always the opposite that happens: the
genius types lead (blindly) without caring much whether the average
programmers can fully keep up or not (some even take sadistic pleasure from
seeing "inferior" colleagues suffer), and because such team leaders are on
an intellectual high, they fail to see that their project is heading for
disaster.

Real genius team leaders would recognise their own genius as a danger for
the success of the project/team, and instead apply their genius to the
proactive reduction of system complexity, thus *effectively* leveraging the
human resource in his/her fellow TEAM members.

I recently worked with a team leader who was so full of himself that he kept
the entire design of the system (which was *very* complex) in his head, and
coded furiously without bothering to comment his code. I once said to him
that if he died (e.g. in a car accident - happens to many), that the entire
project would be jeopardized. He just smiled, shrugged, and carried on as if
I'd never opened my mouth.

My theory is therefore: people like this are a liability in a team
environment, not an asset.
 
T

Thomas Hawtin

jan said:
[Tom Hawtin wrote:]
Seems quite simple to me.

You can't do that (straightforwardly) in C#2.0 or C++ (97).


You know, recently I gained an insight into our industry which was triggered
by similar comments of the sort "Uh... I think it's simple."

I think what you need to know is straightforward. The technical ins and
outs don't meet that criteria. And hands up, I like to know where the
traps, pitfalls and corner cases are.
who are a good deal cleverer than Average (Programmer) Joe really are

I think it's more motivation than cleverness, although cleverness kind
of helps.
I advocate that "super programmers" who can juggle vastly more complex balls

Point of pedantry: It's usually the number, pattern and not opening your
mouth which is the problem. It's largely independent of the balls
(chainsaws excluded, but not knives and torches).
I recently worked with a team leader who was so full of himself that he kept
the entire design of the system (which was *very* complex) in his head, and
coded furiously without bothering to comment his code. I once said to him

Then he's a bad programmer.
My theory is therefore: people like this are a liability in a team
environment, not an asset.




In my experience the use of code implemented with wildcards is mostly
confined to infrastructure. Wildcards, extends and super form
polymorphism for generics. Infrastructure should be polymorphic. Indeed
it should bend over backwards to make sure that the bulk (industry
average) code can be as simple as possible. It should be written by good
programmers.

I think the way teams are typically organised is wrong. If you have,
say, two good programmers and ten industry (median) average programmers,
then your productivity would be less than that with just the first two.
That should probably impact on hiring and firing.

Now if you have a mix of good, very good and industry average
programmers what should you do? Obviously split the team. Keep all the
the averagers together and add a sacrificial good programmer to tutor
and keep order. The other (progress) team does all the gritty stuff and
a fair amount of the bulk work. Then the manager has to exercise the
soft skills keeping everyone happy, which keeps her out of the progress
teams way.

Tom Hawtin
 
T

Tim Tyler

jan V said:
though the resulting class files don't seem to be very
backwards-compatible in practice at the moment.

"for the moment" ? ... clearly Sun will have to stick with how they've done
it for 1.5, because if not, then we're heading for a complete an utter
incompatibility chaos. [...]

Retroweaver strongly suggests that a compiler *could* spit out class files
compatible with earlier versions of Java from source code written
with generics without too much difficulty - indeed that's what the old
generics compiler used to do.
 
J

jan V

Tor Iver Wilhelmsen said:
In clj.help: Sure. In clj.programmer: No way.

IMO KISS applies everywhere. From one-man projects to sending astronauts to
Mars.

In any engineering field, if engineers aren't consciously trying to prevent
complexity going through the roof, then failure will surely be the end
result. In our field, too often people are completely oblivious to
complexity-over-time dynamics for their project... and as we all know,
projects too often fail too (link?).
 
T

Thomas Hawtin

jan said:
IMO KISS applies everywhere. From one-man projects to sending astronauts to
Mars.

In any engineering field, if engineers aren't consciously trying to prevent
complexity going through the roof, then failure will surely be the end
result. In our field, too often people are completely oblivious to
complexity-over-time dynamics for their project... and as we all know,
projects too often fail too (link?).

I think KISS is the wrong principle here (the use of generic
wildcards/extend/super). The alternatives are to either copy and paste,
kludge, or add an unnatural, extra layer of indirection.

jan's point of view appears to be that "a bent coat-hanger will do instead".

Tom Hawtin
 
P

Patricia Shanahan

Tor said:
In clj.help: Sure. In clj.programmer: No way.

:)

I think the real issue is where to optimize for simplicity, and where to
optimize for functionality.

Make a piece of infrastructure simpler than it needs to be, and every
program that uses that piece of infrastructure collects extra
complexity. Optimize for smoothness in how the infrastructure appears to
the rest of the world, even at the expense of making its own
implementation a bit more complicated, and it simplifies everything that
uses it.

The JDK 1.5 generics seem to me like a case of optimizing for simplicity
in the implementation of the infrastructure, rather than in its use. It
should not be hard for experienced programmers to write warning-free code.

Patricia
 
T

Tim Tyler

[After looking at error messages from Java's generic types]
IMO KISS applies everywhere. From one-man projects to sending astronauts to
Mars.

In any engineering field, if engineers aren't consciously trying to prevent
complexity going through the roof, then failure will surely be the end
result. In our field, too often people are completely oblivious to
complexity-over-time dynamics for their project... and as we all know,
projects too often fail too (link?).

I think KISS is the wrong principle here (the use of generic
wildcards/extend/super). The alternatives are to either copy and paste,
kludge, or add an unnatural, extra layer of indirection. [...]

....or to use another language.
 
R

Raymond DeCampo

Tim said:
Generic types make Java a lot more complex.

The /way/ in which Sun added it makes it a lot more complex than was
necessary.

It is - nontheless - an improvement over Java without generic types, IMO.

The analogy with inner classes seems good to me. These were a disasterous
alternative to closures - done for the sake of backwards compatibility
of the class files.

The modern generic types are about equally messed up for much the same
reason (though the resulting class files don't seem to be very
backwards-compatible in practice at the moment).

Tim,

I thought you were sticking to 1.1 features only?

Ray
 
R

Roedy Green

A Collection<Car>, on the other hand, may
only contain Cars. It is an error to try to add a Truck to such a
collection.

I did an experiment the other night and JDK 1.5 let me add a Dalmatian
to a Dog ArrayList.

I should repeat that to be doubly sure. I was expecting it to reject
the Dalmatian which would then make the <? E> <E> distinction
meaningful.


--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
R

Roedy Green

Yes, but it's kind of subtle.

I Salaam you Chris. This is indeed subtle. How did you ever figure
this out?

What practical use then is a ArrayList<? extends Automobile>?

These are just templates, waiting to be filed my concrete classes?


I have used the syntax with Comparators, where it make sense that you
might use a more generic type for your Comparator than the type your
are storing in your ArrayLists, e.g. Comparator<? super T>


--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
R

Roedy Green

Collection<? extends Automobile>

Let me see if I follow:


Collection<? extends Automobile> a = new ArrayList<Automobile>( 10 );

a.add( new Automobile() );

a.add( new Car() ); // blocked


So strangely Collection<? extends Automobile> means the exact
opposite.

it means Collection<only Automobile no Cars or Trucks>



--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
T

Thomas Hawtin

(As a Car instance is not an instance of a Truck.)
I did an experiment the other night and JDK 1.5 let me add a Dalmatian
to a Dog ArrayList.

I should repeat that to be doubly sure. I was expecting it to reject
the Dalmatian which would then make the <? E> <E> distinction
meaningful.

Suppose we have:

List<Dog> dogs = ArrayList<Dog>
List<? extends Dog> someDogs = ArrayList<Terrier>();

Now if we try

dogs.add(new Dalmation());

That's fine. A Dalmation is a Dog. We could have written it as:

Dog dalmation = new Dalmation();
dogs.add(dalmation);

On the other hand

someDogs.add(new Dalmation()); // Disallowed at compile time.

A Dalmation in a Terrier list would be just wrong. The trouble is we
don't know enough about the bounds to work out what kind of dog we can
put in there. However we do know that everything in there is a dog.



Contrast this with how arrays work.

Dog[] dogs = new Dog[42];
Terrier[] terriers = new Terrier[13];
Dog[] someDogs = terriers;

Now try

dogs[0] = new Dalmation();

That is fine.

someDogs[0] = new Dalmation();

This compiles, but it doesn't work. We get an ArrayStoreException. If we
did:

Terrier terrier = terriers[0];

We wouldn't want to find a Dalmation in our Terrier.


Tom Hawtin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top