Skip to content

Instantly share code, notes, and snippets.

@udoyen
Created February 13, 2019 18:44
Show Gist options
  • Save udoyen/ccf264f077e5b54b553729a43bf90511 to your computer and use it in GitHub Desktop.
Save udoyen/ccf264f077e5b54b553729a43bf90511 to your computer and use it in GitHub Desktop.
Java Paramter Type Names
E – Element (used extensively by the Java Collections Framework, for example ArrayList, Set etc.)
K – Key (Used in Map)
N – Number
T – Type
V – Value (Used in Map)
S,U,V etc. – 2nd, 3rd, 4th types
// Generic Method
public class GenericsMethods {
//Java Generic Method
public static <T> boolean isEqual(GenericsType<T> g1, GenericsType<T> g2){
return g1.get().equals(g2.get());
}
public static void main(String args[]){
GenericsType<String> g1 = new GenericsType<>();
g1.set("Pankaj");
GenericsType<String> g2 = new GenericsType<>();
g2.set("Pankaj");
boolean isEqual = GenericsMethods.<String>isEqual(g1, g2);
//above statement can be written simply as
isEqual = GenericsMethods.isEqual(g1, g2);
//This feature, known as type inference, allows you to invoke a generic method as an ordinary method, without specifying a type between angle brackets.
//Compiler will infer the type that is needed
}
}
// Generic Interface
public interface Comparable<T> {
public int compareTo(T o);
}
// Generic Class
public class GenericsType<T> {
private T t;
public T get(){
return this.t;
}
public void set(T t1){
this.t=t1;
}
public static void main(String args[]){
GenericsType<String> type = new GenericsType<>();
type.set("Pankaj"); //valid
GenericsType type1 = new GenericsType(); //raw type
type1.set("Pankaj"); //valid
type1.set(10); //valid and autoboxing support
}
}
// Generic Bounded Type Parameters
public static <T extends Comparable<T>> int compare(T t1, T t2){
return t1.compareTo(t2);
}
// Java Generics and Inheritance
public class GenericsInheritance {
public static void main(String[] args) {
String str = "abc";
Object obj = new Object();
obj=str; // works because String is-a Object, inheritance in java
MyClass<String> myClass1 = new MyClass<String>();
MyClass<Object> myClass2 = new MyClass<Object>();
//myClass2=myClass1; // compilation error since MyClass<String> is not a MyClass<Object>
obj = myClass1; // MyClass<T> parent is Object
}
public static class MyClass<T>{}
}
// Java Generic Classes and Subtyping
interface MyList<E,T> extends List<E>{
}
// Java Generics Wildcards
//Question mark (?) is the wildcard in generics and represent an unknown type. The wildcard can be used as the type of a parameter, field,
//or local variable and sometimes as a return type. We can’t use wildcards while invoking a generic method or instantiating a generic class.
//In following sections, we will learn about upper bounded wildcards, lower bounded wildcards, and wildcard capture.
//Java Generics Upper Bounded Wildcard
//Upper bounded wildcards are used to relax the restriction on the type of variable in a method.
//Suppose we want to write a method that will return the sum of numbers in the list, so our implementation will be something like this.
public static double sum(List<Number> list){
double sum = 0;
for(Number n : list){
sum += n.doubleValue();
}
return sum;
}
// Now the problem with above implementation is that it won’t work with List of Integers or Doubles because we know that List<Integer> and
//List<Double> are not related, this is when upper bounded wildcard is helpful. We use generics wildcard with extends keyword and the upper
//bound class or interface that will allow us to pass argument of upper bound or it’s subclasses types.
The above implementation can be modified like below program.
public class GenericsWildcards {
public static void main(String[] args) {
List<Integer> ints = new ArrayList<>();
ints.add(3); ints.add(5); ints.add(10);
double sum = sum(ints);
System.out.println("Sum of ints="+sum);
}
public static double sum(List<? extends Number> list){
double sum = 0;
for(Number n : list){
sum += n.doubleValue();
}
return sum;
}
}
// Sometimes we have a situation where we want our generic method to be working with all types, in
//this case unbounded wildcard can be used. Its same as using <? extends Object>.
public static void printData(List<?> list){
for(Object obj : list){
System.out.print(obj + "::");
}
}
// Suppose we want to add Integers to a list of integers in a method, we can keep the argument type as List<Integer>
//but it will be tied up with Integers whereas List<Number> and List<Object> can also hold integers, so we can use lower
//bound wildcard to achieve this. We use generics wildcard (?) with super keyword and lower bound class to achieve this.
// We can pass lower bound or any super type of lower bound as an argument in this case, java compiler allows to
//add lower bound object types to the list.
public static void addIntegers(List<? super Integer> list){
list.add(new Integer(50));
}
//Subtyping using Generics Wildcard
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numList = intList; // OK. List<? extends Integer> is a subtype of List<? extends Number>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment