stupid generics

G

Googmeister

My understanding is that the underlying reason is that arrays are
"covariant" but generics are not. In other words, String[] is a subtype
of
Comparable[], but List<String> is not a subtype of List<Comparable>.

In a world without generics, covariant arrays are useful, e.g., to
implement Arrays.sort(Comparable[]) and have it be callable with an
input of type String[]. But now that Java has generics, the usefulness
of covariant arrays is diminished, but we are stuck with them.
 
T

Thomas G. Marshall

Thomas Hawtin coughed up:
Thomas said:
Thomas Hawtin coughed up:
Roedy Green wrote:

...[rip]...


You don't need generics with arrays. Typing in built in properly.

Generics is a built in property of arrays. You don't need arrays of
generics.



That doesn't make any sense to me at all. In this example:

ArrayList<Apple>[] allGroves = new ArrayList<Apple>[100];

I would be asking for an array of ArrayLists's that each only take
Apples.
This would prevent someone from doing this by accident later:

allGroves[50] = new ArrayList<Orange>();

Regardless of whether or not the OP has modeled his particular issue
correctly, not having this ability seems an annoyance that /might/ not
have
been necessary.

What I was trying to say (extremely badly) is that arrays fit in with
the concept of genericity in that they have the property of being
generic. Unfortunately they do it with different (and less safe rules)
than the rest of the language.

Arrays are objects that maintain their own type contents, which is generic
behavior, sure. But in what way is this less safe than the rest of the
language? It is certainly far safer than generics in general in that arrays
exhibit this behavior at runtime as well.

Once we have something the wraps arrays,
then the only real need for arrays of references is for optimisation.

Sure, but he's not wrapping the array. He's attempting to have an array of
a type of a type.

....[rip]...
 
G

Googmeister

Thomas said:
Thomas Hawtin coughed up:
Thomas said:
Thomas Hawtin coughed up:

Roedy Green wrote:


...[rip]...


You don't need generics with arrays. Typing in built in properly.

Generics is a built in property of arrays. You don't need arrays of
generics.



That doesn't make any sense to me at all. In this example:

ArrayList<Apple>[] allGroves = new ArrayList<Apple>[100];

I would be asking for an array of ArrayLists's that each only take
Apples.
This would prevent someone from doing this by accident later:

allGroves[50] = new ArrayList<Orange>();

Regardless of whether or not the OP has modeled his particular issue
correctly, not having this ability seems an annoyance that /might/ not
have
been necessary.

What I was trying to say (extremely badly) is that arrays fit in with
the concept of genericity in that they have the property of being
generic. Unfortunately they do it with different (and less safe rules)
than the rest of the language.

Arrays are objects that maintain their own type contents, which is generic
behavior, sure. But in what way is this less safe than the rest of the
language?

One unsavory consequence of covariant arrays in Java is the
ArrayStoreException.

Object[] a = new String[10]; // OK
a[0] = "hello"; // OK
a[1] = new Integer(42); // a runtime error
 
T

Thomas G. Marshall

Roedy Green coughed up:

....[rip]...
public static void main ( String[] args )
{
ArrayList<String>[] stuff = new ArrayList<String>[ 10 ];
}
}

I feel embarrassed that Java's generics are so Mickey Mouse they don't
even integrate with arrays.


Yes. And I feel equally embarrassed, but am holding off most of my
condemnation of it until I get a better handle on how badly things would
have been had they added a runtime generic type.

Please refer to my new thread in comp.lang.java.advocacy:

Subject: runtime generics: Could JVM's solve the backward incompatibility?
 
T

Thomas G. Marshall

Googmeister coughed up:
Thomas said:
Thomas Hawtin coughed up:
....[rip]...
Arrays are objects that maintain their own type contents, which is
generic
behavior, sure. But in what way is this less safe than the rest of the
language?

One unsavory consequence of covariant arrays in Java is the
ArrayStoreException.

Object[] a = new String[10]; // OK
a[0] = "hello"; // OK
a[1] = new Integer(42); // a runtime error

That's precisely the protection you /want/ at runtime. However, I believe
that your complaint with this is that it isn't something caught at
compile-time?
 
T

Tor Iver Wilhelmsen

zero said:
When you use this class, for example;

GenericContainer<MyClass> c = new GenericContainer<MyClass>(5);

The problem with C++'s approach is that you don't use that class, you
use that *template*. There is no base GenericContainer class to cast
to, since there is no common base class Object.

It's quite easy to make a template system of your own, e.g. using Ant
to generate the concrete classes, if you find that to be sufficient.
 
T

Tor Iver Wilhelmsen

Thomas G. Marshall said:
Yes. And I feel equally embarrassed, but am holding off most of my
condemnation of it until I get a better handle on how badly things
would have been had they added a runtime generic type.

Are you referring to Smalltalk's message-based structure and
#doesNotUnderstand:aMessage if a given object does not understand an
attempted method invocation? That would be keen, yes. But then, having
Smalltalk win the language wars would have been nice, but thanks to
expensive licenses and infighting it was not to be.

(I flatly refuse to read clj.advocacy, you see. :) )
 
G

Googmeister

Thomas said:
Googmeister coughed up:
Thomas said:
Thomas Hawtin coughed up:
...[rip]...
What I was trying to say (extremely badly) is that arrays fit in with
the concept of genericity in that they have the property of being
generic. Unfortunately they do it with different (and less safe rules)
than the rest of the language.

Arrays are objects that maintain their own type contents, which is
generic
behavior, sure. But in what way is this less safe than the rest of the
language?

One unsavory consequence of covariant arrays in Java is the
ArrayStoreException.

Object[] a = new String[10]; // OK
a[0] = "hello"; // OK
a[1] = new Integer(42); // a runtime error

That's precisely the protection you /want/ at runtime. However, I believe
that your complaint with this is that it isn't something caught at
compile-time?

Yes, my complaint is that you have to wait until runtime to notice
such things. If arrays weren't covariant, Java could detect such
errors at compile time.
 
T

Thomas G. Marshall

Googmeister coughed up:
Thomas said:
Googmeister coughed up:
Thomas G. Marshall wrote:
Thomas Hawtin coughed up:
...[rip]...

What I was trying to say (extremely badly) is that arrays fit in with
the concept of genericity in that they have the property of being
generic. Unfortunately they do it with different (and less safe rules)
than the rest of the language.

Arrays are objects that maintain their own type contents, which is
generic
behavior, sure. But in what way is this less safe than the rest of the
language?

One unsavory consequence of covariant arrays in Java is the
ArrayStoreException.

Object[] a = new String[10]; // OK
a[0] = "hello"; // OK
a[1] = new Integer(42); // a runtime error

That's precisely the protection you /want/ at runtime. However, I
believe
that your complaint with this is that it isn't something caught at
compile-time?

Yes, my complaint is that you have to wait until runtime to notice
such things. If arrays weren't covariant, Java could detect such
errors at compile time.

ok.

--
Enough is enough. It is /not/ a requirement that someone must google
relentlessly for an answer before posting in usenet. Newsgroups are for
discussions. Discussions do /not/ necessitate prior research. If you are
bothered by someone asking a question without taking time to look something
up, simply do not respond.
 
T

Thomas Hawtin

Thomas said:
Thomas Hawtin coughed up:


Arrays are objects that maintain their own type contents, which is generic
behavior, sure. But in what way is this less safe than the rest of the
language? It is certainly far safer than generics in general in that arrays
exhibit this behavior at runtime as well.

A program that does not generate mandatory warnings should only generate
ClassCastExceptions at explicit casts. I think that is significant for a
strong, statically typed language. Without that we might as well all use
Smalltalk.

Warning-free, castless programs using arrays of references can generate
runtime exceptions in quite nasty ways.
Sure, but he's not wrapping the array. He's attempting to have an array of
a type of a type.

Quite. He shouldn't be. Dumping now unnecessary uses of arrays is part
of upgrading to generics.

Tom Hawtin
 
T

Thomas Hawtin

Ross said:

Hmm, that's interesting. In that, they give the reason for avoiding
this kind of thing as

"This restriction is necessary to avoid situations like:

List<String>[] lsa = new List<String>[10]; // not really allowed
Object o = lsa;
Object[] oa = (Object[]) o;

This cast is unnecessary, as things stand.
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li; // unsound, but passes run time store check
String s = lsa[1].get(0); // run-time error - ClassCastException

If arrays of parameterized type were allowed, the example above would
compile without any unchecked warnings, and yet fail at run-time."

Perhaps it's just me, but I don't really see much difference between
that and:

List<String> lsa = new ArrayList<String>(); // ... but this is.
Object o = lsa;
Object[] oa = (Object[]) o;

You think this is going to work?
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li; // still unsound, and *no* runtime store check
String s = lsa.get(0); // run-time error - ClassCastException

Have I missed something, or is it just a pretty poor excuse. If the

You've missed something.

Tom Hawtin
 
T

Thomas Hawtin

Ross said:
I think the current system achieves a reasonable balance between
flexibility on the one hand, and performance and backward compatibility
on the other. I'm not saying it's perfect (*far* from it), but I think
that if they had gone the bytecode-generation route it would have been
a lot less useful - an unrestricted number of new classes being
generated on the fly, entirely 'under the hood' (i.e. outside your
app's control). It might make even basic operations entirely
unpredictable in terms of time, compromise security, and make it much
more difficult to implement custom classloading strategies. I expect
it's likely that the generics team started with something like above,
given that bytecode generation is used elsewhere in the platform, and
then worked backward to try to make it performant and compatible.

C++-style code generation would have been nuts. (C++ templates can share
object code, but most compilers do not do so.)

The alternative I prefer would insert a layer of indirection between
objects and classes. Most problems in computer science can be resolved
by an additional layer of indirection.

Instead of each object having a pointer to the details of its runtime
implementation class, it would have a pointer to a structure containing
a pointer to the old implementing class details and its runtime generic
types. Code would be shared, as before, and runtime casts at point of
use. (You could imagine type-specific optimisation variants on this theme.)

Old code implementing new types would simply have blanks for the generic
information. When it comes to casting generic types, anything blank
would just pass, to be checked at use. But for new implementations,
types can be checked and used for reflection based activities.

Tom Hawtin
 
T

Thomas G. Marshall

Thomas Hawtin coughed up:
A program that does not generate mandatory warnings should only generate
ClassCastExceptions at explicit casts. I think that is significant for a
strong, statically typed language. Without that we might as well all use
Smalltalk.

Warning-free, castless programs using arrays of references can generate
runtime exceptions in quite nasty ways.


Quite. He shouldn't be. Dumping now unnecessary uses of arrays is part
of upgrading to generics.

That's still the rub. In /what/ way is what he is attempting an example of
an unnecessary use of arrays?

As I said elsewhere, he wants something akin to this. An array of 100 apple
groves, each grove an arraylist of apples.

ArrayList<Apple>[] allGroves = new ArrayList<Apple>[100];

to prevent someone from doing this by accident later:

allGroves[50] = new ArrayList<Orange>();

Why should he want to avoid this?


--
I've seen this a few times--Don't make this mistake:

Dwight: "This thing is wildly available."
Smedly: "Did you mean wildly, or /widely/ ?"
Dwight: "Both!", said while nodding emphatically.

Dwight was exposed to have made a grammatical
error and tries to cover it up by thinking
fast. This is so painfully obvious that he
only succeeds in looking worse.
 
T

Thomas Hawtin

Thomas said:
That's still the rub. In /what/ way is what he is attempting an example of
an unnecessary use of arrays?

An array is unnecessary because List would have done instead. It's quite
unnecessary to drop down to a less able type. Reference arrays bad.
As I said elsewhere, he wants something akin to this. An array of 100 apple
groves, each grove an arraylist of apples.

ArrayList<Apple>[] allGroves = new ArrayList<Apple>[100];

That should normally be written:

List<List<Apple>> allGroves = new ArrayList<List<Apple>>(100);

Or better:

List<Grove> allGroves = new ArrayList<Grove>(100);

That also has the advantage that there are no uninitialised
elements/components hanging around.

Tom Hawtin
 
T

Thomas G. Marshall

Thomas Hawtin coughed up:
Thomas said:
That's still the rub. In /what/ way is what he is attempting an example
of
an unnecessary use of arrays?

An array is unnecessary because List would have done instead. It's quite
unnecessary to drop down to a less able type. Reference arrays bad.
As I said elsewhere, he wants something akin to this. An array of 100
apple
groves, each grove an arraylist of apples.

ArrayList<Apple>[] allGroves = new ArrayList<Apple>[100];

That should normally be written:

List<List<Apple>> allGroves = new ArrayList<List<Apple>>(100);

Or better:

List<Grove> allGroves = new ArrayList<Grove>(100);

That also has the advantage that there are no uninitialised
elements/components hanging around.


I disagree with your overall notion. This is just a statement that he could
replace arrays with arraylists, which should not be his only recourse here.
 
R

Ross Bamford

Ross said:
Hmm, that's interesting. In that, they give the reason for avoiding
this kind of thing as
"This restriction is necessary to avoid situations like:
List<String>[] lsa = new List<String>[10]; // not really allowed
Object o = lsa;
Object[] oa = (Object[]) o;

This cast is unnecessary, as things stand.

I know, but this is Sun's code. It's 'the reason they didn't implement
generic arrays', according to the PDF link Zero posted. I just quoted it
as context for:
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li; // unsound, but passes run time store check
String s = lsa[1].get(0); // run-time error - ClassCastException
If arrays of parameterized type were allowed, the example above
would
compile without any unchecked warnings, and yet fail at run-time."
Perhaps it's just me, but I don't really see much difference between
that and:
List<String> lsa = new ArrayList<String>(); // ... but this is.
Object o = lsa;
Object[] oa = (Object[]) o;

You think this is going to work?

No. I was saying that, I didn't see that much difference - the second
example (which is just a slightly modified version of the original)
compiles cleanly with no unchecked warning, but throws CCE at runtime.
Therefore, the reason given for avoiding generic array instantiation is
pretty weak, given that it can happen easily anyway, no? Surely the
convenience would have outweighed the risks?
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li; // still unsound, and *no* runtime store
check
String s = lsa.get(0); // run-time error - ClassCastException
Have I missed something, or is it just a pretty poor excuse. If the

You've missed something.

Tom Hawtin
 
T

Thomas Hawtin

Ross said:
Ross said:
List<String>[] lsa = new List<String>[10]; // not really allowed
Object o = lsa;
Object[] oa = (Object[]) o;
Perhaps it's just me, but I don't really see much difference
between that and:
List<String> lsa = new ArrayList<String>(); // ... but this is.
Object o = lsa;
Object[] oa = (Object[]) o;


You think this is going to work?

No. I was saying that, I didn't see that much difference - the second
example (which is just a slightly modified version of the original)
compiles cleanly with no unchecked warning, but throws CCE at runtime.

Not much difference?? In the first example an array is being cast to an
array (the particular example can be done without the explicit cast).
The second is casting from an *array* to a *List*. Well, duh.
Therefore, the reason given for avoiding generic array instantiation is
pretty weak, given that it can happen easily anyway, no?
Drivel.

Surely the
convenience would have outweighed the risks?

My idea of convenience includes compatible semantics.

Tom Hawtin
 
B

Brendan Guild

Googmeister wrote in
Googmeister coughed up:
One unsavory consequence of covariant arrays in Java is the
ArrayStoreException.

Object[] a = new String[10]; // OK
a[0] = "hello"; // OK
a[1] = new Integer(42); // a runtime error

That's precisely the protection you /want/ at runtime. However, I
believe that your complaint with this is that it isn't something
caught at compile-time?

Yes, my complaint is that you have to wait until runtime to notice
such things. If arrays weren't covariant, Java could detect such
errors at compile time.

But at the cost of greatly reducing the power of arrays and restricting
a perfectly reasonable operation on arrays. It would be just silly to
forbid us from performing operations on abstract arrays without
declaring the type of the array.

With covariant arrays I can write a procedure to reverse the order of
the elements and I won't have to rewrite it for every class that I might
have an array for. Functional languages devote lots of syntax to what
they call 'polymorphism' just to get this kind of power. For them it
feels special; for us it comes naturally, so long as we don't fight it.

The reason that ArrayStoreExceptions are so rare is that the programming
error they represent is so obvious and natural that people almost never
make it.
 
G

Googmeister

Brendan said:
Googmeister wrote in
Googmeister coughed up:
One unsavory consequence of covariant arrays in Java is the
ArrayStoreException.

Object[] a = new String[10]; // OK
a[0] = "hello"; // OK
a[1] = new Integer(42); // a runtime error

That's precisely the protection you /want/ at runtime. However, I
believe that your complaint with this is that it isn't something
caught at compile-time?

Yes, my complaint is that you have to wait until runtime to notice
such things. If arrays weren't covariant, Java could detect such
errors at compile time.

But at the cost of greatly reducing the power of arrays and restricting
a perfectly reasonable operation on arrays. It would be just silly to
forbid us from performing operations on abstract arrays without
declaring the type of the array.

With covariant arrays I can write a procedure to reverse the order of
the elements and I won't have to rewrite it for every class that I might
have an array for.

Sure, I assume that was the original motivation for covariant
arrays (as I indicated earlier with an Arrays.sort example), and now
Java is stuck with it. But if you were designing a type system from
scratch with generics, why not let generics be the way to accomplish
The reason that ArrayStoreExceptions are so rare is that the programming
error they represent is so obvious and natural that people almost never
make it.

I have to agree that I've never encountered one myself. But I know that
every time I assign something to an array, it is (needlessly) checked
at
run-time, hopefully by an optimizing compiler.
 

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

Similar Threads

generics puzzle 57
How to sort a CSV file with merge sort JAVA 7
Generics and for each 12
can this be done with generics? 32
subclassing and generics 19
Generics annoyance 18
JDK5 Generics 6
Generics 12

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,216
Latest member
topweb3twitterchannels

Latest Threads

Top