Notes on SCJP I did in 2008
Generics
Straight forward Type Safe Collections
List<Animal> myList = new ArrayList<Animal>();
the generic type in the declaration must match on both side of = , in this case <String>
(unless a wildcard is used to the left of the equals OR the ref has no gen type eg List myList).
can only add <Animal> or subtypes to myList
eg
myList.add(new Animal()); // GOOD
myList.add(new Dog()); // GOOD
myList.add(new Integer()); //ERROR
Passing / Returning from method
void myMeth(List<Animal> animals){ …
can accept
List<Animal>, Vector<Animal> // GOOD
cannot accept
List<Dog>, ArrayLis<Cat> // ERROR
Mixing Old and New Collections
List<Integer> list = new ArrayList<Integer>();
oldClass.alterList(list)
…
class OldClass{
void alterList(List List){
list.add(” a string ! “); // works
}
}
Its not until someone calls a Integer method on the String obj in the collection that it will blow up !
However the compiler will issue a warning.
Type Safe Collections with wildcards
When you dont need to add to a collection
void lookAtThis(List<? extends Animal>){ …
can take:
List<Animal>
ArrayList<Dog>
Vector<Lion>
etc
can also take class type that implements an interface. [eg Animal implements ManEater]
List<? extends Animal> li = new ArrayList<Dog>(); // GOOD
this means assign anything to li that is Animal or subclass BUT will not be able to add to it
List<?> list is equivalent to : List<? extends Object>
Wildcards when you need to add to a collection
void addTo(List<? super Dog> list){ …
this can take:
List<Dog>
List<Animal>
List<Object>
adding to:
list.add(new Dog()); // GOOD
list.add(new Object()); // ERROR
list.add(new Animal()); // ERROR
List<? super Dog> li = new ArrayList<Animal>(); // GOOD, looks abit weird usually more specific on right eg List l = new ArrayList();
li.add(new Animal()); // ERROR weird but true
li.add(new Alsatian()); // GOOD
Summary:
When see a ref that has notation like List<?> this can take list of any type but cannot add to it.
See Pauls explanation as to why you can’t add to it (or any <? extends> )
Generic Type Reference | Task | is task valid? | Notes |
List<Animal> list | list.add(new Dog()); | Y | OK add
NOT OK poly pass list type |
pass this to it List <Dog> | N | ||
list.add(new Animal()); | Y | ||
List<? extends Animal> list | list.add(anything); | N | OK pass poly generic subtypes
CAN NOT add to |
pass ArrayList<Dog> | Y | ||
pass List<Alsatian> list | Y | ||
List<? super Dog> list | list.add(new Dog()); | Y | OK pass generic supertype to it
OK ADD only the generic type to it |
list.add(new Animal()); | N | ||
pass List<Dog> | Y | ||
pass List<Animal> | Y |
Templating your own Classes
A class can be templated (such as the collections classes have been in the API). Instance vars, method pass and return types can all be templated eg:
class GenExample<T>{
T obj;
List<T> myList;
void meth1(T var){
this.obj = var;
}
List<T> getList(){
return myList;
}
T getObj(){
return obj;
}
}
if the class above was instantiated as GenExample<String> eg = new GenExample<String>();
it would produce an instan ce of the class below.
class GenExample<String>{
String obj;
List<String> myList;
void meth1(String var){
this.obj = var;
}
List<String> getList(){
return myList;
}
String getObj(){
return obj;
}
}
Templating your own Methods
if you done need to template a whole class you could just template one method eg
public <T> void aMethod(T obj){ ….
here the template type MUST come before anything else including the return type.
For both class and methods you can put boundaries on them e.g.
public <T extends CharSequence> void aMethod(T obj){ ….
note the syntax is slightly different to that used when declaring a generice reference to something e.g. List<? extends Object> list