Is it possible to use generics in lists in Java 1.4?
Asked Answered
I

5

5

I have to use Java 1.4 and am using arraylist structures. Now I need to do some re-factoring and it would help if I can use Generics. Currently I have code like this

ArrayList rows = new ArrayList();

Which is a straightforward ArrayList. But now the "rows" variable is becoming more complex and need to define a "Row" class. I now want to do something like what you see in J2SE 1.5

ArrayList<Row> rows = new ArrayList();

A trawl through Google doesn't expose any answers without some sophisticated use of 3rd party solutions. How would my code have to change to accommodate this in 1.4, without using 3rd party solutions/open source projects, (if possible)?

Intramural answered 12/6, 2011 at 5:24 Comment(0)
V
9

Generics were introduced in JDK 1.5. So you can't use them in 1.4. However, you may be able to use JDK 1.5 compiler but target 1.4 with your classes with -target 1.4 javac option while keeping -source 1.5 option to indicate that your source is 1.5 compatible. In this case you can use generics as they should not affect result classes.

See the section on Cross-Compilation Options

Viyella answered 12/6, 2011 at 5:29 Comment(4)
In case of generics, yes, since they don't have effect on bytecode.Viyella
So it is possible to tell the compiler to use syntax of 1.5 but the compiler will generate class files that are 1.4 compatible ? The jvm on the web server I will be using requires run time for 1.4. The benefit in trying to accomplish this, is to prevent runtime errors because of casting problems. (Had to re-add this comment because it was locked after 5 minutes)Intramural
Sorry to sound like a noob, but I would greatly appreciate a reference to a link that demonstrates this configuration for Eclipse.Intramural
Sorry, I don't use Eclipse regularly. And I don't see anything obvious there. To produce final artifact, you probably should use some scripting tool (ant, maven etc). But if you need it for Eclipse, I suggest you post another question.Viyella
G
4

Generics tends to address the problem of what I deem "naive casts" in Java 1.4 or earlier when dealing with Collections. In Java 1.5+, the line you've placed:

ArrayList<Row> rows = new ArrayList();

would give a warning, the proper generic code is

ArrayList<Row> rows = new ArrayList<Row>();

This tells the compiler that your ArrayList object should only ever contain the Row type.

However, since Java 1.5 is backwards-compatible with huge sets of libraries that don't contain that syntax, but rather your previous code:

ArrayList rows = new ArrayList();

Generics obviously wouldn't work with these older libraries - therefore generics are only a compile time option - the 1.5 and 1.4 classes are effectively equivalent (minus any internal refactoring/new methods added later) because they are really ArrayList implementations that handle any Object type.

The 1.5 code simply adds in a direct cast for you.

In 1.4 code, say you wanted to iterate over the ArrayList. The naive cast way to do this is the following:

for(Iterator rowIterator = rows.iterator(); rowIterator.hasNext(); ) {
    Row row = (Row) rowIterator.next();
    // Do something with the row.
}

Java 1.5's code is exactly equivalent to the naive cast version. It takes the fact that you are telling the compiler that it is a row and does that code for you. So, the syntactic sugar benefits are nicer (this uses the newer for each loop syntax, but it generates the same code as the above loop):

for(Row row : rows) {
   // Do something with the row
}

So, if you want to use an ArrayList containing only rows, you still can. But there's no way to get the compiler to check that the ArrayList contains only all rows (although, even though the compiler provides this check, it is still possible to send in an ArrayList that contains other types of objects, since, again, the ArrayList still only really handles the Object type, and the generics are erased at runtime - all that remains is the naive cast code that you don't see anymore).

The non-naive variant is to check each instance and throw a ClassCastException yourself with an informative message (rather than have the program throw one with its default message):

for(Iterator rowIterator = rows.iterator(); rowIterator.hasNext(); ) {
    Object shouldBeRow = rowIterator.next();
    if(!(shouldBeRow instanceof Row)) {
        throw new ClassCastException("The object " + shouldBeRow + " is not an instance of Row - only Rows should be present in the list!");
    }
    Row row = (Row) shouldBeRow;
    // Do something with the row.
}

However, generally no one does this - good documentation can make this issue moot, as it places the burden of providing the correct collection on the caller and thus you can just have the ClassCastException thrown by the JVM.

Gonagle answered 12/6, 2011 at 5:38 Comment(0)
M
2

Yes you can. Use a 1.5 compiler, and use

javac -target jsr14 ............

This will generate java 1.4 classes, but allow generics.

This switch can only be used for non byte code visible 1.5 features. For instance you can't use Enums, or new methods introduced in 1.5. But generics are fine, as they are not really present in the byte code.

Mistake answered 12/6, 2011 at 6:31 Comment(0)
B
0

No, you can't use them in JDK 1.4. They were introduced in JDK1.5

Bertrambertrand answered 12/6, 2011 at 5:36 Comment(0)
M
-1

All you have to do is cast them. This could merit a runtime exception if you put "wrong" types into the list.

Row arow = (Row) rows.get(0);

for ($i=0; i<rows.size(); $i++){
    Row element = (Row) rows.get($i);
    element.printCells();
    (...)
}
Molten answered 12/6, 2011 at 5:35 Comment(1)
hey wtf. The other guy told you in 60 lines what I told you in 4. Ill recommend you "effective java" by Joshua Bloch, but that's it.Libertine

© 2022 - 2024 — McMap. All rights reserved.