Parameterized TypesMultiple ParametersAutoboxing and UnboxingBounded TypesGeneric Methods & InterfacesWildcard Arguments
When generics were introduced in JDK 5, they brought about changes to many of the classes and methods of the core Java API. Through the use of generics, it is possible to create classes, interfaces and methods that will work in a type-safe manner for several types of data.
Parameterized Types
Generics are often referred to has parameterized types, where you can create classes, methods and interfaces that have the type of data they work with specified as a parameter.
class Something<T> { T object; // declare an object of type T. // pass the constructor a reference to // an object of type T. Something (T object) { this.object = object; } // return object. T getObject() { return this.object; } // show type of T. void showType() { System.out.println("The type of <T> is: " + object.getClass().getName()); } }
Multiple Parameters
class TwoTypes<T, V> { T objOne; V objTwo; TwoTypes(T objOne, V objTwo) { this.objOne = objOne; this.objTwo = objTwo; } void showTypes() { System.out.println("Type of <T>: " + objOne.getClass().getName()); System.out.println("Type of <V>: " + objTwo.getClass().getName()); } }
Autoboxing and Unboxing
Generics do not utilize primitive types (such as
int
, double
, etc.) as type parameters. When declaring variables in these contexts, Java will automatically convert the type to its corresponding wrapper class (a process called autoboxing).[If a conversion goes the other way, it’s called unboxing.]
Bounded Types
Sometimes, we want to limit the types utilized to a certain constraint, such as
int
, float
, double
, etc. To do so, we can utilize generic types that extend classes.class StatisticsYo<T extends Number> { T[] numbers; StatisticsYo(T numbers) { this.numbers = numbers; } double average() { double sum = 0.0; for (T x : numbers) sum += x.doubleValue(); return sum / numbers.length; } }
Generic Methods & Interfaces
class Something { static <T extends Comparable<T>, V extends T> boolean isIn(T x, V[] y) { for (int i = 0; i < y.length; i++) if (x.equals(y[i])) return true; return false; } }
interface MinMax<T extends Comparable<T>> { T min(); T max(); } class MyClass<T extends Comparable<T> implements MinMax<T>> { T[] values; public T min() { ... } public T max() { ... } }
Wildcard Arguments
boolean sameAverage(StatisticsYo<?> obj) { if (this.average() == obj.average()) return true; return false; } // upper bounds specified using <? extends superclass>. // lower bounds specified using <? super subclass>.