Appearance
Use generics
When using ArrayList
, if the generic type is not defined, the generic type is actually Object
:
java
// compiler warning:
List list = new ArrayList();
list.add("Hello");
list.add("World");
String first = (String) list.get(0);
String second = (String) list.get(1);
At this time, <T>
can only be used as Object , and the advantages of generics are not used.
When we define the generic type <String>
, the generic interface of List<T>
becomes the strong type List<String>
:
java
// no compiler warnings:
List<String> list = new ArrayList<String>();
list.add("Hello");
list.add("World");
// No forced transformation:
String first = list.get(0);
String second = list.get(1);
When we define the generic type <Number>
, the generic interface of List<T>
becomes the strongly typed List<Number>
:
java
List<Number> list = new ArrayList<Number>();
list.add(new Integer(123));
list.add(new Double(12.34));
Number first = list.get(0);
Number second = list.get(1);
If the compiler can automatically infer the generic type, it can omit the subsequent generic type. For example, for the following code:
java
List<Number> list = new ArrayList<Number>();
When the compiler sees the generic type List<Number>
it can automatically infer that the generic type of the following ArrayList<T>
must be ArrayList<Number>
. Therefore, the code can be abbreviated as:
java
// You can omit the following Number, and the compiler
// can automatically infer the generic type.:
List<Number> list = new ArrayList<>();
Generic interface
In addition to ArrayList<T>
using generics, you can also use generics in interfaces. For example, Arrays.sort(Object[])
can sort any array, but the elements to be sorted must implement Comparable<T>
generic interface:
java
public interface Comparable<T> {
/**
* Return a negative number: the current instance is smaller than parameter o
* Return 0: The current instance is equal to parameter o
* Returns a positive number: the current instance is larger than parameter o
*/
int compareTo(T o);
}
String
arrays can be sorted directly:
java
// sort
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
String[] ss = new String[] { "Orange", "Apple", "Pear" };
Arrays.sort(ss);
System.out.println(Arrays.toString(ss));
}
}
This is because String
itself has implemented the Comparable<String>
interface. If you try changing to our custom Person
type:
java
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Person[] ps = new Person[] {
new Person("Bob", 61),
new Person("Alice", 88),
new Person("Lily", 75),
};
Arrays.sort(ps);
System.out.println(Arrays.toString(ps));
}
}
class Person {
String name;
int score;
Person(String name, int score) {
this.name = name;
this.score = score;
}
public String toString() {
return this.name + "," + this.score;
}
}
When we run the program, we will get ClassCastException
, which means that Person
cannot be converted to Comparable
. We modify the code to let Person
implement the Comparable<T>
interface:
java
// sort
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Person[] ps = new Person[] {
new Person("Bob", 61),
new Person("Alice", 88),
new Person("Lily", 75),
};
Arrays.sort(ps);
System.out.println(Arrays.toString(ps));
}
}
class Person implements Comparable<Person> {
String name;
int score;
Person(String name, int score) {
this.name = name;
this.score = score;
}
public int compareTo(Person other) {
return this.name.compareTo(other.name);
}
public String toString() {
return this.name + "," + this.score;
}
}
Running the above code can correctly sort by name
.
You can also modify the comparison logic, for example, sort by score
from high to low. Please modify the test yourself.
Summary
When using generics, replace the generic parameter <T>
with the required class type, for example: ArrayList<String>
, ArrayList<Number>
etc.;
Types that the compiler can automatically infer can be omitted, for example: List<String> list = new ArrayList<>();
;
When the generic parameter type is not specified, the compiler will give a warning and can only treat <T>
as the Object
type;
Generic types can be defined in interfaces, and classes that implement this interface must implement the correct generic type.