Java Forum / General / April 2006
Warnings and collections
Patricia Shanahan - 23 Apr 2006 07:00 GMT I'm picking up a project I last worked on about a year, and one JDK version, ago. It makes extensive use of java.util collections.
I just did a rebuild, and got 100 "Type safety" warnings. It used to be warning-free.
My options seem to be:
1. Modify the source code to use generics, spending time making changes that are not really relevant to my current project.
2. Live with the warnings, and the consequential risk that I'll miss a warning that does mean something.
3. Go back to JDK 1.4, and not use e.g. generics in any new code.
4. Something else? If so, what?
Has anyone found a good solution to this problem? If not, any advice on which less-than-desirable compromise to choose?
Thanks,
Patricia
hiwa - 23 Apr 2006 07:33 GMT javac -source 1.4 Xyz.java
hilz - 23 Apr 2006 07:53 GMT > javac -source 1.4 Xyz.java But this will prevent the use of generics in new code.
In order to be able to use generics in new code, warnings can be suppressed using annotations:
@SuppressWarnings("unchecked")
see: http://java.sun.com/docs/books/tutorial/java/javaOO/annotations.html
Missaka Wijekoon - 23 Apr 2006 17:39 GMT > I'm picking up a project I last worked on about a year, and one JDK > version, ago. It makes extensive use of java.util collections. [quoted text clipped - 20 lines] > > Patricia Patricia,
If the company or persons using the project has *no issue* in using JDK 1.5, I would go ahead and fix the type safety warnings because:
1. a year or more later, the code will be easier to maintain. 2. generics are generally a good idea that helps the programmer avoid future type casting mistakes. That's worth a lot. 3. you may spot a yet undiscovered bug.
Cheers, Missaka
Patricia Shanahan - 23 Apr 2006 17:48 GMT >> I'm picking up a project I last worked on about a year, and one JDK >> version, ago. It makes extensive use of java.util collections. [quoted text clipped - 33 lines] > Cheers, > Missaka It's part of my academic research, so I am, in effect, my own customer. However, I'm also my own project manager, responsible for prioritizing changes, and a firm believer in "If it ain't broke, don't fix it.".
Patricia
Oliver Wong - 25 Apr 2006 21:32 GMT >> I'm picking up a project I last worked on about a year, and one JDK >> version, ago. It makes extensive use of java.util collections. [quoted text clipped - 4 lines] > If the company or persons using the project has *no issue* in using JDK > 1.5, I would go ahead and fix the type safety warnings because: [...]
> 3. you may spot a yet undiscovered bug. This happened to us. We had this big project that used lots of collections back when 1.4 was the latest version of Java. Our project lead is a big fan of using the latest and greastest versions of everything, so when Java 1.5 came out, we immediately switched over, yielding lots of warnings.
We generally ignored the warnings for the most part. When we had to revisit and update a given class, that's when we'd spend the time to actually update the code to use generics.
Over the process of slowly converting the code, we've uncovered a bug. Basically, one part of the code thought it was dealing with a vector of Customer (i.e. Vector<Customer>), but it was actually a Vector<String> representing customer IDs.
- Oliver
Chris Uppal - 26 Apr 2006 10:28 GMT > Over the process of slowly converting the code, we've uncovered a bug. > Basically, one part of the code thought it was dealing with a vector of > Customer (i.e. Vector<Customer>), but it was actually a Vector<String> > representing customer IDs. Wow! An actual, real live, bug found by generics -- I'm impressed.
(BTW, out of real curiosity, about how many warnings were /not/ indicators of bugs ? Also, how did a confusion between Customer and String get through testing, did two bugs cancel out, or something ?)
-- chris
Oliver Wong - 26 Apr 2006 14:54 GMT >> Over the process of slowly converting the code, we've uncovered a >> bug. [quoted text clipped - 7 lines] > of > bugs ? All the others. The figure was in the low 3 digits (200? 300?)
> Also, how did a confusion between Customer and String get through > testing, did two bugs cancel out, or something ?) I think that part of the code never actually got executed. It was part of a GUI whose window wasn't ever made setVisible(true) yet, since the features were still experimental and in early development.
- Oliver
Roedy Green - 26 Apr 2006 20:41 GMT On Wed, 26 Apr 2006 10:28:07 +0100, "Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org> wrote, quoted or indirectly quoted someone who said :
>Wow! An actual, real live, bug found by generics -- I'm impressed. Perhaps the most frustrating Java programming assignment I ever did was a classified ad system. I was handed code with hundreds of collections all with Generic Map type, along with collection assignment Had the code been done with Generics, it would have been a snap.. Tracking down just what was supposed to go in each collection was a nightmare.
On top of that there was the matter of null pointers. Where are they valid and where do you need empty strings?
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Mike Schilling - 26 Apr 2006 20:59 GMT > On Wed, 26 Apr 2006 10:28:07 +0100, "Chris Uppal" > <chris.uppal@metagnostic.REMOVE-THIS.org> wrote, quoted or indirectly [quoted text clipped - 11 lines] > On top of that there was the matter of null pointers. Where are they > valid and where do you need empty strings? Off and on, I've been playing with the idea that there could be two kinds of references in Java: those that can contain "null" as a value and those that can't. Assigning null to a non-nullable reference would be illegal. Assigning a nullable reference to a non-nullable one would require a cast and might result in an NPE then and there, so that the NPE points to the logical error, rather than occurring later when some perfectly innocent code trips over the null pointer.
Thomas Hawtin - 27 Apr 2006 01:06 GMT > Off and on, I've been playing with the idea that there could be two kinds of > references in Java: those that can contain "null" as a value and those that [quoted text clipped - 3 lines] > logical error, rather than occurring later when some perfectly innocent code > trips over the null pointer. Nice does that. It gets a bit difficult with constructors - how do you know if a member variable has been initialised yet? And then there's threads...
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Mike Schilling - 27 Apr 2006 04:08 GMT >> Off and on, I've been playing with the idea that there could be two kinds >> of references in Java: those that can contain "null" as a value and those [quoted text clipped - 6 lines] > Nice does that. It gets a bit difficult with constructors - how do you > know if a member variable has been initialised yet? I suppose you'd have to guarantee that all the non-nullable ones get initialized. If thery're final, that already guaranteed.
> And then there's threads... I suppose you'd need to guarantee that objects gets flushed after construction. Or just accept that odd behavior can result from unsychronized access.
The one I can't see a good solution for is arrays. A newly constrcuted array is full of null pointers, and you can initialize all of the members perhaps 10% of the time. I think you have to accept that
~Object o = arr[i]; // proposed syntax for non-nullable references
alwyas needs to be checked.
Thomas Hawtin - 27 Apr 2006 03:46 GMT >> Nice does that. It gets a bit difficult with constructors - how do you >> know if a member variable has been initialised yet? > I suppose you'd have to guarantee that all the non-nullable ones get > initialized. If thery're final, that already guaranteed. Constructors can call methods before final variables are set. Certainly the super constructor will have been called.
> The one I can't see a good solution for is arrays. A newly constrcuted > array is full of null pointers, and you can initialize all of the members > perhaps 10% of the time. I think you have to accept that Just insist on using collections instead...
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Mike Schilling - 27 Apr 2006 07:50 GMT >>> Nice does that. It gets a bit difficult with constructors - how do you >>> know if a member variable has been initialised yet? [quoted text clipped - 3 lines] > Constructors can call methods before final variables are set. Certainly > the super constructor will have been called. The super constructor can't see the variables defined at the level of "this". You're right that methods called from a constructor will have to be careful about the state of the object being constrcted, but that's already true.
My point about finals was probably unclear. I meant that the compiler already knows how to check than finals get set from every constructor; they can equally well check that any non-nullable field gets set from every constrcutor.
>> The one I can't see a good solution for is arrays. A newly constrcuted >> array is full of null pointers, and you can initialize all of the members >> perhaps 10% of the time. I think you have to accept that > > Just insist on using collections instead... And how does one implement the collections without using arrays? :-)
Mike Schilling - 27 Apr 2006 08:25 GMT >>>> Nice does that. It gets a bit difficult with constructors - how do you >>>> know if a member variable has been initialised yet? [quoted text clipped - 8 lines] > be careful about the state of the object being constrcted, but that's > already true. Finalizers, which can see partially constructed objects, too.
Thomas Hawtin - 27 Apr 2006 11:55 GMT > The super constructor can't see the variables defined at the level of > "this". You're right that methods called from a constructor will have to be > careful about the state of the object being constrcted, but that's already > true. They can. Normally through calling virtual methods. But this can be casted as well.
> My point about finals was probably unclear. I meant that the compiler > already knows how to check than finals get set from every constructor; they > can equally well check that any non-nullable field gets set from every > constrcutor. You can all to easily see final variables before they are initialised.
> And how does one implement the collections without using arrays? :-) Magic black box. I believe Eiffel does something similar.
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Mike Schilling - 27 Apr 2006 14:49 GMT >> The super constructor can't see the variables defined at the level of >> "this". You're right that methods called from a constructor will have to [quoted text clipped - 10 lines] > > You can all to easily see final variables before they are initialised. True, but at least you can't leave them uninitialized.
Note that fields cause two sorts of problems.
1. It's possible to see them before they're initialized, thus you see a null you're not expecting.
2. It's difficult if not impossible to prevent:
NN1 = this.NN2; // both declared non-nullable, but NN2 has not yet been set.
The first can cause NPEs at that line. The second can result in NPEs anywhere, which is much worse. In fact, it's exactly like Java today.
Oliver Wong - 27 Apr 2006 17:31 GMT > And how does one implement the collections without using arrays? :-) Remove all asymptotic runtime guarantees and implement everything using linked lists and binary trees?
- Oliver
Tony Morris - 27 Apr 2006 05:00 GMT > Nice does that. It gets a bit difficult with constructors - how do you > know if a member variable has been initialised yet? You are eluding to the formal invalidation of "OO as we know it" under a given axiom (which I believe you are assuming). Care to continue the logic? It's quite interesting - for myself and a few other interested parties at least. Of course, like most religions, it's difficult for its subscribers to swallow - but that's all part of the fun :) I can refer you to other interested people if you like.
 Signature Tony Morris http://tmorris.net/
