tags:

views:

235

answers:

7

Can someone explain what were the reasons generics were introduced in Java?

As far as I understand they were introduced so that you don't accidentally add the wrong type of object to a collection.

I kind of like the generics for collection but can't see why they were added for other classes too. I have seen some generic classes that make your head hurt and your eyes bleed.

So what are all the reasons generics were introduced (mainly for non collections)?

TIA!

+5  A: 

The Java Collection Framework is nothing special from a Java perspective, so there's no reason or need to add a new language feature to this framework only.

Look at generics from a user perspective: Now if you have a collection you know what kind of objects are in it. That's a great advantage. Just compare the following snippets, without and with generics:

With Java 1.5+

List<Animal> zoo = new ArrayList<Animal>();
for(Animal animal:zoo) {
  feed(animal);
}

Before Java 1.5-

List zoo = new ArrayList();
for (int i = 0; i < zoo.size(); i++) {
  if (!(zoo.get(i) instanceof Animal)) {
    continue;
  } else {
    Animal animal = (Animal) zoo.get(i);
    feed(animal);
  }
}

From users perspective, it's more the old style that hurts the eye.

Andreas_D
This doesn't really answer my question
user3332
It does answer it: There was no reason to make this new feature only work with collections, when it can be used in all kinds of situations.
Thilo
The OP has no problem with generics on collections, so your example code is moot.
Thilo
+1. Doesn't answer the question about non-collection generic uses, but makes a good point about the code with generics is a lot cleaner. Maybe the declaration is wider, but its use is great! (and you don't have to guess what the type of the object is!)
helios
A: 

Generics are indeed particularly useful in collection classes, but their usefulness is not limited to that. I can't imagine how the generic capability could have been made available to collection classes and yet not be made generally available - generics are a fundamental language feature not a specific patch for collections. Would you want the compiler to have logic like:

if this is a collection class
    allow generics

and how could the compiler spot that it has a collection class - after I can write my own collections.

Like many sharp tools generics can be misapplied and overused, that doesn't make the tool itself a bad thing.

djna
"how could the compiler spot that it has a collection class - after I can write my own collections." Well, your own collection would implement Collection or Map, so the compiler would know about it. Just like the foreach loop works "after you write your own iterable".
Thilo
+1  A: 

Anyplace where you want to do generic programming ;-)

It is, you don't mind (too much) about the type of some object, but want to restrict its type to function properly.

Imaging pipe&filters. Imagine each pipe has a specific output. One outputs bytes, other strings, and other numbers. It would be nice each pipe has its specific type and you could only hook a pipe of an X output to a pipe of an X input.

Byte -> Filter -> String -> Filter -> Integer

So your first Filter will be Filter<Byte, String> and its hookOutputPipe will receive a Pipe<String>.

Maybe your eyes bleed with over parametrized types, but in some situations it's a pretty good allied for an API developer. If you start to use them in appropiate situations you'll feel the usefulness of them.

One example from real world: event types and handler types in GWT.

helios
+6  A: 

Essentially type safety and convenience.

Java implements its generics by a mechanism known as type erasure which effectively replaces the generic definition with a non-generic definition at compile time. The reason this was done was to maintain API compatability between 1.4 and 1.5 - the collections API may well have been updated but if you accessed it in a non-generic way in 1.5 it would work the same.

The difference was that if you intended a collection to only contain particular types of objects you could explictly encode that requirement in your APIs and avoid issues such as receiving a list with the wrong type of objects in it - and also the need to have to explictly cast those objects making your code simpler to read and less error prone.

You would use the generics for essentially the same reasons as when they are used with collections - when you need to say that an object is a composite of other objects, but that there may be a range of types possible for that composition and that once bound the addition of these new objects implies a new composite type disimilar to other similar composites. That is to say a list of strings is similar in type to a list of integers but they are no longer compatable with each other.

One example of this is in the Future where you are waiting for an asynchronous result. The Future class encapsulates the concept of the asynchronous result, but the specific type of Future such as Future<String> futher specifies what type of result you can expect - and makes it distinct from Future<Integer>.

cyborg
+1. Simple and powerful example.
helios
+4  A: 

They were added because the only way to make a truly generic placeholder in the original Java was to have a field of type Object. This can take any object.

Unfortunately when you NEED it again it is of type Object which doesn't hold any interesting methods, so you need to cast it to the type you happen to know it has. These runtime casts were a frequent source of error and - by nature - happened at runtime.

Generics move this to the compiler, and cause a LOT less ClassCastExceptions which improve quality. The actual syntax is a bit verbose - here the C# keyword 'var' would help a lot - but the bit of extra labor gives a lot of payoff.

I believe you have to had programmed in a strongly typed language like Haskell to know what is possible, and why it is desirable.

Thorbjørn Ravn Andersen
+3  A: 

Generics afford the programmer some type safety. The most obvious use is to prevent a user inadvertantly passing the wrong type into a function. They can also be used to avoid a lot of noisy casting.

Here is a non collection example that would benefit from a generic. If we have lots of views which are associated with a model, we might define an interface to represent a view. The interface might have a getModel() method:

public interface View {
   Model getModel();
}

Anyone that calls the method has to cast the result which is a pain:

MyView view = new MyView();
MyModel model = (MyModel) view.getModel();

So instead we specify interface using as generic:

public interface View<M extends Model> {
   M getModel();
}

A concrete class called MyView

class MyView implements View<MyModel> {
  MyModel getModel();
}

Then the client code is a bit cleaner:

MyView view = new MyView();
MyModel model = view.getModel();

With careful crafting generics can make code a lot more readable. However generic type info doesn't get compiled into the class file so there is still potential for abuse at runtime.

locka
+1  A: 

Lets say, we want to write a method to find the maximum of two comparable objects, similar to Math.max():

public static <T extends Comparable<T>> T max(T arg0, T arg1) {
    return arg0.compareTo(arg1) > 0 ? arg0 : arg1;
}

Now you can call the method like this,

int maxNum = max(5 ,3);
String maxString = max("AAA", "BBB");
File maxFile = max(new File("path/to/file1"), new File("path/to/file2"));

Try defining this functionality without generics. Here the return type is inferred and you dont need any type casting at all. Further the type is checked at compile time rather than resulting in ClassCastException at runtime.

Marimuthu Madasamy