Generics more info

2 0 0
                                    

Common mistake of creating a generic class is wrong assumption of hierarchical of classes. For example if you create a generic class MyClass<T> and then you included this class as a parameter in one of your methods like myMethod(MyClass<Number> m) using Number class as T. And so, during invoking of your method, you assume that you can use Integer as type since Number class is the mother class of Integer class. But this is wrong since MyClass<Number> and MyClass<Integer> are two separate classes that false under Object class.  It is under Object class since the Number and Integer was just a type parameter of your class. The type parameter does not change like Generic1<T> has a subtype Generic2<T>. So, if Generic2<String> is using String as a type parameter, then Generic1<String> must use a String too.

Wildcard(?) is an unknown type.

Types of wildcard

1. Upper bounded wildcard - is used to lessen the restriction of a variable.  Like for example, myMethod(MyClass<Number>  my) MyClass here will take a type parameter of Number class only but will not extend to its subclasses but it you use a wildcard like myMethod(MyClass<? extends Number> my), MyClass will take a type parameter of Number class and all of its subclasses like Integer, Double and so on.

===================

class YourGeneric070222 {
private static void getSomething(Singles<? extends Number> singles){
System.out.println("Value: " + singles.getT());
}

public static void main(String[] args) {
Singles<Number> s1 = new Singles<>(3.14);
Singles<Integer> s2 = new Singles<>(Integer.valueOf(10));

YourGeneric070222.getSomething(s1);
YourGeneric070222.getSomething(s2);
}
}
class Singles<T>{
private T t;

Singles(T t1){
t = t1;
}

protected T getT(){
return t;
}
}

===================

Result:

Value: 3.14Value: 10


2. Unbounded wildcard means it doesn't depend on any type parameter.

===================

class YourGeneric070222 {
private static void getSomething(Singles<?> singles){
System.out.println("Value: " + singles.getT());
}

public static void main(String[] args) {
Singles<Number> s1 = new Singles<>(3.14);
Singles<Integer> s2 = new Singles<>(Integer.valueOf(10));
Singles<Object> s3 = new Singles<>("Hello World");

YourGeneric070222.getSomething(s1);
YourGeneric070222.getSomething(s2);
YourGeneric070222.getSomething(s3);
}
}
class Singles<T>{
private T t;

Singles(T t1){
t = t1;
}

protected T getT(){
return t;
}
}

====================

Result:

Value: 3.14Value: 10Value: Hello World


3. Lower bounded wildcard - It is just like the upper bound but the difference is the upper bound uses the extends keyword while this lower bound uses the super keyword. Note that you cannot uses both the lower and upper bound. You can only choose one. This lower bound just do the opposite. Say your method in upper bound is this:

myMethod(MyClass<? extends Number> my){}

The opposite of the above method which is in lower bound is this:

myMethod(MyClass<? super Integer> my)

Note: The way it works is just the opposite. So, the upper bound allows you to use Number, then going down to Integer or Double or any of its subclasses. On the other hand, the lower bound allows you to use Integer going up to Number and any of its super class.

==================

class YourGeneric070222 {
private static void getSomething(Singles<? super Integer> singles){
System.out.println("Value: " + singles.getT());
}

public static void main(String[] args) {
Singles<Number> s1 = new Singles<>(3.14);
Singles<Integer> s2 = new Singles<>(Integer.valueOf(10));
Singles<Object> s3 = new Singles<>("Hello World");
YourGeneric070222.getSomething(s1);
YourGeneric070222.getSomething(s2);
YourGeneric070222.getSomething(s3);
}
}
class Singles<T>{
private T t;

Singles(T t1){
t = t1;
}

protected T getT(){
return t;
}
}

==================

Result:

Value: 3.14Value: 10Value: Hello World


Note: It works the same in Unbounded since Object is the super type of all mother classes. Always take note of the common error. In generic classes, the hierarchy does not depend on the type parameters but in the class itself where the super class is the Object class. But if you use a wildcard, there will be a relationship as long as it is the subtype or super type of another class.


Java ProgrammingWhere stories live. Discover now