Java 5 Generics Question

S

Steven

I am trying to define an array of vectors.
For example:

Vector<Object>[] data = new Vector[4];

The preceeding works with warnings.
Trying:

Vector<Object>[] data = new Vector<Object>[4];

Fails with errors.
What is the proper way to define an array of Vector<Object> ?

Thanks,
Steve
 
P

Peter Sestoft

Steven said:
I am trying to define an array of vectors.
For example:

Vector<Object>[] data = new Vector[4];

The preceeding works with warnings.
Trying:

Vector<Object>[] data = new Vector<Object>[4];

Fails with errors.
What is the proper way to define an array of Vector<Object> ?

You cannot (in Java 5.0). The reason is that there's no way the array
element assignment check at data = ... could be performed, because
there is no runtime representation of the array element type
Vector<Object>.

Instead use array lists, as in:

ArrayList<Vector<Object>> data = new ArrayList<Vector<Object>>();

WARNING: Technical information, not flame bait, ahead:

This is one of the things that work a little better in
C#/CLI 2.0: the runtime supports exact type instances of generic
types, and therefore you can create an array whose element type is a
type instance of a generic type.

Peter
 
T

Thomas G. Marshall

Peter Sestoft coughed up:
Steven said:
I am trying to define an array of vectors.
For example:

Vector<Object>[] data = new Vector[4];

The preceeding works with warnings.
Trying:

Vector<Object>[] data = new Vector<Object>[4];

Fails with errors.
What is the proper way to define an array of Vector<Object> ?

You cannot (in Java 5.0). The reason is that there's no way the array
element assignment check at data = ... could be performed, because
there is no runtime representation of the array element type
Vector<Object>.

Instead use array lists, as in:

ArrayList<Vector<Object>> data = new ArrayList<Vector<Object>>();

WARNING: Technical information, not flame bait, ahead:

This is one of the things that work a little better in
C#/CLI 2.0: the runtime supports exact type instances of generic
types, and therefore you can create an array whose element type is a
type instance of a generic type.

Peter



Depending upon your point of view, sun really shot java in the kneecaps by
trying to keep generics so backward/forward compatible. They opted for the
weakest possible way to implement them, which is to use erasure. The
information just doesn't exist at runtime, which is a shame really. It
would have been The Right Way to Do It (tm) IMHO.





--
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 G. Marshall

Peter Sestoft coughed up:
Steven said:
I am trying to define an array of vectors.
For example:

Vector<Object>[] data = new Vector[4];

The preceeding works with warnings.
Trying:

Vector<Object>[] data = new Vector<Object>[4];

Fails with errors.
What is the proper way to define an array of Vector<Object> ?

You cannot (in Java 5.0). The reason is that there's no way the array
element assignment check at data = ... could be performed, because
there is no runtime representation of the array element type
Vector<Object>.



My other point aside, which addresses runtime info in general, I do have a
question about this particular answer of yours. Why do array genericism
/strictly speaking/ require that the type information exist at runtime?
Erasure give us nothing more than compile-time checks anyway, and such
checks could certainly be performed on the element assignment:

data = ....

that you pointed out. No?


Instead use array lists, as in:

ArrayList<Vector<Object>> data = new ArrayList<Vector<Object>>();

WARNING: Technical information, not flame bait, ahead:

This is one of the things that work a little better in
C#/CLI 2.0: the runtime supports exact type instances of generic
types, and therefore you can create an array whose element type is a
type instance of a generic type.

Peter



--
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.
 
P

Peter Sestoft

Thomas G. Marshall said:
You cannot (in Java 5.0). The reason is that there's no way the array
element assignment check at data = ... could be performed, because
there is no runtime representation of the array element type
Vector<Object>.


My other point aside, which addresses runtime info in general, I do have a
question about this particular answer of yours. Why do array genericism
/strictly speaking/ require that the type information exist at runtime?
Erasure give us nothing more than compile-time checks anyway, and such
checks could certainly be performed on the element assignment:

data = ....

that you pointed out. No?


The reason is that array type B[] is considered a subtype of array
type A[] when B is a subtype of A (and A and B are reference types).
This holds in Java as well as C#.

This so-called array type co-variance rule is unsound unless you have
a runtime check at every array element assignment. This check
requires exact types at runtime (which the JVM doesn't have for types
constructed from generic types).

Since ArrayList<B> is not a subtype of ArrayList<A> even though B is a
subtype of A, such checks are not needed for assignment to array list
elements.

Peter
 
T

Thomas G. Marshall

Peter Sestoft coughed up:
"Thomas G. Marshall"
You cannot (in Java 5.0). The reason is that there's no way the
array element assignment check at data = ... could be performed,
because there is no runtime representation of the array element type
Vector<Object>.


My other point aside, which addresses runtime info in general, I do
have a question about this particular answer of yours. Why do array
genericism /strictly speaking/ require that the type information
exist at runtime? Erasure give us nothing more than compile-time
checks anyway, and such checks could certainly be performed on the
element assignment:

data = ....

that you pointed out. No?


The reason is that array type B[] is considered a subtype of array
type A[] when B is a subtype of A (and A and B are reference types).
This holds in Java as well as C#.


In what way is this true? Is this specified somehow in the JLS? It seems
like a strict violation of type inheritance.
 
J

John C. Bollinger

