"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6
How To Ask Questions How To Answer Questions
Winston Gutkowski wrote:Is this new or am I missing something? (very possible )
Stephan van Hulst wrote:I think you're missing the fact that lists don't have a fixed capacity. ArrayList needs to be able to create new arrays, therefore its array field can't be of type E[], but must be of type Object[]. The clone() method wouldn't have provided the correct runtime type.
I wouldn't say the method was redundant. Unfriendly? Yes. I agree with Rob that now, with the introduction of functional interfaces, they could have given List a toArray() method that takes an array factory, rather than an array.
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
Rob Spoor wrote:I've checked the documentation, but nowhere does it say that the return type must be an actual Object[].
What I do miss though (in Collection) is public <T> T[] toArray(IntFunction<T[]>)...
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
Winston Gutkowski wrote:And the nice thing about it is that, since the internal array is now properly typed, the class requires no casts whatsoever, and type safety is guaranteed by generics. Currently, ArrayList defines an internal Object[] and explicitly casts (and presumably suppresses warnings for) every value returned from it.
A minor inconvenience is that, for methods that take an Object (like contains()), you should reeally do comparisons from the array value's standpoint - ie, elements[i].equals(o), rather than o.equals(elements[i]).
I've not come across array factories yet, but varargs seem to do just fine for this case.
What I'm wondering is if the behaviour I'm seeing is new, or if they've always worked this way. If so, I have a new respect for varargs.
Stephan van Hulst wrote:
A minor inconvenience is that, for methods that take an Object (like contains()), you should reeally do comparisons from the array value's standpoint - ie, elements[i].equals(o), rather than o.equals(elements[i]).
I don't understand what you mean. The two expressions should be equivalent.
I'm referring to Stream.toArray() accepting an array factory (in this case, IntFunction<A[]>), which Rob mentioned could have been added to the Collection interface. They could have added a parameterless toArray() method that returns a generic array, but this would have broken every collection implementation with a parameterless constructor (which, if they follow the advice in the Collection contract, includes ALL of them).
Yes, from the start
Actually, it led to some problems when the designers retrofitted methods like Arrays.asList()...
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
Winston Gutkowski wrote:If you use o.equals(elements[i]), I could supply a spurious subtype of CharSequence that allows comparison with Strings (illegal of course) to ArrayListX<String>.contains() and get a "false positive" match.
With elements[i].equals(o) that can't happen with either version, because I already know that elements[i] is a String.
Furthermore, I'd say that such a constructor would be applicable (and quite nice to have) for any existing collection.
Ain't programming amazing? You really do learn something new every day. I don't know how many times I've used varargs, but it never occurred to me to use them as an "array typer". I also wonder if it might not be possible to use the same technique to create a generic array generator, viz:
...
It should probably be added that this behaviour ONLY applies to constructors. If you try the same thing with a method, it returns an Object[].
I can't replicate the behaviour you describe, even if I assign toArray() output to an Object[]. It always prints out the contents for me.
Stephan van Hulst wrote:Switching the order just hides the fact that the program is bugged.
I would strongly discourage you from writing APIs like this though. ... It's in Effective Java: Use varargs judiciously.
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
Winston Gutkowski wrote:The one thing that bothers me is that I can't find any specific documentation about this behaviour in the JLS, even when I search for 'arity'; so it's possible that it's just a feature of Oracle's javac program. If you have any suggestions where to look, I'd be eternally grateful.
On the other hand it makes sense: When you call a constructor of a typed class, you supply the type either explicitly or implicitly, so there's no reason a compiler shouldn't be able to work out the specific type of array it should generate for a varargs parameter. With a method it's a little harder, since by the time the compiler gets around to parsing it, it may only know the erasure type of the class.
static (and possibly typed) methods?: Dunno, but I trust your findings. And again, the compiler probably has more to go on (like a target type) to work out what type of array is needed.
If the member is a variable arity method with arity n, then
for all i (1 ≤ i ≤ n-1), the i'th
argument of the method invocation is potentially
compatible with the type of the i'th parameter
of the method; and, where the nth parameter of the method
has type T[]
, one of the following is true:
The arity of the method invocation is equal to n-1.
The arity of the method invocation is equal to n, and
the nth argument of the method invocation is
potentially compatible with either T or
T[]
.
The arity of the method invocation is m, where m > n, and for all i (n ≤ i ≤ m), the i'th argument of the method invocation is potentially compatible with T.
SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6
How To Ask Questions How To Answer Questions
Stephan van Hulst wrote:Generics are handled the same for all methods, static or not, and constructors. Type erasure doesn't come into play.
When the compiler runs into generic varargs, it just creates a generic array, as if it had called new T[]{...} before passing it to the method.
The weird thing is that this completely ignores the entire reason we as programmers are not allowed to manually create generic arrays ourselves.
...
This makes me wonder why they didn't make the instantiation of a generic array emit a warning, instead of just forbidding it.
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
Rob Spoor wrote:ArrayList could never lose its parameter-less constructor while still being backward compatible. Although new Java code wouldn't have a problem (new ArrayList<>() would simply receive zero vararg elements), existing code will definitely break.
(It helps having programmed JNI a bit )
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
If m
is being
invoked with k ≠ n actual argument expressions, or, if
m
is being invoked with k = n actual argument expressions
and the type of the k'th argument expression is not assignment
compatible with T[]
, then the argument list (e1
, ...,
en-1
, en
, ..., ek
) is evaluated as if it were written as (e1
,
..., en-1
, new
|T[]
| {
en
, ..., ek
}
),
where |T[]
| denotes the erasure (§4.6)
of T[]
.
Stephan van Hulst wrote:So really, this means that the compiler just translates <X>call(a,b,c); to call(new X[] {a,b,c}); IF X is a reifiable type...
The designers did:..
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
Stephan van Hulst wrote:They probably thought that using T... was not appropriate, and I agree with them
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
Don't count your weasels before they've popped. And now for a mulberry bush related tiny ad:
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
|