[java] Java Generics

Started by
4 comments, last by etothex 18 years, 5 months ago
Recently in 1.5 java has added generics... and I'm just lost on them. I mean Java seemed so nice and easy before they threw this in, and now it's just crazy. But anyways, enough with the rant: my basic question is this - can anyone give me a good explanation of java generics? (how and why you you would use them, what the exact syntax means.. just the works, but from a very basic starting point) I've searched google, and Sun's explanation got a bit complex, as well as some other sites... so can anyone give links to any really simple tutorials on this subject? Thanks, o_o
Advertisement
This should help mate

ace
the syntax is simple

ArrayList<Type> list = new ArrayList<Type>();

fill in any reference type you want for Type. Primitive types are not acceptable, you'll have to use the fully qualified class versions.

Once you have done this, you can only add objects of a specific type to the list (there are other uses). When you retrieve an object from the list, it's automatically cast back to the original type.

It's supposedly a measure of type safety, but in reallity it's just a short cut. In fact, it's pretty easy to absolutely destroy any semblence of type safety that java generics claim to add.

If you don't want to use them, you can use the old collections and such, you'll just get a compile time warning. They offer no performance gain whatsoever. They compile to the exact same code as using the old collections with manual type casting. All they do is clean up your source code a little.

When compared to C++ templates and C# generics, they're a bloody joke.

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

Generics add some more type-safety and help you write better code, especially when using the standard Java Collections like Vector, List, etc.

For example, you used to have to do this:

List list = new ArrayList();String s1 = "hi there";String s2 = "hi there too";list.add(s1);list.add(s2);...//later on...String s = (String)list.get(0);System.out.println(s);


Notice the ugly cast. It obscures what you are doing, and more importantly, you won't get a compile-time error if you accidentally:

//later on...Integer i = (Integer)list.get(1);Exception: java.lang.ClassCastException ...


Rather you get the runtime error which might, depending on the size and complexity of the application, never appear during beta testing, but rather when the code is already in production.

So now we can prefer:

List<String> list = new ArrayList<String>();String s1 = "hi there";String s2 = "hi there too";list.add(s1);list.add(s2);...//later on...String s = list.get(0); //notice - no cast!!System.out.println(s);...//later on...Integer i = list.get(0); //compile-time error, no exception!


EDIT: plus, now we get the cool for each operator. Instead of getting an iterator and going through all the elements of a collection, we can do:

for(String s : list) {   //stuff with strings}


This is possible because with generics, types can be checked at compile time.
Quote:Original post by etothex
This is possible because with generics, types can be checked at compile time.
well, sort of. I think they're actually checked BEFORE compile time. Java Generics are essentially a preprocessor directive that expand out to their type-casting equivalent expressions before being compiled.

ArrayList<String> a = new ArrayList<String> ();Object b = a;ArrayList c = (ArrayList) b;c.add (new Integer (23));System.out.println (a.get (0));


This code dies on the very last line, because the Java Generics "preprocessor" replaces the code with this before compiling:

ArrayList a = new ArrayList ();Object b = a;ArrayList c = (ArrayList) b;c.add (new Integer (23));System.out.println ((String) a.get (0));


This isn't trivial code, however. There are many times in which one desires to save lists of lists, and the component lists are of varying types. For example, a priority queue would have a list of queues, each individual queue storing objects of a single type different from the other queues. How would you code such a thing with generics?

List<Queue> queues = new List<Queue>();queues.add(new Queue<Type1>());queues.add(new Queue<Type2>());queues.add(new Queue<Type3>());

when you go to retrieve the individual queues, you've lost that Type information, because the Queue<Type1> and Queue<Type2>, etc. will be returned as just a Queue. At that point, you're again left to your own devices, just as you were before Java Generics, to determine what the type of the objects are in those Queues.

C++ templates are also preprocessor templates, but they create a completely new class for each type used, using class and variable name garnishing to differentiate internally. Attempts to violate the template structure will result in a compile time error. C# Generics maintain type information throughout the lifecycle of the application, instead of discarding the information prior to compiling as in Java's case.

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

True, though one of the requirements with introducing generics into Java was that it be fully compatible with older JVM's. Unfortunately, this leads to some deficiencies in the implementation.

Given all their requirements, they seem to have done an impressive job. In the end though, the best things about Java generics are that it allows you to mostly write simpler Collections code(without explicit casts) as well as let the compiler run an elementary check over your code for a commonly written bug.

This topic is closed to new replies.

Advertisement