Code Review Request: 7157893: Warnings Cleanup in java.util.*
Rémi Forax
forax at univ-mlv.fr
Thu Apr 5 08:12:55 UTC 2012
On 04/05/2012 09:08 AM, Stuart Marks wrote:
> Hi Kurchi, Remi,
>
> Sorry for the delay in this review. There were a lot of files to go
> through, and I wanted to dig up some history as well. (I've also been
> busy....) There are no real major issues, but I wanted to clear a
> couple things up and possibly file issues for further work.
>
> Comments follow on a file-by-file basis.
>
>
>
>
> src/share/classes/java/util/Arrays.java
> ----------------------------------------------------------------------
>
> In this file there are several places where @SuppressWarnings is
> placed on a method, which is rather a broad scope. In some cases like
> mergeSort() it's probably not worth extracting expressions into
> declarations just to narrow the scope. In other cases there's a
> declaration handy already, for example those listed below. It would be
> good to narrow @SW to these declarations.
>
> - L2251 declaration of T[] copy
so you want to move the @SupressWarnings on the local variable like this:
public static <T,U> T[] copyOf(U[] original, int newLength, Class<?
extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(),
newLength);
...
I'm Ok this that.
>
> - L2520 declaration of T[] copy
Ok too.
>
>
>
> src/share/classes/java/util/Collections.java
> ----------------------------------------------------------------------
>
> - L1408 this casts to a raw Set in the parameter to super(). There
> was some discussion about this earlier [1], [2]. David Holmes had
> suggested casting to Set<? extends Map.Entry<K,V>> but this still
> generates an unchecked warning. I haven't been able to figure out a
> cast that doesn't generate an unchecked warning (and I suspect Remi
> was in the same situation).
You can't in fact. You have to explain to the type system that because
the Set is unmodifiable,
you can use it in a covariant way, there is no way to do that in Java
because you can't put
variance annotation at declaration site, but even with that you also
need a way to say that
all methods that take an E are not implemented and reflect that to the
type-system.
> So we might as well leave the cast to the raw type. For me, this only
> generates an unchecked warning, not a rawtypes warning, so maybe we
> can omit suppression of rawtypes warnings.
Eclipse requires the two declarations.
This is, in my opinion, a bug of Eclipse, I will report it but I would
prefer to let the two declarations for now.
>
> I was going to suggest adding a comment to explain this but I suspect
> that would make this code even more confusing.
just perhaps something saying it's a known limitation of the type-system
>
> [1]
> http://mail.openjdk.java.net/pipermail/jdk8-dev/2011-December/000497.html
>
> [2]
> http://mail.openjdk.java.net/pipermail/jdk8-dev/2011-December/000501.html
>
>
>
> src/share/classes/java/util/ComparableTimSort.java
> ----------------------------------------------------------------------
>
> - L117 there's a @SuppressWarnings("UnnecessaryLocalVariable") and
> the local variable newArray really does seem unnecessary. Why not just
> assign tmp the result of new Object[]?
>
> - same at L866
>
> Is there any reason to keep the local variables, for example, if this
> code came from an upstream repo?
As far as I know, this code was written by Josh and comes from the Doug
repository.
>
>
>
> src/share/classes/java/util/Currency.java
> ----------------------------------------------------------------------
>
> - L404 I don't think the @SuppressWarnings here is necessary, as
> there is @SW inside this method that suppresses a narrower scope. See
> [3]. I didn't see any other warnings in this method that needed
> suppression.
You're right, it's a merge issue for me.
The annotation should be removed.
>
> [3]
> http://mail.openjdk.java.net/pipermail/jdk8-dev/2011-December/000469.html
>
>
>
> src/share/classes/java/util/EnumMap.java
> ----------------------------------------------------------------------
>
> - I'm not sure why unmaskNull() was changed to return Object instead
> of V. There are bunch of places elsewhere in the file where it's used
> and its return value is cast to (V), generating unchecked warnings at
> those points. It seems to me that it would be preferable to have
> unmaskNull() return V and have @SW on its declaration than to have @SW
> sprinkled in a bunch of places elsewhere in the file. This makes
> unmaskNull() asymmetric with maskNull(), which returns Object, but
> that's the way the file was originally (so maybe that's OK).
>
> - L337 lines can be joined now that wildcards are shorter
I disagree, the casts should be put where they are needed and you don't
need them for equals and remove
which work with an Object and do not require a V.
If one day generics are reified, unlike today, the VM will have to
execute some code for these casts,
so I prefer to have them only if it's needed even if you have to put
more @SW.
>
>
>
> src/share/classes/java/util/HashMap.java
> ----------------------------------------------------------------------
>
> - L393 a @SuppressWarnings is on the declaration of the for-loop
> index variable? This is somewhat unorthodox. I think it would be
> better to put the @SW on a new local variable just before the for-loop:
>
> @SuppressWarnings("unchecked")
> Entry<K,V> first = (Entry<K,V>)table[i];
> for (Entry<K,V> e = first; e != null; e = e.next) {
>
> - L413 similar to above
The unorthodox thing here is the fact that in Java you can declare a
variable in a for loop.
If you don't want that, I prefer
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)table[i];
for (; e != null; e = e.next) {
it extends the scope of the variable but it will not be flagged by
static bytecode analyzers
as an unneeded local variable.
>
> - L442 Oooh, Entry<?,V> -- a half-wildcard! ("Is this a feral type?"
> -- Joe Darcy)
yes, a kind of semi-domesticated type :)
> This is interesting and unusual and inconsistent with the use of
> Entry<K,V> in the other put*() methods, but it actually makes sense in
> this case. It's worth a comment that explains that it's this way
> because e.key is explicitly used as an Object, not as type K.
>
>
>
> src/share/classes/java/util/Hashtable.java
> ----------------------------------------------------------------------
>
> - L440, L479, L703, L1107 more cases of @SW on a for loop variable;
> change as noted above
so same as above.
>
>
>
> src/share/classes/java/util/PropertyPermission.java
> ----------------------------------------------------------------------
>
> - L599 this is another case of "laundering" a conversion through a
> raw type (similar to Collections.java above), as we can't directly
> convert an Enumeration<PropertyPermission> to Enumeration<Permission>.
> As Remi noted in [4] this conversion wouldn't be necessary if
> Collections.enumeration() method were changed to take Collection<?
> extends T> instead of Collection<T>. But that's an API change and
> should be handled separately. I'll file a bug on this.
>
> Meanwhile leaving the cast to raw is probably reasonable. There should
> be a comment that mentions the inability to convert directly to
> Enumeration<Permission>. This generates an unchecked warning, so that
> should be suppressed too.
Ok.
>
> [4]
> http://mail.openjdk.java.net/pipermail/jdk8-dev/2011-December/000488.html
>
>
> Thanks!!
>
> s'marks
many thanks too.
Rémi
More information about the core-libs-dev
mailing list