Appendix Afg

Embed Size (px)

Citation preview

  • 7/28/2019 Appendix Afg

    1/32

    AAppendix: Generic Types

    Generic types are not a different capability from the class and interface types that we have undergone in

    the earlier chapters. The facility for defining generic class and interface types is an extension of theordinary definition of classes and interfaces that we are already familiar with that enables you to definefamilies of classes and interfaces.

    Using Generics it is possible to create classes, interfaces, and methods that will work in a type-safemanner with various kinds of data. With generics you can define an algorithm only once and then applythat algorithm to a wide variety of data types without any additional effort. This chapter can beconsidered as the leading edge of the Object-Oriented Programming. You can get by without knowingany of the information in this chapter, so feel free to skip it if you are on your way to something moreinteresting. It is better to just have an idea about the collections so as to learn how Ar r ayLi st andLi nkedLi st classes to use the new generics feature. Collection Framework, an important feature in

    Java, has been significantly affected by generics. Whereas collection is a group of objects, CollectionsFramework defines several classes, such as lists and maps that manage collections. How generics haveaffected collections classes is that they can be used with complete type safety. Overall generics enabledan existing feature to be substantially improved. Lets see an example, the add method for the

    Ar r ayLi st class had this declaration, publ i c bool ean add( Obj ect obj ) , in which you can passany type of object to the add method which would be accepted by the array list.

    Before retrieving any item from the collection, there is a definite need of casting it to the correct objecttype. Suppose if you had an array list named cust l i st with Cust omer objects, following line of codecan be used in order to get the first customer from the list:

    Customer c = (Customer) custlist.get(obj);

    Since, the add method can accept any object type, its not certain that only certain types of objects couldbe added to the collection. So, generics were invented. Now you can declare the Ar r ayLi st like this:

    ArrayList custlist = new ArrayList();

    Here, cust Li st is declared as an Ar r ayLi st which will hold only Cust omer types. The add methodcan be declared as publ i c bool ean add(Cust omer c) .

  • 7/28/2019 Appendix Afg

    2/32

    Appendix A

    Now, you can only add employee objects to the list. And the get method will be declared as publ i cCust omer get ( i nt i ) . The get method here is returning a Cust omer object. So there is no need tocast the result of the Cust omer as the compiler already knows that the object is Empl oyee.

    What are Generic Types?A generic type, also referred to as a parameterized type, is a class or interface type definition consistingof one or more type parameters. This is one of the several extensions to the Java programming language.It was first introduced in JDK 1.5.

    With generics, it is no longer necessary to explicitly employ casts to translate between object and thetype of data that is actually operated upon. With generics, all casts are automatic and implicit. In otherwords, generics expand your ability to reuse code.

    You can define an actual class or interface type from a generic type by providing a type argument foreach of the type of parameters that the generic type has. Heres a typical usage of that kind:

    List Lst = new LinkedList();

    Lst.add(new Integer(0));Integer i = (Integer) Lst.iterator().next();

    The cast on third line is slightly misinterpreting. The programmer knows exactly, what kind of data havebeen placed into a particular list. However, the cast is essential. The compiler can only guarantee youthat an object will be returned by the iterator. To guarantee you that the assignment to a variable of typeI nteger is type safe, the cast is essential. It not only introduces clutter but also introduces thepossibility of a runtime error, since the programmer might be mistaken.

    What will happen if programmers could actually express their intentions, and mark out a list which isrestricted to contain a particular data type? This becomes the core idea behind generics. Here s a versionof the preceding-mentioned program fragment using generics:

    List Lst = new LinkedList();

    Lst.add(new Integer(0));Integer in = Lst.iterator().next();

    Note the type declaration for the variable Lst . It specifies that it is not just an arbitrary Li st , but also alist of Integer, written Li st . Lets say that Li st is a generic interface that takes a type

    parameterin this case, Integer. When creating the list object, we also specify a type parameter. The otherthing to notice is movement of the cast to third line. Now, you may think that all we have achieved is tomove the clutter around.

    We have I nteger as a type parameter on first line instead of a cast to I nteger in third line. However,we can notice a very big difference here. The compiler can now check the type correctness of theprogram at compile-time. When we say that Lst is declared with type Li st , this explainsus something about the variable Lst , which holds true wherever and whenever it is used and thecompiler will ensure it. In comparison, the cast tells us something the programmer thinks is true at asingle point in the code. The net output, especially in large programs, is improved readability androbustness.

  • 7/28/2019 Appendix Afg

    3/32

    Generic Types

    Look at this statement:

    List Lst = new List(53);

    This statement generates an error (Error cant use primitive type) because while declaring an instanceof a generic type, the type argument passed to the type parameter must be a class type. You cannot use aprimitive type, such as i nt or char . With Li st it is possible to pass any class type I nteger , but youcannot pass a primitive type. Instead you can also use the type wrappers to encapsulate a primitive type.

    All instances of a generic class, regardless of what type each instance has been parameterized with, areconsidered to be the same class. A type variable is an unqualified identifier that is used in the definitionof a generic class as a placeholder. Type variables appear between the angle braces. This identifier willbe replaced (automatically) by whatever specific object type the user of the generic class plugs into thegeneric class. Take this example:

    List Lst;

    . . .List str;

    Lst = str;

    This is wrong because a reference of one specific version of a generic type is not type compatible withanother version of the same generic type. Even though Lst and st r are of type Li st , they arereferences to different types as their type parameters are different.

    The Java compiler does not actually create different versions of a generic class. What the compiler does isthat it removes all generic type information, substituting the necessary casts, to make the code behave asif a specific version of Li st has been created. In reality there is only one version of Li st that actuallyexists in your program. The process of removing generic type information is called erasure.

    Parameterized Types

    A generic class is also known as a parameterized class. Parameterized types enable you to create classes,interfaces, and methods in which the type of data upon which they operate is specified as a parameter.Using generics, it is possible to create a single class that automatically works with different types.

    The class is defined with space for one or more parameters, placed between the angle braces, where thetype of the parameters is specified during the declaration of a specific instance of the class. For the rest ofthis section, the termgeneric class will be used to refer to a parameterized class. Also note that a class oran interface in Java can be made generic. For the rest of this section, unless otherwise stated, the wordclass includes classes and interfaces.

    In the example at the start of this section, I nteger is the specific type that takes the place of the typevariable for the parameterized Ar r ayLi st . The direct super-types of a generic class are the classes inthe extends clause, if present (orj ava. l ang. Obj ect if not present), and any interfaces, if any arepresent. Therefore, in the following example, the direct super-type is Ar r ayLi st :

    class arrlist extends ArrayList { }

    The super-types of type variables are those listed in the bounds list for that type variable. If none arespecified, j ava. l ang. Obj ect is the super-type. In hierarchies of generic classes, one importantrestriction exists. To support translation by type erasure (see here for more on type erasure), a class or

  • 7/28/2019 Appendix Afg

    4/32

    Appendix A

    type variable cannot have two different parameterizations of the same class/interface at the same time.This is an example of an illegal hierarchy:

    interface BaseInterface { A getInfo(); }class app implements BaseInterface {

    public Integer getInfo() { return(null); }}

    class Childapp extends app implements BaseInterface { }

    The interface BaseI nt er f ace is first parameterized with I nteger , and later parameterized withSt r i ng. These are in direct conflict, so the compiler will issue the following error:

    c:\code\BadParents.java:14: BaseInterface cannot be inherited with different

    arguments: and class Childapp extends app implements BaseInterface { }

    1 error

    Defining Generic ClassesAs mentioned earlier, both interfaces and classes can be parameterized. Since type variables have noinherent type, all that matters is the number of type variables that act as parameters in a class. The list oftype variables appears between the angle braces (the less-than sign and greater-than sign). An exampleof changing the existing Ar r ayLi st class from a nongeneric class to a generic class changes itssignature to:

    public class ArrayList { . . . }

    The type variable here is I t emType, and can be used throughout the class as a not-yet-specified type.When an object of the class is defined, a type is specified and is plugged into the generic class by the

    compiler. The scope of a type variable extends throughout the class, including the bounds of the typeparameter list, but not including static members/methods. Each type variable can also have bounds thatplace a restriction on the type variable. The type variable can be forced to extend from a class other thanj ava. l ang. Obj ect (which it does when no extends clause is specified) or implement any number ofspecific interfaces.

    For example, if you define an interface Gr aphi cContext as part of a graphics library, you might writea specialization of a collection to only hold objects that implement the Gr aphi cContext interface. Toplace only an interface restriction on the type variable, the extends clause must be specified, even if it isonlyj ava. l ang. Obj ect . However it is possible to only list interfaces after the extends clause. If youonly list interfaces, it is implicitly understood that j ava. l ang. Obj ect is the base class of the typevariable. Note that interfaces are separated by the ampersand (&). Any number of interfaces can bespecified.

    Casts and InstanceOfAnother implication of sharing of a generic class among all its instances, is that it usually makes no senseto ask an instance if it is an instance of a particular invocation of a generic type:

  • 7/28/2019 Appendix Afg

    5/32

    Generic Types

    Collection col = new ArrayList();

    if (col instanceofCollection) { . . . }In the similar way, a cast such as:

    Collectioncolstring = (Collection) colec;

    It gives an unchecked warning, since this isnt something, which the runtime system is going to checkfor you. The same is true of type variables:

    T badCast(T t, Object ob) { return (T) ob; }

    Type variables dont exist at runtime meaning that they entail no performance overhead in either time orspace, which is a correct thing. Unfortunately, it also means that you cant reliably use them in casts.

    A Simple Program on GenericsBefore going into the more complex details of this special gener i cclass, lets take a simple exampleshown in the following code (you can find this file, genf eature. j ava on CD) in order to understandthe concept of Gener i cs :

    class defgen {G obj;

    defgen(G ob) { obj=ob; }

    G getobj() { return obj; }void displaytype() {

    System.out.println("G is having following type :- "+obj.getClass().getName()); }

    }class genfeature {

    public static void main(String args[]) {

    defgen iogen;iogen=new defgen(100);

    iogen.displaytype();

    int val=iogen.getobj();

    System.out.println("value is equal to - "+val);System.out.println (); }

    }

    Here, Gis the parameter passed to the generic class def gen. So, Gwhich is defined between the bracketswill be called as per the requirement of the programmer. Obj is the object of the type Gmeans the datatype of the obj will be the same as that of G. The constructor def gen(G ob) has the type G, whichemphasize that the ob will also possess the same data type that of G. One thing here to stress that theprimitive data types are not allowed to pass through the generic classes, although you can use the

    Wr apper class to use data types in order to access the integer or string values using the feature ofautoboxing described earlier.

    The functionG get obj ( ) is returning a value of G type object. As obj is also defined of type G. Thedi spl aytype( ) method displays the type of G by calling the methods get Name( ) and getCl ass( )

  • 7/28/2019 Appendix Afg

    6/32

    Appendix A

    on the object obj . The getCl ass( ) method returns the type of class and get Name( ) method returnsthe string representation of the class name.

    Now, comes the explanation of the mai n( ) through which the methods are used. We have created an

    object i ogen of the type def gen defined preceding and the I nteger data type of the wr apper class isbeing passed in order to access the integer values as objects. The i ogen is being initialized with anyinteger value (here 100) using thenewkeyword to allocate the memory. The methods getobj ( ) anddi spl aytype( ) are called using the object i ogen. The values passed are assigned to the variable val which is then displayed. Here we have not used any type cast in order to fetch the value of the object.The output of the preceding program is:

    G is having following type :- java.lang.Integer

    value is equal to 100

    Bounded Generic Type and WildcardsSuppose you want to create a generic class that contains a method that returns the average of an array ofany type of numbers, including integers, floats, and doubles. Lets look at this example which gives acompilation error just because the compiler has no way of knowing that you are passing only numerictypes:

    class GT {G[] bnd;

    GT(G[] t) { bnd = t; }

    double aver() {double sum = 0.0;

    for(int v=0; v < bnd.length; v++) {

    sum += bnd[v].dblValue(); // Error!!!return sum / bnd.length; }

    }

    }

    To handle such situations, Java provides bounded types. When specifying a type parameter you cancreate an upper bound that declares the superclass from which all type arguments must be derived. Thiscan be done using extends clause.

    How will extends solve the problem found earlier? You can use Number as an upper bound in order tomake the Java compiler know all objects of type G that call dbl Val ue( ) . See the following code tounderstand better (you can find this file, BndDemo. j ava on CD):

    class GT {

    G[] bnd;

    GT(G[] t) { bnd = t; }double aver() {

    double sum = 0.0;

    for(int v=0; v < bnd.length; v++)sum += bnd[v].doubleValue();

    return sum / bnd.length; }

    }class BndDemo {

    public static void main(String args[]) {

  • 7/28/2019 Appendix Afg

    7/32

    Generic Types

    Integer vnums[] = { 10, 20, 30, 40, 50 };

    GT vob = new GT(vnums);double j = vob.aver();

    System.out.println("vob average is " + j);

    Double dnums[] = { 10.1, 20.2, 30.3, 40.4, 50.5 };GT dob = new GT(dnums);

    double k = dob.aver();

    System.out.println("dob average is " + k); }}

    Heres the output:

    vob average is 30.0

    dob average is 30.3

    You can bound a generic type, for example, the showAl l , showXY, showXYZ method to display thecoordinates from the same entry. The bounded generic type specifies that E is a generic subtype ofCoords.

    An unbounded generic type is same as . Here is a small excerpt from the

    definitions of the interfaces List and Iteratorin package java.util.

    Take a look at this code to understand it better (you can find this file, gen_bound. j ava on CD):

    class TwoDim {int x, y;

    TwoDim(int a, int b) {

    x = a;y=b; }

    }

    class ThreeDim extends TwoDim {

    int z;ThreeDim(int a, int b, int c) {

    super(a,b);

    z=c; }}

    class FourDim extends ThreeDim {

    int t;FourDim(int a, int b, int c, int d) {

    super(a,b,c);

    t=d; }}

    class Coords {

    T[] crds;Coords(T[] o) { crds = o; }

    }

    class gen_bound {static void displayXY(Coords c) {

    System.out.println("X Y Coordinates:");

    for(int i=0; i

  • 7/28/2019 Appendix Afg

    8/32

    Appendix A

    static void displayXYZ(Coords

  • 7/28/2019 Appendix Afg

    9/32

    Generic Types

    3 4 5 6

    4 -3 -23 27

    This should all be familiar, except for the stuff in angle brackets. Those values are the declarations of theformal type parameters of the interfaces Li st and I terat or . Throughout the generic declaration, typeparameters can be used, where you would use ordinary types.

    In the introduction, we saw invocations of the generic type declaration Li st , such as Li st .In the invocation (usually called a parameterized type), all occurrences of the formal type parameter (inthis case, E) are replaced by the actual type argument (in this case, Integer). You may assume thatLi st stands for a version of Li st where E has been uniformly replaced by Integer:

    public interface IntegerList {

    void add(Integer x)

    Iteratoriterator();

    }

    Though this intuition can be guiding, but it

    s also misleading. It is helpful, because the parameterizedtype Li st does indeed have methods that look just like this expansion. It is misleadingbecause the declaration of a generic is actually never expanded in this way. Multiple copies of the codeare not in source, binary, disk and not even in memory. If you are a C++ programmer, youll understandthat this is very different than a C++ template.

    A generic type declaration is compiled once and for all, and turned into a single class file, just like anordinary class or interface declaration. Type parameters are analogous to the ordinary parameters usedin methods or constructors.

    A generic declaration has formal type parameters, in the same way like a method has formal valueparameters that describe the kinds of values it operates on. When a method is invoked, actual argumentsare substituted for the formal parameters, and the method body is evaluated whereas when a genericdeclaration is invoked, the actual type arguments are substituted for the formal type parameters.

    We recommend that you use pithy (single character if possible) but still evocative names for formal typeparameters. Its best to avoid lower three case characters in these names, thus, making it easy to differentiateformal type parameters from ordinary classes and interfaces. As in the preceding examples, many container

    types use Efor element, in later examples, well see some additional conventions.

    In order to make the upper bound for a wildcard type Obj ect , just write it as:

    ? extends Object

    Specifying a wildcard with an upper bound is very useful as it forces the specification to represent onlyclass types and not interface types. This way you can use this when you want to specify any type asl ong as its a class type.

    A bounded wildcard is especially important when you are creating a generic type that will operate on a

    class hierarchy. You can explicitly constrain a wildcard specification. One possibility is to specify that itextends another type. This type of constraint is described as an upper bound of the wildcard typebecause it implies that any subclass of the type that the wildcard extends is acceptable, including thetype itself. Take a look at this snippet:

  • 7/28/2019 Appendix Afg

    10/32

    Appendix A

    class TD {

    int x, y;TD(int a, int b) { x = a; y = b; }

    }

    TheTDencapsulates a two-dimensional, XY coordinate. See a generic class called coorobj , which storesan array of coordinates:

    class coorobj {

    G[] coords;

    Coords (G[] g) { coords = g; }

    }

    The Coords specifies a type parameter bounded byTD. This is an indication that any array stored in aCoords object will contain objects of type TD or one of its subclasses. Now to write a method thatdisplays the X andY coordinates for each in the coords array, the following can be done:

    static void showXY(Coords w) {System.out.println("2-D Coordinates:");

    for(int k=0; k < w.coords.length; k++)

    System.out.println(c.coords[k].x + " " + w.coords[k].y);System.out.println();

    }

    Generics and SubtypingLets now test our knowledge of generics.

    Listlstring = new ArrayList();Listlobject = lstring;

    Here Line 1 is certainly legal. The trickier part of the question is Line 2. This boils down to the question:Is a list of St r i ng, a list of Obj ect ? Most peoples instinct is to answer: sure!. Well, take a look at thenext few lines:

    lobject.add(new Object());String ls = lstring.get(0);

    Here we have aliased l st r i ng and l obj ect . Accessing l st r i ng, a list of St r i ng, through the aliasl obj ect , we can insert arbitrary objects into it. As a result, l st r i ng does not hold just St r i ngsanymore, and when we try and get something out of it, we get a rude surprise.

    Of course, the Java compiler will prevent this from happening. Line 2 will cause a compile time error.This probably is the hardest thing you need to learn about generics, because it goes against our deeplyheld intuitions. The reason for this is the assumption that collections dont change. Our instinct takesthese things to be immutable.

  • 7/28/2019 Appendix Afg

    11/32

    Generic Types

    For example, if the department of motor vehicles provides a list of drivers to the census bureau, itsounds reasonable. We think that a Li st is a Li s t , assuming that Dr i ver is asubtype of Per son. In fact, what is being passed is a copyof the registry of drivers. Otherwise, the

    census bureau could corrupt the DMV

    s records by adding new people who are not drivers into the list.In order to tackle this situation, its advisable to consider more flexible generic types. The rules we haveseen so far have limitations.

    Look into this example to understand this concept better (you can find this file, Subcl as. j ava on CD):

    class Mainclas {

    int mnum;Mainclas(int j) { mnum = j; }

    int getnum() { return mnum; }

    }class Gensub extends Mainclas {

    T item;

    Gensub(T k, int l) {super(l);

    item = k; }

    T getitem() { return item; }}

    class Subclas {

    public static void main(String args[]) {

    Gensub h = new Gensub("Black Book", 10);System.out.print(h.getitem() + " ");

    System.out.println(h.getnum()); }

    }

    Heres the output:

    Black Book 10

    Type ParametersThe generic type Li nkedLi st has a single type parameter; normally you can define a generic typewith as many type parameters as you want to. For instance, if you want to define a generic type which,defines a set of classes that encapsulates a pair of objects of arbitrary types. This would typically arisewhere one object is used to access the other in a collection.

    For example, you might store Per son objects in a collection that encapsulates personal details such asthe name, the address, and the phone number. You could associate each Per son object with a Nameobject that you use as a key to retrieve the Per son object. One way of establishing the associationbetween an object and its key would be to encapsulate both in another objectof type Pai r , say.

    How can you declare more then one type parameter in generic type? Simply use a comma-separated list.Heres the way by which we can define a generic type, Pai r , that is to be used for defining

    classes that encapsulate a key/value pair of any type:

    public class app {

    public app(KeyType key, ValueType aValue) {key = aKey;

  • 7/28/2019 Appendix Afg

    12/32

    Appendix A

    value = aValue; }

    public getKey() { return key; }public getValue() { return value; }

    public setValue(ValueType aValue) { value = aValue; }

    private KeyType key;private ValueType value;

    }

    It is quite obvious that a practical definition would be more complicated than thisyoud need a meansof comparing key objects. Take a look at this practical example that uses two type parameters (you canfind this file, Si mpGen. j ava on CD):

    class TwoPara {

    G ty1;

    T ty2;TwoPara (G g1, T g2) {

    ty1 = g1;

    ty2 = g2; }

    void DispTypes() {System.out.println("G is " + ty1.getClass().getName());

    System.out.println("T is " + ty2.getClass().getName()); }

    G getty1() { return ty1; }T getty2() { return ty2; }

    }

    class SimpGen {public static void main(String args[]) {

    TwoPara pgObj = new TwoPara(2005,

    "Parameters");pgObj.DispTypes();

    int i = pgObj.getty1();

    System.out.println("The value with integer = " + i);

    String str = pgObj.getty2();System.out.println("The value with string: " + str); }

    }

    Heres the output:

    G is java.lang.Integer

    T is java.lang.String

    The value with integer = 2005The value with string: Parameters

    Variables of Raw TypesYou may use a generic class without specifying a concrete type in the following way:

    app stack = new app();This is roughly equivalent to

    app stack = new app();

  • 7/28/2019 Appendix Afg

    13/32

    Generic Types

    You can use the generic type name by itself to define variables. The class that corresponds to the rawtype is produced by removing the type parameters from the generic type definition and replacing eachinstance of a type variable in the definition by the leftmost bound of its correspond type parameter. Thisprocess of mapping from a generic type to non-generic type is called type erasure because all occurrenceof a type variable are effectively erased from the generic class definition. A raw type exists as aconsequence of implementing generic types using type erasure.

    In the absence of any explicit type parameter bound, every type parameter T is implicitly bounded bytype object. All occurrence ofT in a generic type definition will be replaced by object to produce the rawtype. This is important for interface type such as i t er abl e and compar abl e in the standardpackage. Interface in the standard package that defined methods are generally defined as generic typefor maximum flexibility. When you implement such interface in an ordinary class without specifying atype argument, your class is implementing the raw type, so the method in the interface will be declaredwith parameters and/ or return type of type object.

    Backward CompatibilityGener i cSt ack class used without a type parameter is called a raw type. The raw type is allowed for

    backward compatibility with the prior versions of JDK. For example, generic type is used inj ava. l ang. Comparabl e, but a lot of code is still using the raw type Compar abl e as shown here:

    public class app {

    public static Comparable max(Comparable com1, Comparable com2) {if (com1.compareTo(com2) > 0) { return com1; }

    else { return com2; }

    }

    Here Compar abl e com1 and Compar abl e com2 are raw type declarations. Raw type is unsafe. Forexample, you may invoke the max method using:

    app.max("Welcome", 23);

    A runtime error will be shown because you cant compare a string with an integerobject. The compiler displays a warning on Line 5 when compiled with the optionXlint:unchecked

    A better way to write the max method is to use a generic type, as shown in next code. If you invoke themax method using:

    app1.max("Welcome", 23);

    It will give you a compilation error because in app1 two arguments of the max method must have thesame type (e.g. two strings or two integer objects):

    public class app1 {

    public static E max(E com1, E com2) {

    if (com1.compareTo(com2) > 0) { return com1; }else { return com2; }

    }

  • 7/28/2019 Appendix Afg

    14/32

    Appendix A

    For example, you may declare a raw type stack in Line 1, assign new appto it in Line 2, andpush a string and an integer object to the stack in Lines 3 and 4:

    app stack;stack = new app();

    stack.push("Welcome to Java");

    stack.push(new Integer(2));

    Line 4 is usually unsafe because here the stack is supposed to store St r i ng, but an I nteger object isadded into the stack. Line 3 should be OK, but the compiler will show warnings on both Lines 3 and 4,as it cant follow the semantic meaning of the program. What the compiler knows is that stack is a rawtype and it is unsafe to perform certain operations. Therefore, warnings are shown to alert potentialprograms.

    WildcardsWe can define a particular type from the set defined by a generic type by supplying a type argument for

    each of its type parameter. To understand this lets take an example, to specify the Bi naryTr eetypethat stores objects of type string, you specify the type argument as string so the type isBi nar yTree. Instead of supplying a specific type as the type argument for the generic type,you can specify the argument as ? (wildcard), in which case you have specified the type argument as aWildcard. A wildcard represents any class or interface type. You can declare variable of a generic typeby using a wildcard type argument.

    For example:

    BinaryTree bt = new BinaryTree();

    Here well consider some of the more advanced uses of wildcards. We have seen how wildcards wereuseful when reading from a data structure. Now consider the inverse, a write-only data structure. Theinterface Si nk is a simple example of this sort:

    interfaceSink { flush(T t); }We can imagine using it as demonstrated by the code here. The method wr i t eAl l ( ) is designed toflush all elements of the collection col to the sink snk, and return the last element flushed:

    public static T writeAll(Collection col, Sink snk) {

    T last;

    for (T t : col) {last = t;

    snk.flush(last); }

    return last;} . . .

    Sink s;

    Collection collec;

    String strng = writeAll(collec, s);

  • 7/28/2019 Appendix Afg

    15/32

    Generic Types

    As written, the call to wr i t eAl l ( ) is illegal, as no valid type argument can be inferred; neither St r i ngnor Obj ect are appropriate types forT, because the Col l ect i on element and the Si nk element mustbe of the same type.

    We can fix this by modifying the signature of wr i t eAl l ( ) as shown here, using a wildcard:

    public static T writeAll(Collection

  • 7/28/2019 Appendix Afg

    16/32

    Appendix A

    public static

    T max(Collection coll)

    That is, the method takes a collection of some typeT that is comparable to it, and returns an element ofthat type. This turns out to be too restrictive. To see why, consider a type that is comparable to arbitraryobjects:

    classtrial implementsComparable { . . . } . . .Collection coltr = . . .;

    Collections.max(coltr);// should work

    Every element of col t r is comparable to every other element in col t r , since every such element is at ri al , which is comparable to any object, and in particular to another trial. However, using thesignature preceding, we find that the call is rejected. The inferred type must be trial, but trial does notimplement Comparabl e. It isnt necessary thatT be comparable to exactly itself. All thatsrequired is that T be comparable to one of its super types. This gives us the actual signature of

    Col l ect i ons. max( ) which is more involved:

    public static

  • 7/28/2019 Appendix Afg

    17/32

    Generic Types

    Declaration as per JDK 1.5 and later:

    package java.lang;

    public interface Comaprable{ public int compareTo(T o) }

    New DeclarationA definition of generic type looks very much like the definition of an ordinary class, but with aparameter specification with the class name. The parameter that appears between the angled bracket,follows the generic type name, is called a type parameter. Here, represents a formal generic type,which can be replaced with an actual concrete type later. The name,T, identifies the type parameter, andwe use the parameter name in the definition of the methods and fields in the generic type where there isa dependency on the arguments value for this parameter in the implementation detail.

    Occurrences of the type parameter name in the definition of a generic type are called type variablesbecause they will be replaced by a value that is a type, in a similar way to how method parameters are

    replaced by the arguments that you supply.

    To create a class from the generic type, you just supply an appropriate argument for the parameterbetween the angled brackets. All the occurrences of the type, T that appears in the definition will bereplaced by the type argument that you supply. This will result in a class type that you can use to createan object that implements a linked list that will store objects of the type that you specified as shown inthe Figure A. 1.

    Thus, a generic type essentially defines a set of typesthe set being produced by different arguments forthe parameters or parameters for the generic type. This is to note at this stage that the Figure A.S.1shows three types being defined, there arent three classes. There are just the generic class types to whichyou supply a type argument to produce a particular type. The three types in Figure A. 1 are produced byplugging the three type arguments shown into the generic type.

    You can supply only a class or interface type such as type St r i ng or type Poi nt as an argument for atype parameter in a generic type. In other words, you cannot use a primitive type such as i nt or typedoubl e as an argument, although, of course, you can use type I nteger or type Doubl e. When youcreate a particular type from the generic type definition by supplying an argument value for T, theargument will be substituted for every occurrence ofT in the generic type specification. This applies tofield as well as the definitions of methods in the generic type.

    Figure A.1: Showing three classes.

  • 7/28/2019 Appendix Afg

    18/32

    Appendix A

    For example, the following statement declares that s is a reference variable whose type isCompar abl e:

    Comparable s = "Hello All! Welcome to Java 1.5";

    So, you can assign a string to s since St r i ng implements Compar abl e, but you cannot assign ani nteger object to s (such as s = new I nteger (1)), even though I nteger implements Compar abl e.

    The StackOf I nt eger s Class (Optional) is used to generalize the element type with a generic type. Thenew stack class named Gener i cSt ack is given here:

    public class GenericStack {

    private E[] elements;private int size;

    public app() { this(16); }

    public app(int capacity) { elements = (E[])new Object[capacity]; }public E push(E value) {

    if (size >= elements.length) {

    E[] tmp = (E[])new Object[elements.length * 2];System.arraycopy(elements, 0, tmp, 0, elements.length);elements = tmp; }

    return elements[size++] = value; }

    public E pop() { return elements[--size]; }public E peek() { return elements[size - 1]; }

    public boolean empty() { return size == 0; }

    public int getSize() { return size; }

    }

    The class declaration has the formal parameter defined . The class uses the el ement s as object tostore the items in the stack. The push method accepts a parameter of type E. The pop method returns thevalue of type E. If the array is empty then the pop method returns null. The peek method also returnsthe value of type E. The get Si ze method returns the arrays length.

    Heres an example that gives rise to a stack to hold strings and adds three strings to the stack:

    app stack = new app();stack.push("Washington DC");

    stack.push("Las Vegas");

    stack.push("New York");

    Heres another example that generates a stack to hold integers and adds three integers to the stack:

    app stack = new app();

    stack.push(1); stack.push(2);stack.push(3);

    InteroperabilityThe Novice Programmer says Here we are assuming that everyone is using the latest version of the Javaprogramming language, which supports generics, unfortunately, this isnt the case. Millions of lines of

  • 7/28/2019 Appendix Afg

    19/32

    Generic Types

    code have been written in earlier versions of the language, and these all cannot be converted overnight.So in this situation what can be done? You say, Well tackle this situation by converting the old code tothe generics.

    In this part, well focus on a simpler problem how can legacy code and generic code interoperate? This

    has two parts: using legacy code in generic code, and using generic code within legacy code.

    Using Legacy Code in GenericsHow can you use old code, while you are still enjoying the benefits of generics in your own code? Forexample, assume that you want to use the package gener i ccode. The folks at abc. commarket asystem for inventory control, highlights of which are shown here:

    package genericcode;

    public interface Part { . . . }public class Inventory {

    public static void addAssembly(String name, Collection parts) { . . . }

    public static Assembly getAssembly(String name) { . . . }

    }public interfaceAssembly { Collection getParts(); }

    Now, youd like to add new code that uses the preceding-mentioned API. It would be nice to ensure thatyou always called addAssembl y( ) with the proper arguments (abc.com is a purely fictional company,used for illustration purposes. Any relation to any real company or institution, or any persons living ordead, is purely coincidental). The collection you pass in is indeed a Col l ect i on of Par t . Of course,generics are tailor-made for this:

    package inventory;

    import genericcode.*;

    public class Blade implements Part { . . . }

    public class Razor implements Part { }public classMain {

    public static voidmain(String[] args) {Collection col = new ArrayList();col.add(new Razor()) ;

    col.add(new Blade());

    Inventory.addAssembly(thingee, col);

    Collection kol = Inventory.getAssembly(thingee).getParts();}}

    When we call addAssembl y, the second parameter should be of type Col l ect i on. The actualargument is of type Col l ect i on. This works, but why? After all, most of the collections dontcontain Part objects, and so in general, the compiler never knows what kind of collection the typeCol l ect i on refers to. In proper generic code, Col l ect i on would always be accompanied by a typeparameter. When it does not happen, its called a raw type.

    The first perception of man people is that Col l ect i on really means Col l ect i on. However,

    as explained earlier, it isnt safe to pass a Col l ect i on in a place where aCol l ect i on is required. In reality, the type Col l ect i on denotes a collection of some

    unknown type, just like Col l ect i on. But wait, that cant be right either!

  • 7/28/2019 Appendix Afg

    20/32

    Appendix A

    Consider the call to getParts() , which returns a Col l ect i on. This is then assigned to kol , which is aCol l ect i on. If the result of the call is a Col l ect i on, the assignment would be an error.In reality, the assignment is legal, but it generates an unchecked warning. The warning is needed, because

    the compiler can

    t guarantee its correctness. In getAssembl y( ) , we have no way of checking the legacycode to ensure that the collection being returned is a collection of Parts. The type used in the code isCol l ect i on, and in such a collection, one can legally insert all kinds of objects. So, shouldnt this be anerror? Theoretically, yes; but practically, if generic code is going to call legacy code, this has to beallowed. Its up to the programmer, to satisfy yourself that in this case, the assignment is safe becausethe contract of getAssembl y( ) says it returns a collection of Parts, even though the type signaturedoesnt show this.

    So, raw types are very much like wildcard types, though not type-checked as stringently. To allowgenerics to interoperate with pre-existing legacy code, it is a deliberate design decision. It is inherentlydangerous to call legacy code from generic code; once you mix generic code with non-generic legacycode. All the safety guarantees that the generic type system usually provides are voi d. But, you are stillbetter off than you were without using generics at all because at least you know that the code at yourend is consistent.

    At this moment of time, there are a lot more non-generic codes than the generic codes, and there willinevitably be situations where they have to mix. You have to pay close attention to the uncheckedwarnings if you find that you must intermix legacy and generic code. Think carefully how you can

    justify the safety of the code that creates the warning.

    Using Generic Code within Legacy CodeNow lets reverse our case. Suppose that abc. comchose to convert their API to use generics, but thatsome of their clients are not interested in doing so. So now the code of supplier looks like:

    package genericcode;

    public interface Part { . . . }

    public class Inventory {public static void addAssembly(String name, Collection parts) {...}

    public static Assembly getAssembly(String name) {...}}public interface Assembly { Collection getParts(); }

    And the code of client appears like:

    packageinventory;import genericcode.*;public classBlade implements Part { ... }public classRazor implements Part { }public classMain {

    public static voidmain(String[] args) {Collection col = new ArrayList();

    col.add(new Razor()) ;col.add(new Blade());

    Inventory.addAssembly(thingee, c);Collection kol = Inventory.getAssembly(thingee).getParts(); }

    }

  • 7/28/2019 Appendix Afg

    21/32

    Generic Types

    Though the client code was written before introduction of generics, but it uses the packagegener i ccodeand the collection library, both of which are using generic types. So we can say that allthe uses of generic type declarations in the client code are raw types.

    Line 1 gives an unchecked warning, because a raw Col l ect i on is being passed in where aCol l ect i on of Parts is expected, and the compiler cannot guarantee that the raw Col l ect i on reallyis a Col l ect i on of Parts.

    Alternatively, you can compile the client code using the source 1.4 flag, ensuring that no warnings aregenerated. However, in that case, you wont be able to use any of the new language features introducedin JDK 1.5.

    Erasure and TranslationNovice Programmer asks, Why was generics implemented in Java? You say, Need for compatibilitywith previous version of Java was the need of the hour.

    Simply put, generic code had to be compatible with pre-existing, non-generic code. The way Javaimplements generics while satisfying this constraint is through the use of erasure. Even though it is not

    necessary to know how the Java compiler transforms the source code into object code, in the case ofgenerics, some general understanding is necessary. Now take a look at this code:

    publicString holes(Integer i) {List lst = new LinkedList();

    List xst = lst;

    xst.add(i);returnlst.iterator().next();

    }

    Here, we have aliased a list of strings and a plain old list. We insert an I nteger into the list, andattempt to extract a St r i ng. This seems to be wrong. If we try to execute this code ignoring thewarning, it will fail exactly at the point where we try to use the wrong type. At runtime, this codebehaves like:

    publicString holes(Integer i) {List lst = new LinkedList;

    List xst = lst;xst.add(i);

    return(String) lst.iterator().next();}

    When an element is extracted from the list, and an attempt is made to treat it as a string by casting it toSt r i ng, well get a Cl assCast Except i on. Same thing happens with the generic version of hol es() . The reason behind this is that generics are implemented by the Java compiler as a front-end conversioncalled erasure. You can (almost) think of it as a source-to-source translation, whereby the generic versionof hol es( ) is converted to the non-generic version.

    As a result, even in the presence of unchecked warnings, the type safety and integrity of the Java virtualmachine are never at risk. Basically, erasure gets rid of (or erases) all generic type information. All thetype information between angle brackets is thrown out, for example, a parameterized type likeLi st is converted into Li st . All remaining uses of type variables are replaced by the upper

  • 7/28/2019 Appendix Afg

    22/32

    Appendix A

    bound of the type variable (usually Obj ect ). And, whenever the resulting code isnt type-correct, a castto the appropriate type is inserted, as in the last line of holes.

    Its good to know a little bit about erasure, especially when you want to do more complicated things, for

    example, converting existing APIs to use generics, or just want to understand why things are the waythey are.

    Wildcard Parameterized TypeYou express a particular type from the set defined by a generic type by supplying a type argument foreach of its type parameters. For example, take the problem of writing a routine, which prints out all theelements in a collection. Heres how you might write it in an older version of the language:

    void printCollection(Collection col) {

    Iterator x = col.iterator();for (k = 0; k < c.size(); k++) { System.out.println(x.next()); }

    }

    And heres a naive attempt at writing it using generics (and the new for loop syntax):

    void printCollection(Collection col) {

    for (Object x : col) { System.out.println(x); }

    }

    The problem is that this new version is much less useful than the old one. Whereas the old code could becalled with any kind of collection as a parameter, the new code only takes Col l ect i on,which, as we have just demonstrated, is not a super type of all kinds of collections!

    So what is the super type of all kinds of collections? It s written Col l ect i on (pronouncedcollection of unknown), that is, a collection whose element type matches anything. Its called a wildcardtype for obvious reasons. We can write:

    void printCollection(Collection col) {

    for (Object x : col) { System.out.println(x); }}

    Now, we can call it with any type of collection. Notice that inside pri ntCol l ect i on( ) , we can stillread elements from c and give them type Obj ect . This is always safe as it does contain objects whateveris the actual type of the collection. However, it isnt safe to add arbitrary objects to it:

    Collection col = new ArrayList();

    col.add(new Object());

    We cant add objects to it, since we dont know for what the element type of col stands. The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is?, it stands for some unknown type. Any parameter we want to add should be a subtype of thisunknown type. Since we dont know the type of that, we cant pass anything in. The sole exception isnull, which is a member of every type. On the other hand, given a Li st , we cancall get() andmake use of the result. The result type is an unknown type, but we always know that it is an object.

  • 7/28/2019 Appendix Afg

    23/32

    Generic Types

    Therefore, it is safe to assign the result of get() to a variable of type Obj ect or pass it as a parameterwhere the type Obj ect is expected.

    Arrays of Variables of a Parameterized TypeThe component type of an array object may not be a type variable or a parameterized type, unless it is a(unbounded) wildcard type. You can declare array types whose element type is a type variable or aparameterized type, but not array objects. This is annoying, to be sure. This restriction is necessary toavoid situations like:

    List[] lsa = new List[10];

    Object o = lsa;

    Object[] ob = (Object[]) o;

    List lst = new ArrayList();lst.add(new Integer(3));

    ob[1] = lst;

    String s = lsa[1].get(0);

    If arrays of parameterized type were allowed, the preceding example would compile without anyunchecked warnings, and yet fail at runtime. We have had type-safety as a primary design goal ofgenerics. In particular, the language is designed to guarantee that if your entire application has beencompiled without unchecked warnings usingj avac -source 1.5, it is type safe.

    However, you can still use wildcard arrays. Here are two variations on the previous code. The firstforgoes the use of both array objects and array types whose element type is parameterized. As a result,we have to cast explicitly to get a St r i ng out of the array:

    list[] lsa = new List[10];

    Object o = lsa;

    Object[] ob = (Object[]) o;List lst = new ArrayList();

    lst.add(new Integer(3));ob[1] = lst;String s = (String) lsa[1].get(0);

    In the next variation, we refrain from creating an array object whose element type is parameterized, butstill use an array type with a parameterized element type. This is legal, but generates an uncheckedwarning. Indeed, the code is unsafe, and eventually an error occurs:

    List[] lsa = new List[10];Object o = lsa;

    Object[] ob = (Object[]) o;

    List lst = new ArrayList();lst.add(new Integer(3));

    oa[1] = lst;

    String s = lsa[1].get(0);

    Similarly, attempting to create an array object whose element type is a type variable causes a compile-time error:

  • 7/28/2019 Appendix Afg

    24/32

    Appendix A

    T[] makeArray(T t) { return new T[100]; }

    Since type variables don

    t exist at runtime, there is no way to determine what the actual array typewould be. The way to work around these kinds of limitations is to use class literals as runtime typetokens.

    As of the time of this writing, arrays of generic types and arrays of type variables are not allowed.Attempting to create an array of parameterized Vectors , for example, causes a compiler error:

    import java.util.*;public class GenericArrayExample {

    public static void main(String args[]) {

    Vector vectorList[] = new Vector[10]; }

    }

    If you try to compile that code, the compiler issues the following two errors. This code is the simplestapproach to creating an array of a generic type and the compiler tells you explicitly that creating a

    generic type array is forbidden:

    GenericArrayExample.java:6: generic array creationVector vectorList[] = new Vector[10];

    ^

    1 error

    Generic ConstructorsA constructors is a specialized kind of method and you can define class constructors with their ownindependent parameters. You can define parameterized constructors for both ordinary classes andgeneric class type. Lets take an example.

    Let say, you want to add a constructor to the Bi naryTr ee type definition that will accept anargument that is an array of items to be added to the binary tree. In this case, defining the constructor asa parameterized method gives you the same flexibility you have with the add( ) method. Heres howthe constructor definition looks:

    public BinaryTree(E[] treeitems) {for(E treeitem : treeitems) { add(treeitem); }

    }

    The constructor parameter is E. You have defined this with an upper bound ofT, so that argument to theconstructor can be an array of elements of the type specified by the type variableT or any subclass ofT.For example, if you define a binary tree of type Bi nar yTree, then you can pass an array tothe constructor with elements of type Per son or any type that is a subclass of Per son.

    Lets understand this with the help of an example. The definition of Bi naryTr eewill be as follows:

    public class app,T extends Comparable> {no-arg constructor

    public app() { }

  • 7/28/2019 Appendix Afg

    25/32

    Generic Types

    parameterized constructor

    public BinaryTree(E{ } treeitems) {for(E treeitem : treeitems) { add(treeitem); }

    }

    //Add a value to the treepublic void add (E val) {

    if(root == null { root = new Node (val); }

    else { }}

    //Recursive insertion of an object

    private void add(E val, Node n) {int comparison = n.obj.compareTo(val);

    if(comparison == 0) {

    ++n.count;return; }

    if(comparison > 0) {

    if(n.left ==null) { n.left = new Node(val); }else { add(val, n.left); }

    }

    else { if (n.right == null) { n.right = new Node(val); }

    else { add (val, n.right); }

    }}

    Create a list containing the values from the tree in sequence:

    Public linkedList sort() {

    treeSort(root);return val;

    }

    The only change from the previous version are the addition of the constructor that accepts an array as an

    argument and the definition of the no-org constructor, which is not supplied by the compiler when youexplicitly define a constructor of your own.

    Because the constructor has an independent parameter and that parameter has the type variable for theBi naryTr ee type as its upper bound, the constructor accepts the managers array as the argumentbecause it is a subclass of Per son, the type argument that you use to specify the type of the binary treeobject.

    The output shows that the array elements were added to the binary tree and were successfully extractedand stored in sequence in a linked list by the sor t ( ) method. Consider this small program whichshows the possibility for constructors to be generic:

    import java.util.*;

    class constr {

    private double val;

    constr(T arg) { val = arg.doubleValue(); }void showval() { System.out.println("Constructor value: " + val); }

    }

    class constrDemo {public static void main(String args[]) {

    constr test = new constr(90);

  • 7/28/2019 Appendix Afg

    26/32

    Appendix A

    constr test2 = new constr(33.5F);

    test.showval();test2.showval(); }

    }

    Heres the output:

    Constructor value: 90.0

    Constructor value: 33.5

    Generic MethodsThe Novice Programmer says, Can we declare generic interfaces and classes and use generic types todeclare generic methods. You say, yes we can explain it by taking an examplea generic methodpri nt (Lines 1014) to print an array of objects. Line 6 passes an array of integer objects to invoke thegeneric print method whereas Line 7 invokes print with an array of strings (you can find this code file,

    gen_met . j ava on CD):

    public class gen_met {public static void main(String[] args ) {

    Integer[] integers = {1, 2, 3, 4, 5};

    String[] strings = {"Melbourne", "Moscow", "Rome", "Cairo"};

    print(integers);print(strings); }

    public static void print(E[] list) {

    for (int i = 0; i < list.length; i++)System.out.print(list[i] + " ");

    System.out.println(); }

    }

    Heres the result:

    C:\java gen_met

    1 2 3 4 5Melbourne Moscow Rome Cairo

    Consider writing a method that takes an array of objects and a collection and puts all objects in the arrayinto the collection. Here is a first attempt:

    static void fromArrayToCollection(Object[] ob, Collection col) {

    for(Object ob : a) { col.add(ob); }}

    By now, youll have learned to avoid the beginner

    s mistake of trying to use Col l ect i on, asthe type of the collection parameter. You may or may not have recognized that using Col l ect i on

    isnt going to work either. Recall that you cannot just shove objects into a collection of unknown type.The way to do deal with these problems is to use generic methods. Just like type declarations, methoddeclarations can be generic that is, parameterized by one or more type parameters:

  • 7/28/2019 Appendix Afg

    27/32

    Generic Types

    static void fromArrayToCollection(T[] atcol, Collection col) {

    for (T o : atcol) { col.add(o); }}

    We can call this method with any kind of collection whose element type is a super type of the elementtype of the array:

    Object[] ob = new Object[100];

    Collection col = new ArrayList();

    fromArrayToCollection(ob, col);String[] sst = new String[100];

    Collection colst = new ArrayList();

    fromArrayToCollection(sst, colst);

    fromArrayToCollection(sst, col);

    Integer[] i = new Integer[100];

    Float[] f = new Float[100];

    Number[] n = new Number[100];

    Collection coln = new ArrayList();fromArrayToCollection(i, coln);

    fromArrayToCollection(f, coln);

    fromArrayToCollection(n, coln);

    fromArrayToCollection(n, col);

    fromArrayToCollection(n, colst);

    Notice that we dont have to pass an actual type argument to a generic method. The compiler infers thetype argument for us, based on the types of the actual arguments. It will generally infer the most specifictype argument that will make the call type-correct. One question that arises is: when should we usegeneric methods, and when should we use wildcard types? To understand the answer, let s examine afew methods from the Col l ect i on libraries:

    interface Collection {

    public boolean containsAll(Collection col);public boolean addAll(Collection

  • 7/28/2019 Appendix Afg

    28/32

    Appendix A

    isnt such a dependency, a generic method should not be used. It is possible to use both generic methodsand wildcards in tandem. Here is the method:

    Collections.copy():class Collections {

    public static void copy(List dst, List

  • 7/28/2019 Appendix Afg

    29/32

    Generic Types

    a[i] = a[j];

    a[j] = temp;}

    The syntax for the parameters in a generic method is the same as that for generic classes. Type variablescan have bounds just like they do in class declarations. Two methods cannot have the same name andargument types. If two methods have the same name and argument types, and have the same number oftype variables with the same bounds, then these methods are the same and the compiler will generate anerror.

    Parameterized Types and InheritanceThe Novice Programmer says Ok, now tell me can we define a class as a subclass of a class type that isan instance of a generic type. You say, Of course we can, lets go through the following example tounderstand this.

    You could derive a new class from type Li nkedLi st or from type Bi naryTree.Methods and fields will be inherited from the base class in the usual way. However, you can encountercomplications because of the way the compiler translates methods that involve type arguments intobytecodes, so lets first understand that process.

    The method that involves parameter and/or the return value type specified by a type argument istranslated by the compiler to a method with the same name, but with the type of each parameter whosetype is a type variable replaced by its left most bound. Casts are inserted in the body of the translatedmethod wherever necessary to produce the actual type required. You will find this in an example thatclarifies this.

    We had already seen the version of the Li nkedl i st type defined as:

    public LinkedList {

    public void addItem(T listitem) { }

    }

    If you define an object of type Li nkedl i st , notionally the addI tem( ) method for theobject is like this:

    public void addItem(String itemstring) { }

    However, the compiler will translate the addI tem( ) method to the following:

    public void addItem(Object itemobject) { }

    Normally you dont need to be aware of this. However, suppose you derive a new class from typeLi nkedl i st :

    public class SpecialList extends LinkedList {public void addItem(String itemstring) {}

    }

  • 7/28/2019 Appendix Afg

    30/32

    Appendix A

    Speci al Li st class inherited from Li nkedl i st has a method addi tem( ) , which willoverwrite the addi tem( ) method available in Li nkedl i st class. Because of the difference inparameter type of both the methods, compiler will not be able to overwrite the addi t em( ) method of

    base class, i.e. Li nkedl i st class. Parameter of the addi tem( ) method of the Li nkedl i st class is ofobject type whereas parameter of the addi tem( ) method of the Speci al Li st class is of St r i ng type.To fix the problem the compiler will create a br i dge method in your derived special class that will looklike:

    public void addItem(Object itemobject) { addItem((String)itemobject); }

    The effect of the br i dge method is to convert any calls to the inherited version of addI tem( ) to a callto your version, thus making your overwrite of the base class method effective.

    However, the approach addopted by the compiler has implications for you. You must take care not todefine methods in your derived class that have the same signature as an inherited method. Since thecompiler changes the parameter types and return types involving type variables to their bounce, youmust consider the inherited methods in these terms when you are defining your derived class methods.

    If a method in a class that you have derived from the generic type has the same signature as the erasureof an inherited method, you code will not compile.

    Benefits of Using Generic TypesInstead of using a generic type, you could simply make the type element Object that may accommodateany object type. However generics reduce the need to cast references back to the actual types of theobject, and improve the software readability and robustness.

    The frequency of Cl assCast Except i ons will be reduced because the compiler will catch type errorsat compile time rather than at runtime. Errors caught by the compiler are a good thing; runtimeexceptions are not as good.

    Additionally the need to surround casts with i f ( R i nst anceof ) is also gone. The addition ofparameterized types allows you to create code that is geared to collections of objects of a single specific

    type.The following example doesnt need to check type or cast, and the code is cleaner because of this. Thisstatic method filters all values larger than a given cap out of any given collection of I nt egers:

    public static void capiLst (Collection list, int cap) {Iterator rep = list.iterator();

    while (rep.hasNext()) {if(rep.next().intValue() > cap) { rep.remove(); }

    }}

    Notice theres no need for the author of this method to cast Obj ect to I nt eger ; the compiler will takecare of it. In case the user attempts to pass the wrong type of object, it will be refused by the compiler,giving a cannot be applied compiler error.

    When the same code is rewritten without a generic collection, it would require you to cast each elementretrieved from the collection. This is not a problem, but the generic example is cleaner as compared tothe one without.

  • 7/28/2019 Appendix Afg

    31/32

    Generic Types

    Suppose the same method is included here but without the addition of generics. Notice the cast in thei f - statement and the use of i nst anceof to check the type before using it as an I nteger :

    public static void capiLst (Collection list, int cap) {Iterator rep = list.iterator();

    Object R = null;

    while (rep.hasNext()) {R = rep.next();

    if ( R instanceof Integer && ((Integer)R).intValue() > cap) {rep.remove(); }

    }}

    Code developers will use generics to make code more flexible in more than just collections.

    Generic Type Limitation

    There are few limitations that you need to keep in mind when using generics. They involve creatingobjects of a type parameter exceptions arrays and static members. We can examine these one by one.

    Type Parameters cant be InstantiatedYou cannot create an instance by using a generic type parameter. For example consider this class:

    class Genric {

    T obj;

    Genric() { obj = new T(); }}

    Here we cannot create an instance ofT. The reason should be easy to understand becauseT does notexist at runtime. It means the compiler is unable to understand, what type of object to create. Here, the

    one point to be understood is that erasure removes all type parameters during the compiler process.

    Restrictions on Static MembersNo static member can use a type parameter declared by the enclosing class. For example, all of the staticmembers of this class are illegal:

    class Genillegal {

    static T obj;

    static T getobj() { return obj; }static void displayobj() { System.out.println(obj); }

    }

    Although here we are not declaring static members that use a type parameter declared by the enclosing

    class but we can declare static generic method, which define their own type parameters.

  • 7/28/2019 Appendix Afg

    32/32

    Appendix A

    Restrictions on Generic ArraysIn arrays, there are two important generic restrictions. First you cannot instantiate an array whose basetype is a type parameter. Second, you cannot create an array of type specific generic references. Theprogram here shows both the situations:

    class Genric {

    T obj;T values[];

    Gen(T obt, T[] nums) {

    obj = obt;values = nums; }

    }

    class GenArr {

    public static void main(String args[]) {Integer num[] = { 1, 2, 3, 4, 5};

    Genric iobj = new Genric(50, num);

    Genric gns[] = new Genric[10]; }

    }

    As the program shows, it is valid to declare a reference to an array of type, as this line does:

    T values[];

    But, you cannot instantiates an array ofT, as this commented-outline attempt:

    // values = new T[10];

    The reason you cannot create an array ofT is thatT does not exist at runtime, so there is no way for thecompiler to know what type array to actually create.

    Restrictions of Generic ExceptionsA generic class cannot extendThrowabl e. This means that you cannot create generic exception classes.So, similar to generic classes, generic interfaces and generic methods, the creation of a generic exceptionclass is not possible.

    This appendix updates reader with the new extension to the Java programming language i.e.introduction of generics. A generic type is known as parameterized type. This helps in creating generalclasses, interfaces and methods which can be used for any data type. The type on which the genericclasses, interfaces and methods work, is passed as parameter. The use of generics improves readabilityand robustness of the code. It reduces the chances of Cl assCast Except i ons as all type errors arecaught at compile time. With all benefits, the generic comes with some limitations too, which also havebeen discussed in the appendix.