Thomas said:
Peter Sestoft coughed up:
[...]
The reason is that array type B[] is considered a subtype of array
type A[] when B is a subtype of A (and A and B are reference types).
This holds in Java as well as C#.


In what way is this true? Is this specified somehow in the JLS? It seems
like a strict violation of type inheritance.

I don't know about C#, but for Java, in the strictest sense, it isn't
true: all array types in Java have Object as their direct superclass
(JLS2 10.8). Java goes to considerable effort to give the appearance
that it *is* true, however, by providing for widening (JLS2 5.1.4) and
narrowing (JLS2 5.1.5) reference conversions among array types. The
former can be applied in assignment (JLS2 5.2), method invocation (JLS2
5.3), and casting (JLS2 5.5) contexts; the latter can be applied only in
casting contexts. The instanceof operator understands these conversions
too, and they are explicitly accommodated by the relevant methods of
class Class, such as Class.isAssignableFrom(Class) and
Class.isInstance(Object) (see the API docs).

Practically speaking, then, it is almost always fine to operate as if
Peter's assertion were rigorously correct.
 
T

Thomas G. Marshall

John C. Bollinger coughed up:
Thomas said:
Peter Sestoft coughed up:
[...]
The reason is that array type B[] is considered a subtype of array
type A[] when B is a subtype of A (and A and B are reference types).
This holds in Java as well as C#.


In what way is this true? Is this specified somehow in the JLS? It
seems like a strict violation of type inheritance.

I don't know about C#, but for Java, in the strictest sense, it isn't
true: all array types in Java have Object as their direct superclass
(JLS2 10.8). Java goes to considerable effort to give the appearance
that it *is* true, however, by providing for widening (JLS2 5.1.4) and
narrowing (JLS2 5.1.5) reference conversions among array types. The
former can be applied in assignment (JLS2 5.2)


{Screeching brakes}. Earth shattering "huh".

The relevent parts of the JLS2 5.2 example is here:

int[] a = new int[3];
// Assignments to variables of array type:
byte[] b = new byte[4];
a = b; // error: these are not arrays
// of the same primitive type
Point3D[] p3da = new Point3D[3];
Point[] pa = p3da; // ok: since we can assign a
// Point3D to a Point
p3da = pa; // error: (cast needed) since a Point
// can't be assigned to a Point3D

I find that last part alarming. It caught me entirely by surprise. I
literally had no idea that java would allow this. I would have felt better
if they had established Object <|--- (array type) and left it at that.

{shudder} What they've done IMO is tantamount to saying:

ArrayList of Object<|--- ArrayList of Point <|--- ArrayList of Point3D

Or even:

class A { Object o = new Object(); }
class B { JComponent jc = new JComponent(); }
class C { JButton jb = new JButton(); }

and claimed: A <|--- B <|--- C
 
C

Chris Uppal

Thomas said:
{shudder} What they've done IMO is tantamount to saying:

ArrayList of Object<|--- ArrayList of Point <|--- ArrayList of Point3D

I don't like it much myself, but I don't think it's really as bad as all that.
Ugly, yes, but not quite unforgivable.

For one thing it has a practical purpose: without the looser-than-expected
rules, it would not be possible to provide generic array operations like
java.util.Arrays.sort(Object[]).

For another thing, the fact that you -- an experienced Java programmer --
didn't know that this blemish existed is evidence that it doesn't in fact cause
significant problems. And the lack of regular/incessant discussion on the
point in this ng is stronger evidence for the same thing. (Compare the cases
of java.io.InputStream.read(byte[]) and available(), which /do/ cause
problems -- to the point of tedium.)

Perhaps you would find it less bothersome if you didn't gloss it as a subclass
relationship, but took the Java spec's language seriously: Point3D[] is /not/
a subclass of Point[] in any sense, however the rules about substitutability
have been extended to allow some cases that are not covered by subclass
relationships. The effect is that Java's type system doesn't exactly coincide
with the inheritance tree -- but then it wouldn't do so even without this
special-case (consider private methods for instance). Type ~= class. not even
in Java.

-- chris
 
T

Thomas G. Marshall

Chris Uppal coughed up:
I don't like it much myself, but I don't think it's really as bad as
all that. Ugly, yes, but not quite unforgivable.


Well {exasperated sigh}, the minute after I posted, I wanted to take it
back, but was pulled away from my system, as luck would have it, and I've
been chomping at the bit to get back to this thread ever since.

Of course I've designed subsystems with methods that take actual array
parameters via common superclass array formal parameters. Object[] is the
obvious one. I've often just needed the array to come in as an Object as
well, for the odd cases where it is advantageous take either array and
non-array and do RTTI to figure out what to do.

I'm humiliated to admit that, for /some reason/, this just didn't sink in as
a Object[] to Thing[] narrowing/widening relationship when reading the JLS.
Something about it spooked the purist part of me. {palms-up shrug}

Very sorry for the WOT.



For one thing it has a practical purpose: without the
looser-than-expected rules, it would not be possible to provide
generic array operations like java.util.Arrays.sort(Object[]).

For another thing, the fact that you -- an experienced Java
programmer -- didn't know that this blemish existed is evidence that
it doesn't in fact cause significant problems.

I did, but forgot that I did. :) And no, I don't see it causing
significant problems...


....[rip]...
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top