On 04/05/2012 11:04 PM, Stuart Marks wrote:

[...]


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

Yeah, probably something like "need to cast to raw in order to work around a limitation in the type system."

your English is better than mine :)


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.

I couldn't find it in Doug Lea's JSR166 repository, if that's what you were referring to.

Note that a similar code snippet appears in TimSort.java, extra local variable and all.

After a dig up session, Martin Buchholz proposes the patch from sources written by Josh
from the Android source repository.
see http://mail.openjdk.java.net/pipermail/core-libs-dev/2009-June/001937.html


I'm inclined to leave the @SW and extra local variable in place, on the off chance that there's some reason for having them that we're unaware of.

I agree.


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.

I assume you disagree with my preference leave unmaskNull() returning V, not with joining the lines at L337. :-)

yes.


I'm somewhat skeptical of making code changes now based on potential future benefits when/if generics become reified. This was discussed before; see

http://mail.openjdk.java.net/pipermail/jdk8-dev/2011-December/000454.html

In that message, John Rose said "If the best practices have to change, then we'll have to change that code again. Or maybe the retrofit strategy will have to take account of the existing code idioms. In any case, we'll cross that bridge when we get to it. (Coping with reification in this case is a decision to make tomorrow, not today.)"

I disagree with John. The main issue with generics nowadays is that
most of the people doesn't care about a cast to a type variable because
everybody knows about erasure. So codes are written with an implementation glitch in mind. Frankly, I don't know if reification will appear (yes it's a kind of magical) or not
but I think it's a sloppy path to not consider all casts as equals.

If unmaskNull return a V, the code of equals will upcast the value from Object to V
to just after downcast it from V to Object,
I think it's better that unmask to return Object and upcast it to V when it's necessary.


That said, if you think that unmaskNull() returning an Object makes sense, even after setting aside the reification issue, then I'm ok with this change.

see above.



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.

I'm more concerned with clarity of source code than extra local variables. We've left in extra locals before (ComparableTimSort.java above, and also in other files). And when we fix up code in response to warnings from static analyzers, we'll have more important things to deal with, I'm sure.

We are currently fixing warnings from a static analyzer :)

For me, letting an extra local variable is not a big deal because perf tests was already done on that code moreover if my memory is good, this extra local variable is not in the middle of the loops of the sort. Here, you want to add a new local variable and I know by experience that if you have no luck that can be enough for Hotspot to don't inline a method that was previously inlined. Even the proposed change as an impact, too long to explain here, but it can make the size of the method
a little bigger.
Anyway, you're right that clarity is more important than any of these details.


In any case I think your suggested rewrite is fine.

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.

Yes, same for these as well.

s'marks


cheers,
Rémi

Reply via email to