Keeping track of what's in the collection in Java pre-dipids?

For a number of reasons that (believe it or not) are not as vast as you think, we are still (sigh) using Java 1.4 to build and run our code (although we plan to finally switch to Java 7 at the end of the year) .

Our existing code that uses Collection classes doesn’t really clarify what is expected in Collection . Obviously, you can read the code and see what the downcasts will end and draw a conclusion from this, but you cannot just look at the declaration of the method and find out that the Collection object, which is the argument of the method or the return value of the method, actually takes place.

In the new code that I write, and when I am in the older code that uses Collection s, I added comments in the line to Collections declarations to show what would be announced if generics were used. For instance:

 Map/*<String, Set<Integer>>*/ theMap = new HashMap/*<String, Set<Integer>>*/(); 

or

 List/*<Actions>*/ someMethod(List/*<Job>*/ jobs); 

In keeping with the gloomy subjectivity here at SO, instead of asking what you think about it (although admittedly, I would like to know - I find this a little ugly, but still like to have type information) I ' d instead, just ask what, if anything, you will do to understand what is held by the pre-type Collection objects.

+4
source share
4 answers

What we recommended in the old days β€” and I was a Java architect in Sun when Java 1.1 was New Thing β€” was to write a class around the structure (I don't think 1.1 even had Collection as a base class), so the casts types in the code you control instead of user code. So for example, something like

  public class ArrayOfFoo { Object [] ary; // ctor left as exercise public void set(int index, Foo value){ ary[index] = (Object) value; // cast strictly not needed, any Foo is an Object } public void get(int index){ return (Foo) ary[index]; // cast needed, not every Object is a Foo } } 

It seems that the base code base is not built for this convention; if you write new code, there is no reason why you cannot start. Otherwise, your convention is not bad, but it is easy to forget the throw, and then search to find out why you get a bad exception. It is mildly better to use a variant in the Hungarian notation or in the Smalltalk aVariable convention, encoding the type in the names, so that you use

  Object fooAry = new Object[aZillion]; fooAry[42] = new Foo(); Foo aFoo = fooAry[42]; 
+4
source

Use clear variable identifiers such as jobList , actionList or dictionaryMap . If you are concerned about the type of objects they contain, you can even make it an agreement to always indicate the collection hint identifier about what type of objects it contains.

The comments you enter are not an idea. When I moved project 1.5 to 1.4, I did just that (instead of deleting type parameters). It worked out quite well.

+1
source

I would recommend writing tests. For different reasons:

  • You still have to write tests.
  • You can easily claim the type of a member of a collection to make sure that all of your code paths add the types you need to the collection.
  • You can use the test to write code, which serves as an "example" of the correct use of the collection.
+1
source

If you just want binary compatibility with 1.4, you might consider using a tool to downgrade class files to 1.4 and thus start developing in 1.6 or 1.7 right now. Of course, you will need to avoid any API that was not in 1.4 (unfortunately, you cannot compile code with generics against 1.4 cans directly, since they do not declare any common types). Bytecode is still the same (since at least 1.6, I definitely don't know about 1.7). One free tool that can do the trick is ProGuard . It can do much more complex things and can also delete all traces of generics in class files. Just turn off obfuscation and optimization if you don't need one. It will also warn you if any missing API was used in the processed code, if you feed it with libraries 1.4.

I know that this is considered a hack for many, but we had a similar requirement when we needed some code to work on a personal Java virtual machine (this is, in fact, Java 1.1) and several other exotic virtual machines, and this The approach worked pretty well. We started with ProGuard, and then created our own tool so that the task could implement several workarounds for some errors in various virtual machines.

0
source

All Articles