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.