• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Generics understanding

 
Ranch Hand
Posts: 185
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I was very much confused about Generics. So i made this small piece of note about it. Please verify and also any inputs or additions are welcome.

Generics

My understanding

Use - Compile-time type safety. So the net effect, especially in large programs, is improved readability and robustness.


Wildcard ? : Collection<?> means a supertype of all kinds of collections.
Collection<Object> can only take Collection<Object> and not any other subtype.
Now ? means unknown type. So we cannot add objects to it. The sole exceptin is null, we can add null to it, which is a member of every type.
On the other hand, give a List<?> we can call get() and make use of the result. The result type is an unknown type, but we always know that it is an object.

Bounded Wildcards: List<? extends Shape> shapes mean it can accept any parameter which extends Shape implying List<? extends Object> is same as List<?>. In List<? extends Shape> we say that Shape is an upper bound of the wildcard. Now as mentioned earlier, nothing can be added to List<? extends Shape> because ? extends Shape means an unknown subtype of Shape.

Now an example: Suppose that we want to write a method that takes an array of objects and a collection and puts all the objects in the array into the collection.

So we may do like this:

static void fromArrayToCollection(Object[] a, Collection<?> c){
for(Object o:a){
c.add(O);//compile time error
}
}
We know we cannot add to an unknown type. So how are we gonna deal with it? The way to deal with these problems is to use generic methods. Just like type declarations, method declarations can be generic - that is, parametrized by one or more type parameters.

static<T> void fromArrayToCollection(T[] a, Collectin<T> c){
for(T o:a){
c.add(o);
}}
Now we can call this method with any kind of collection whose element type is a supertype of the element type of the array.

Object[] oa = new Object[100];
Collection<Object> co = new ArrayList<Object>();
fromArrayToCollection(oa, co);// T inferred to be Object
String[] sa = new String[100];
Collection<String> cs = new ArrayList<String>();
fromArrayToCollection(sa, cs);// T inferred to be String
fromArrayToCollection(sa, co);// T inferred to be Object
Integer[] ia = new Integer[100];
Float[] fa = new Float[100];
Number[] na = new Number[100];
Collection<Number> cn = new ArrayList<Number>();
fromArrayToCollection(ia, cn);// T inferred to be Number
fromArrayToCollection(fa, cn);// T inferred to be Number
fromArrayToCollection(na, cn);// T inferred to be Number
fromArrayToCollection(na, co);// T inferred to be Object
fromArrayToCollection(na, cs);// compile-time error


One question that arises is: when should I use generic methods, and when should I use wildcard types? To understand the answer, let’s examine a few methods from the Collection libraries.
interface Collection<E> {
public boolean containsAll(Collection<?> c);
public boolean addAll(Collection<? extends E> c);
}
We could have used generic methods here instead:
interface Collection<E> {
public <T> boolean containsAll(Collection<T> c);
public <T extends E> boolean addAll(Collection<T> c);
// hey, type variables can have bounds too!
}
However, in both containsAll and addAll, the type parameter T is used only once.
The return type doesn’t depend on the type parameter, nor does any other argument
to the method (in this case, there simply is only one argument). This tells us that the
type argument is being used for polymorphism; its only effect is to allow a variety of actual argument types to be used at different invocation sites. If that is the case, one
should use wildcards. Wildcards are designed to support flexible subtyping, which is what we’re trying to express here.
Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn’t such a dependency, a generic method should not be used.
It is possible to use both generic methods and wildcards in tandem. Here is the method Collections.copy():
class Collections {
public static <T> void copy(List<T> dest, List<? extends T> src){...}
}
Note the dependency between the types of the two parameters. Any object copied from the source list, src, must be assignable to the element type T of the destination
list, dst. So the element type of src can be any subtype of T - we don’t care which.

Wildcards also have the advantage that they can be used outside of method signatures,as the types of fields, local variables and arrays.
 
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry, I didn't read your whole post, I just wanted to add this useful link: Angelika Langer's Java Generics FAQ. It has everything you ever wanted to know about generics including all the technical details.
 
Sheriff
Posts: 9708
43
Android Google Web Toolkit Hibernate IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There are a few things that I would like to point out to you Jacob

Wildcard ? : Collection<?> means a supertype of all kinds of collections.



I don't understand what you are trying to say here. But from what you wrote below this line, is correct so maybe I'm not able to understand your language.

Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn’t such a dependency, a generic method should not be used.



Again what do you mean here. I think what you are trying to say is that if there is no dependency between the type of the arguments to each other and/or the return type, then wildcards must be used instead of typed methods.

Wildcards also have the advantage that they can be used outside of method signatures,as the types of fields, local variables and arrays.



Well I hope you know that you can use generic types at class level



So here basically I've used a generic type as type of field which you said can only be done using wildcards. I don't know what you meant when you said that wildcards can be used as types of fields and local variables, but I hope you know this



Also the last thing, you must know that you can use lower bounded wildcards and also that type variables cannot have a lower bound

 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic