File size: 3,113 Bytes
3e1b953
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
The use of 'generic type definitions' in classes naturally LIMITS the FUNCTIONALITY OF METHODS that use type definitions. 
Since the 'generic type' can be anything when an object is created from a class, 
we can't use through a variable of the type 'anything other than the features defined in the Object class'.
=????????

=> because Java doesn't know what T actually is at compile time, 
=> you can't assume specific behavior (like calling .length() or + operations) unless explicitly told.
VS
=> In Java, all classes inherit from 'Object'. 
=> So if you have a generic type T, Java treats it as if it were an 'Object' 
=> — meaning you can only safely call methods defined in 'Object', such as:
.toString()
.equals()
.hashCode()
=> You cannot assume anything more specific (like .compareTo(), .length(), +, etc.) unless you bound the generic type to a dtype u want.




The following code, for example, would give a compilation error:


class Box<TYPE> {
    private TYPE value;

    public Box(TYPE value) {
        this.value = value;
    }

    public TYPE getValue() {
        return value;
    }

    public void setValue(TYPE value) {
        this.value = value;
    }
    
    public void isValueLongerThanZero() {
        // This gives a compilation error, because the method
        // length() is not in all classes
        if (value.length() > 0) {
            System.out.println("Longer than 0!");
        }
    }
}
 

THE CODE GIVES A COMPILATION ERROR:
The method length() is undefined for the type TYPE
 


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





However, we can LIMIT the DEFINITION of the generic type by using the 'extends' keyword.

For example, the following 'generic definition' indicates that the 'implementing type' must inherit the class 'Person':

class PersonContainer<T extends Person> {
    private T person;
    
    public PersonContainer(T person) {
        this.person = person;
    }
    
    public String giveName() {
        // Now this works, because T inherits 'Person'
        return person.getName();
    }
    
    public String giveEmail() {
        return person.getEmail();
    }
}






The type to be inherited can also be an 'interface', even though the keyword 'extends' is still used, confusingly.

For example, types implementing the 'Comparable interface '
naturally have the method compareTo in use. 
Note that the generic definition T is also repeated in the name of the interface:

class Comparator<T extends Comparable<T>> {
    public Comparator() {}
    
    public T giveGreater(T element1, T element2) {
        if (element1.compareTo(element2) < 0) {
            return element2;
        } 
        else {
            return element1;
        }
    }
}






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


Generics also involves other issues not covered in this section, 
such as statically, generically typed methods or wildcard characters. 
You can read more about these in Oracle's tutorial:
https://docs.oracle.com/javase/tutorial/java/generics/index.html