Chris Uppal - 27 Apr 2006 13:11 GMT > > Off and on, I've been playing with the idea that there could be two > > kinds of references in Java: those that can contain "null" as a value [quoted text clipped - 5 lines] > > Nice does that. More info here: http://nice.sourceforge.net/manual.html#optionTypes and here: http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/OptionTypes (down at the bottom of the page).
It's not clear whether Nice has any special means to allow an instance field with a non-nullable type to be initialised only in the ctor. I suspect that you have to initialise it statically (as it were), and if necessary change the default in the ctor.
AFAIKT, the Nice collections implementation is layered over the Java stuff, so it's not possible to see how they'd solve the "the underlying array may contain nulls but I know it's not null at this index" problem. I presume that it would require logically unnecessary runtime checks in order to satisfy the compiler.
-- chris
Mike Schilling - 27 Apr 2006 14:45 GMT > AFAIKT, the Nice collections implementation is layered over the Java > stuff, Kan? :-)
Chris Uppal - 27 Apr 2006 15:19 GMT [me:]
> > AFAIKT, the Nice collections implementation is layered over the Java > > stuff, > > Kan? :-) Aargh!
Would you believe me if I claimed: As Far As I Know Today ? No ? Oh, well....
-- chris
Roedy Green - 27 Apr 2006 01:50 GMT On Wed, 26 Apr 2006 19:59:03 GMT, "Mike Schilling" <mscottschilling@hotmail.com> wrote, quoted or indirectly quoted someone who said :
>Off and on, I've been playing with the idea that there could be two kinds of >references in Java: those that can contain "null" as a value and those that [quoted text clipped - 3 lines] >logical error, rather than occurring later when some perfectly innocent code >trips over the null pointer. I have had similar thoughts. I thought about using javadoc to at least document which references are nullable.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Dimitri Maziuk - 23 Apr 2006 19:15 GMT Patricia Shanahan sez:
> I'm picking up a project I last worked on about a year, and one JDK > version, ago. It makes extensive use of java.util collections. [quoted text clipped - 16 lines] > Has anyone found a good solution to this problem? If not, any advice on > which less-than-desirable compromise to choose? -Xlint:unchecked will shut 'em up, however, there's a good chance you can simplify the code (and subsequent maintenance) by getting rid of explicit casts and adding foreach loops, unless you haven't learned anything in the last 12 months, you're sure to find a few things in your code you'll want to improve. (Of course, whether that's worth your time is another question.)
Dima
 Signature Backwards compatibility is either a pun or an oxymoron. -- PGN
Patricia Shanahan - 24 Apr 2006 00:11 GMT ...
> -Xlint:unchecked will shut 'em up, however, > there's a good chance you can simplify the code (and subsequent maintenance) [quoted text clipped - 4 lines] > > Dima Almost invariably, when I reread code I find things I could do better.
The decision about whether to make the change depends on circumstances.
Patricia
Mike Schilling - 23 Apr 2006 22:30 GMT > I'm picking up a project I last worked on about a year, and one JDK > version, ago. It makes extensive use of java.util collections. [quoted text clipped - 16 lines] > Has anyone found a good solution to this problem? If not, any advice on > which less-than-desirable compromise to choose? I would do something like the following:
First, characterize the warnings 1.5 adds to previously warning-free code. Next, create a filter that removes them from the javac output, and use that filter to compile your code. If, at some future date, you want to start using generics and will want to see the warnings, add a comment like
/** No warnings in JDK 1.4 */
to the code you *won't* be genericizing, and filter results only for files that don't contain that comment. (Alternatively, make this a private field instead of a comment, if your filter is written in Java and it's easier to use reflection on the class file than to grep the source file.)
Chris Uppal - 24 Apr 2006 09:13 GMT > I'm picking up a project I last worked on about a year, and one JDK > version, ago. It makes extensive use of java.util collections. > > I just did a rebuild, and got 100 "Type safety" warnings. It used > to be warning-free. I can't offer alternative technical solutions. I doubt if there are any (though Mike's ingenious idea comes close). Welcome to the wonderful world of generics make-work !
Is it possible to split your stuff up so that you can compile some sub-components with 1.4 settings, while continuing to work on other parts with a 1.5 compiler ?
If not, or to the extent that is is not, then I think I'd just [sigh deeply and] accept the hit. Better to get it over with now, rather than having it hanging around irritating me every time I think about it... It'd be a chance to do some code-cleaning too, so it might not be a /total/ waste of time.
This is what we get for using a language with a fashion-lead design process.
-- chris
Patricia Shanahan - 24 Apr 2006 13:47 GMT >>I'm picking up a project I last worked on about a year, and one JDK >>version, ago. It makes extensive use of java.util collections. [quoted text clipped - 18 lines] > > -- chris Fortunately, I use Eclipse. I went into project properties, and found, under "Java Compiler", "Errors/Warnings". It supplies separate control for a series of conditions. J2SE 5.0 gets its very own tab. Changing "Unchecked generic type operation" from "Warning" to "Ignore" got me back to a warning-free compilation.
It seems sufficiently specific that it is unlikely to mask any warning I would care about, unless/until I decide to get on the generic bandwagon.
It also has options in the other direction. I'm not sure I really like the automatic boxing/unboxing feature. Eclipse has an option to turn that into a warning or error.
NICE Eclipse.
Thanks to everyone for their suggestions, and to the Eclipse developers.
Patricia
Chris Uppal - 24 Apr 2006 16:12 GMT > Fortunately, I use Eclipse. I went into project properties, and found, > under "Java Compiler", "Errors/Warnings". It supplies separate control > for a series of conditions. J2SE 5.0 gets its very own tab. Changing > "Unchecked generic type operation" from "Warning" to "Ignore" got me > back to a warning-free compilation. Ah, that was the clever technical solution I couldn't think of -- switch to a different compiler ;-)
-- chris
Ed Kirwan - 24 Apr 2006 11:24 GMT > I'm picking up a project I last worked on about a year, and one JDK > version, ago. It makes extensive use of java.util collections.
> 3. Go back to JDK 1.4, and not use e.g. generics in any new code.
> Thanks, > > Patricia Whereas I like Chris's oh-so deep sighing, I would ask what's wrong with sticking with 1.4? Are there particular features you require in 1.5 that are not in 1.4?
1.4 is neither a second-best nor an out-dated version of the language (older, yes, out-dated, no). Generics-lovers will flap hands, roll eyes, mince around, and squeal, "But it's sssssssssssssooooooooo type-unsafe!" If you're constantly getting ClassCastExceptions because you're repeatedly pulling the wrong class from your collections, then move to 1.5 and generics-up; but if you've programmed in Java for more than 6 months, you'll probably get one of those exceptions per year, and it'll take you somewhere in the region of ... oh, say five seconds to correct it.
And what happens when Java 1.6 (ok, ok, Java 6) comes out? Will you enter zombie-mode and slowly, awkwardly update all your code to be 1.6-specific (all the while moaning, "Brains ...")?
Oh, wait! Hang on! I forgot: in Java 1.5 you can use foreach. Forget everything I said; upgrade to 1.5 and change all your for-loops to foreaches. That'll make it all worthwhile!!
(And if you're wondering whether that's sarcasm, then you really do need to upgrade to 1.5.)
(Sarcasm: 2, Common Sense: 0)
 Signature www.EdmundKirwan.com - Home of The Fractal Class Composition.
Download Fractality, free Java code analyzer: www.EdmundKirwan.com/servlet/fractal/frac-page130.html
Mike Schilling - 25 Apr 2006 00:55 GMT > I'm picking up a project I last worked on about a year, and one JDK > version, ago. It makes extensive use of java.util collections. > > I just did a rebuild, and got 100 "Type safety" warnings. It used > to be warning-free. Can you show some of the statements that cause warnings? We'll be in the same state before long (code we don't want to touch that we'll be compiling under 1.5) and I'd like to know what to watch out for.
Patricia Shanahan - 25 Apr 2006 01:22 GMT >>I'm picking up a project I last worked on about a year, and one JDK >>version, ago. It makes extensive use of java.util collections. [quoted text clipped - 5 lines] > same state before long (code we don't want to touch that we'll be compiling > under 1.5) and I'd like to know what to watch out for. Sure. Here's a typical case:
Type safety: The method get(int) belongs to the raw type List. References to generic type List<E> should be parameterized
The source code line is:
Shop s = (Shop) allShops.get(j);
where allShops is declared as:
private static List allShops = new ArrayList();
Here's another form:
Type safety: The expression of type FileTimes.TimeComparator needs unchecked conversion to conform to Comparator<? super T>
The source code line is:
Collections.sort(files, new TimeComparator());
Unfortunately, I don't see anything that can be done to make a program using java.util collections work in 1.4 and also be warning-clean in 1.5.
Patricia
Mike Schilling - 25 Apr 2006 04:57 GMT >>>I'm picking up a project I last worked on about a year, and one JDK >>>version, ago. It makes extensive use of java.util collections. [quoted text clipped - 30 lines] > Unfortunately, I don't see anything that can be done to make a program > using java.util collections work in 1.4 and also be warning-clean in 1.5. What I don't understand ...
OK, *among* the things I don't understand is why the raw type can't be defined as the moral equivalent of TYPE<Object> (in a type which so declares it, not for all types). That would be correct for the java.util.collections generics, at least, and would remove this sort of silly warning. You' still get a warning when you passed, say, List<String> to a method that expects a raw List, but that's a sensible warning, and comes from mixing 1.4 and 1.5 code.
Oliver Wong - 25 Apr 2006 21:40 GMT >>>>I'm picking up a project I last worked on about a year, and one JDK >>>>version, ago. It makes extensive use of java.util collections. [quoted text clipped - 40 lines] > List<String> to a method that expects a raw List, but that's a sensible > warning, and comes from mixing 1.4 and 1.5 code. There's arguments for it being "defined as the moral equivalent of" (DATMEO) TYPE<Object>, and there's arguments for it being DATMEO TYPE<?>. The two have different semantics. Probably the designers argued back and forth between these two DATMEO interpretations, until they finally threw up their hands and decided that raw types are "neither", that they'll be referred to as "raw", and that we'll put warnings to get the programmers to specify whether they mean TYPE<Object>, TYPE<?>, or something else altogether.
- Oliver
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|