Tuesday, September 14, 2021

Generics in Java

What are Generics?

Enable us to parameterize the type of variables in a class or interface by its definition, so code can be reused for more general types of inputs. Moreover, the type of variables would be checked more thoroughly at compile time, so errors in run-time due to misinterpretation of data are minimized.

ps. 
  1. Type variable (T) can be any non-primitive type.
  2. A generic class can have multiple type parameters. Ex: 
public class GenericType <T1, T2>. 
Since T1, T2 means "any type", you can replace type variable also with another parameterized type. I.e. GenericType<String, Box<Integer>> gt = null;  

 

      3. Avoid using raw type generics, since they only exist for backwards compatibility (prior to JDK5.0).
ex: GenericTypes genericTypeObject2; //Raw type =Generic without specifying type variable
  • Naming convention:
    1. E - Element (used extensively by the Java Collections Framework) 
    2. K - Key
    3. N - Number 
    4. T - Type 
    5. V - Value 
    6. S,U,V etc. - 2nd, 3rd, 4th types
  • Example of generic class/interface:

Reference: https://docs.oracle.com/javase/tutorial/java/generics/types.html
  • Being subtype of another class doesn't make its generic type a subclass of that class as well! 
ex: Integer is subtype of Number, but ArrayList<Integer> isn't subtype of ArrayList<Number>, rather they are both sub-types of ArrayList<?>. 

In order to write a method that works for List<Integer>, List<Number> and List<Double>, we have another syntax called wildcard (syntax = ?) 

  • So what if we extend or implement a generic type class/interface? As long as the type arguments are the same, the subtyping relationship is preserved.


Wildcards: representing unknown type

  • Can be used as:
parameter, field, local variable and return type(not recommended)
  • Cannot be used as:
type argument for generic method, generic class or a supertype.

  • Upper-bound wildcards: 

Following method works for List<Integer>, List<Double> and List<Number>

public static double sumOfList(List<? extends Number> list) {}

  • Un-bounded wildcards:

Useful if

  1. our method only uses API provided by the Object class.
  2. If our method doesn't call any APIs that depends on the type parameter. 

In both cases, the argument type doesn't really matter for our method and it's reasonable to use unbounded wildcards.

  • Lower-bound wildcards:

Following method works for List<Integer>, List<Object> and List<Number>

public static void addNumbers(List<? super Integer> list) {}

 

Guidelines on using wildcards:

1. Don't use wildcard on return types, only use on parameters

2. Use "? extends" when the parameter type serves as input (when I get value out of this parameter)

3. Use "? super" when the parameter type serves as output (when I put value into this parameter)

4. Use unbounded ("?") when this "input" can be accessed using methods defined in the Object class.

5. Don't use wildcard when doing both input and output on that parameter.


Subtype relationship of generic types

Object is super type of all generic types
List<?> is super type of  List<Integer> , List<(any type)> 

Reference: https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html



 


Code Example and important notes on generic:




Reference

https://stackoverflow.com/questions/6008241/what-is-the-difference-between-e-t-and-for-java-generics

No comments:

Post a Comment