Presentation is loading. Please wait.

Presentation is loading. Please wait.

Java Generics. 2 The Dark Ages: Before Java 5 Java relied only on inclusion polymorphism  A polymorphism code = Using a common superclass Every class.

Similar presentations


Presentation on theme: "Java Generics. 2 The Dark Ages: Before Java 5 Java relied only on inclusion polymorphism  A polymorphism code = Using a common superclass Every class."— Presentation transcript:

1 Java Generics

2 2 The Dark Ages: Before Java 5 Java relied only on inclusion polymorphism  A polymorphism code = Using a common superclass Every class is a subclass of java.lang.Object  So there's always at least one common superclass Collections were actually collections of objects  You can put anything into a collection  When you extract something, its static type is Object

3 3 Java 5 and Beyond Parametric polymorphism introduced in Java 5  September 2004  Most significant enhancement since Java's birth May resemble C++ templates, but:  Implemented differently  “Compile once and for all”  Better error messages  Type constraints are explicit  Less power (e.g., cannot inherit from a type parameter)‏  Parameters can only be types  No executable blowup

4 4 Generics – Before and After // Without generics List list = new ArrayList(); list.add(new Integer(0)); Integer x = (Integer) list.get(0); // Programmer must downcast list.add("abc"); Integer y = (Integer) list.get(1); // Run -time exception // With Generics – The compiler “knows” the type of the list elements List list = new ArrayList (); list.add(new Integer(0)); Integer x = list.get(0); list.add("abc"); // Compiler Error – Expected ineteger

5 5 A Generic Method public static List dup(T t, int n) { List result = new ArrayList (); for(int i = 0; i < n; ++i)‏ result.add(t); return result; }... List list = dup("abc", 2); // Implicit instantiation // Explicit not supported...

6 6 Recap: java.lang.Integer, Number package java.lang; public abstract class Number { public abstract int intValue(); public abstract long longValue(); public abstract float floatValue(); public abstract double doubleValue(); public byte byteValue() { return (byte) intValue(); } public short shortValue() { return (short) intValue(); } } package java.lang; public final class Integer extends Number { private final int n; public Integer(int v) { n = v; } public int intValue() { return n; } public long longValue() { return (long) n; } public float floatValue() { return (float) n; } public double doubleValue() { return (double) n; } }

7 7 The Cell class public class Cell { private T value; public T get() { return value; } public void set(T t) { value = t; } // T is at least an Object, so it supports toString() ‏ public String toString() { return value.toString(); } }

8 8 Using Cell Using Cell static void main(String[] args) { Cell ci = new Cell (); ci.set(new Integer(5)); System.out.println(ci.get()); int n = ci.get(); // auto-unboxing n = n*n; ci.set(n); // auto-boxing System.out.println(ci.get()); Cell cn = new Cell (); cn.set(ci.get()); }

9 9 Type Parameters with Upper Bounds public class NumberCell { private T value; public T get() { return value; } public void set(T t) { value = t; } public String toString() { return value.toString(); } // T is at least a Number, so it supports intValue() ‏ public int sum(int x) { return value.intValue() + x; } } The extend keyword specifies an upper bound for T  Can be used with both classes and interfaces Can have multiple bounds:  T extends MyClass & MyInterface

10 10 Cell is not compatible with Cell Cell is not compatible with Cell static void assign(Cell co, Object o) { co.set(o); } void main() { Cell ci = new Cell (); assign(ci, new Integer(10)); // Compiler error: // Cannot convert from Cell to Cell // Otherwise, the following code would break at run time assign(ci, "abc"); Integer n = ci.get(); System.out.println(n.intValue()); } The same conformance issue as with covariant input arguments

11 11 A better version of assign() static void assign(Cell co, T o) { co.set(o); } void main() { Cell ci = new Cell (); assign(ci, new Integer(10)); // Now it works }

12 12 The Wildcard: The Wildcard: static > boolean isNullA(C c) { T t = c.get(); return t == null; } static > boolean isNullB(C c) { return c.get() == null; } static boolean isNullC(Cell c) { return c.get() == null; } If a type parameter is used exactly once – and this occurrence is inside an upper bound – it can be replaced with a wildcard If a type parameter is used exactly once – and this occurrence is as a type of formal parameter of the method – it can be replaced with its upper bound

13 13 Wildcard: Type Checking Rules static boolean isNullC(Cell c) {... } Inside isNullC() :  ? Cannot be used to declare the type of a variable  c.get() return an Object  c.set(o) is not allowed, even if o is of type Object. Exception to this rule: c.set(null) is allowed For every type Y, the type X is a supertype of X

14 14 Lower Bounds public static class Cell { private T value; public T get() { return value; } public void set(T t) { value = t; } public void copyTo(Cell c) { c.set(value); } } The super keyword specifies a lower bound for a wild-card  Cannot be used with regular type parameters

15 15 Implementation of Generics: Type Erasure Compiling a Generic class: Cell  Check: Type correctness  Erase: Replace T with its upper bound ( Object )‏  Compile: to byte code Compiling an instantiation: Cell c;  Replace: The instantiated type with the raw type  Annotate: add a “footnote” specifying the substitution: c: T = String The annotation is saved in the class file declaring c Compiling a field access or a message send: c.get()‏  Obtain: The annotation of the receiver variable, c  Check: Actual method parameters against the actual type parameters (None in this example)‏  Downcast: insert a cast of the return type to the actual type parameter, String

16 16 Type Erasure Benefit of Erasure:  Binary compatibility with older libraries: List is translated to type List (raw type )‏ Code compiled using a "pre-generics" class works correctly Code written using a "pre-generics" class still compiles and work Drawback of Erasure  generic type information is not known at runtime List and List refer to List  type variables cannot be used in new expressions Type is unknown at runtime

17 17 Type Erasure: Example Generic form class Foo { T m(Set s) { } } Erased form: class Foo { Number m(Set s){} }

18 18 Erasure: Loophole List list = new ArrayList (); Object o = list; List err = (List ) o; // Warning: Unchecked Conversion err.add("abc"); Integer i = list.get(0); // Runtime error: cast from String to Integer Unchecked conversion warning  Issued by the compiler when we use an instantiated type in a position where only the raw type is available  Usually appears when we cast to an instantiated generic type The downcast check will be partial  Indicates a danger of type errors at run time  Avoid at all costs


Download ppt "Java Generics. 2 The Dark Ages: Before Java 5 Java relied only on inclusion polymorphism  A polymorphism code = Using a common superclass Every class."

Similar presentations


Ads by Google