2 - Generics


2.1 - Introduction

  • Generics = A parameter in a class that represents an objecttype.
    • Used to:
      • Detect errors at compile-time instead of run-time. --> More reliable software.
      • Improves readablility of the software.
      • Flexible, make one class for multiple types.
    • Can only be an reference type. No primitive types (int, double, char) allowed.
    • Implemented in Java since JDK 1.5
  • Generic Instantiation = During compiling, when the generics get replaced with an contrete type.
  • Formal Generic Type = <T> or <E> that represents a type in the code.
  • Actual Concrete Type = An actual objecttype, after generic instantiation.
  • Autoboxing = Converting an primitive type (int) into an reference type (Integer)
  • Autounboxing =Converting an reference type (Integer) into an primitive type (int).
  • Bounded Generic Type = When a generic type is specified as a subtype of another type.
  • Generic Method = A static method using a generic type.
  • Generic Class = A class using a generic type.
  • Raw Type = A generic class/interface used without an concrete type, to enable backward compatibility with older versions of Java.
    • Raw Types are unsafe, since they are checked at run-time.
    • //Below JDK 1.5
      GenericStack stack = new GenericStack();
      // JDK 1.5 and higher:
      GenericStack<Object> stack = new GenericStack<Object>();
      

2.2 - Defining Generic Classes and Interfaces

In the examples, T can be replaced with E or any other letter.

  • Declaring a generic class:

    • public class ExampleGenericClass<T> { public ExampleGenericClass() {} }
      
  • Declaring a generic class using multiple types:

    • public class ExampleMultipleGenericsClass<T1, T2, T3, ...> { public ExampleMultipleGenericsClass() {} }
      
  • Declaring a class while extending a generic class:

    • public class ExampleExtendsGenericClass extends ExampleGenericClass<T> { public ExampleExtendsGenericClass() {} }
      
  • Declaring a class while implementing a generic interface:

    • public class ExampleImplementsGenericClass extends ExampleGenericInterface<T> { public ExampleImplementsGenericClass() {} }
      
  • Declaring a class with a bounded generic type:

    • public class ExampleEnforceGenericClass<T extends String> { public ExampleEnforceGenericClass() {} }
      
  • Declaring a static generic method with a generic type:

    • public static <T> void genericReturnMethodExample(T[] list){}
      
    • Call the method:
      Class.<String>genericReturnMethodExample(strings); 
      genericReturnMethodExample(strings);
      
  • Declaring a method with a generic return type:

    • public <T> genericReturnMethodExample(){ 
          <T> type = new <T>;
          return type;
       }
      
  • Declaring a method with a generic parameters/arguments types:

    • public void genericArgumentMethodExample(<T1> argument1, <T2 extends ArrayList> argument2){ 
          argument1.print();
          argument2.get(0);
      }
      

2.3 - Wildcards

  • Wildcard Generic Types = Specifing a range for a generic type.
    • Unbounded wildcard = <?>, or <? extends Object>
    • Bounded wildcard = <? extends T>
    • Lower-bound wildcard = <? super T>

2.4 - Easure and Restrictions on Generics

  • Type easure = The information on generics is used by the compiler but is not available at runtime.
    • The compiler erasus the information after compiling, when it is sure that the generics are used safely.
  • The compiler replaces:

    • Example1:

      ArrayList<String> list = new ArrayList<>();
      String state = list.get(o);
      //INTO
      ArrayList list = new ArrayList();
      String state = (String) (list.get(0));
      
    • Example2:

      public static <E> void print(E[] list){}
      //INTO
      public static void print (Object[] list){}
      
    • Example3:

      public static <E extends GeometricObject> boolean equalArea{
      E object1;
      E object2;
      }
      //INTO
      public static boolean equalArea{
      GeometricObject object1;
      GeometricObject object2;
      }
      
  • A generic class is shared by all its instances regardless of its actual concrete type.

    • ArrayList<Integer> and ArrayList<String> will be in the JVM as class ArrayList, because of type erasure.
    • So:
      • ArrayList<Integer> instanceof ArrayList == TRUE
      • ArrayList<String> instanceof ArrayList == TRUE
      • ArrayList<String> instanceof ArrayList<String> == (Compiler/IDE error)
  • Generic type restrictions:

    1. Cannot use new E()
      • New E() is executed at runtime, but E is not available at runtime.
    2. Cannot use new E[]
      • new E[] is executed at runtime, but E is not available at runtime.
      • Circumvent this by using: E[] elements = (E[]) new Object[capacity];
        • This causes an unchecked compile warning.
        • At runtime this can cause a ClassCastException.
        • Same for ArrayLists.
    3. Generic type parameters not allowes in a static context
      • All instances of a generic class have the same runtime class.
      • Static variables and methods of a generic class are shared by all its instances.
      • Thus, it is illegal to refer to a generic type parameter for a class in a static method, field or initializer.
    4. Exception classes cannot be generic
      • A generic class may not extend java.lang.Throwable.
      • Because, the JVM has to check the exception thrown to see if it matches the type in the catch().
      • This is not possible, because type information is not available at runtime.

2.E - Used Examples

  • Pg 741 - Generic Stack
  • Pg 744 - Array Sorting
  • Pg 746 - Return highest parameter
  • Pg 752 - Generic Matrix Class

results matching ""

    No results matching ""