Java泛型最全知识总结
什么是Java泛型?
Java泛型是JDK 5之后引入的新特性,它可以让我们编写更加安全和简洁的程序。它通过参数化类型的概念来实现,可以让我们在编译期检查类型安全,避免了很多传统上容易出现的运行期异常。
泛型的基本语法
泛型语法可以分为四种:泛型类、泛型方法、泛型接口、泛型通配符。
泛型类
泛型类使用<T>
或其他类型参数来表示泛型类型,例如:
public class MyGenericClass<T> {
private T value;
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
这个示例中,MyGenericClass
是一个泛型类,类型参数为T
,value
的类型就是T
。
泛型方法
泛型方法使用<T>
或其他类型参数来表示泛型类型,例如:
public class GenericMethods {
public static <T> void printArray(T[] array) {
for (T elem : array) {
System.out.print(elem + " ");
}
System.out.println();
}
}
这个示例中,printArray
是一个泛型方法,类型参数为T
,可以接受任何类型的数组。
泛型接口
泛型接口使用<T>
或其他类型参数来表示泛型类型,例如:
public interface MyGenericInterface<T> {
T getValue();
void setValue(T value);
}
这个示例中,MyGenericInterface
是一个泛型接口,类型参数为T
,getValue
和setValue
方法都是使用T
作为返回值或参数类型。
泛型通配符
泛型通配符用于限制泛型类型的范围,例如:
public class GenericStack<T> {
private List<T> stackList = new ArrayList<>();
public void push(T element) {
stackList.add(element);
}
public T pop() {
return stackList.remove(stackList.size() - 1);
}
//泛型通配符 ? 表示任意类型
public void pushAll(Collection<?> collection) {
for (Object obj : collection) {
stackList.add((T) obj);
}
}
//泛型通配符 ? extends 表示任意类型的子类
public void pushAllExtends(Collection<? extends T> collection) {
for (T obj : collection) {
stackList.add(obj);
}
}
//泛型通配符 ? super 表示任意类型的超类
public void pushAllSuper(Collection<? super T> collection) {
for (Object obj : collection) {
stackList.add((T) obj);
}
}
}
这个示例中,pushAll
方法使用?
作为泛型通配符,表示可以接收任意类型的集合。pushAllExtends
方法使用? extends T
作为泛型通配符,表示可以接受任意类型的子类集合。pushAllSuper
方法使用? super T
作为泛型通配符,表示可以接受任意类型的超类集合。
泛型的继承和通配符
泛型的继承
泛型类型允许泛型上下界的限制,例如:
public class Animal {}
public class Dog extends Animal {}
public class Cat extends Animal {}
public class Box<T extends Animal> {
private T animal;
public void setAnimal(T animal) {
this.animal = animal;
}
public T getAnimal() {
return animal;
}
}
public static void main(String[] args) {
Box<Animal> box1 = new Box<>();
Box<Dog> box2 = new Box<>();
Box<Cat> box3 = new Box<>();
}
这个示例中,Box
使用T extends Animal
来限制了T
的范围,只能是Animal
类或其子类。
泛型通配符
泛型通配符可以让我们接受任意类型的泛型参数,例如:
public static void printList(List<?> list) {
for (Object obj : list) {
System.out.print(obj + " ");
}
System.out.println();
}
public static void main(String[] args) {
List<String> list1 = Arrays.asList("I", "love", "Java");
List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5);
printList(list1);
printList(list2);
}
这个示例中,printList
方法使用List<?>
来表示接受任意类型的泛型参数。
泛型的类型推断
在JDK7之后,Java提供了类型推断的功能,让我们可以在很多场合下省略泛型类型参数,例如:
List<String> list1 = new ArrayList<>();
这个示例中,我们使用List<String>
来声明了一个空的ArrayList对象,在JDK7之前,我们需要写成这样:
List<String> list2 = new ArrayList<String>();
泛型的重要知识点和注意事项
- Java泛型只在编译时期有效,在运行时期被擦除;
- 泛型类型参数不能是基本数据类型,可以使用包装类型代替;
- 不可以在泛型类型的静态方法和静态初始化块中使用泛型类型参数;
- 泛型类的类型参数可以有多个,例如
MyClass<T, K>
; - 当使用泛型时,我们应该遵循PECS原则(Producer Extends Consumer Super),即使用extends限定生产者类型,使用super限定消费者类型。
示例1:泛型通配符的含义及使用方法
public static void process(List<?> list) {
for (Object obj : list) {
if (obj instanceof Integer) {
System.out.println(obj + " is an integer.");
} else {
System.out.println(obj + " is a string.");
}
}
}
public static void main(String[] args) {
List<Object> list1 = new ArrayList<>();
list1.add(1);
list1.add("hello");
process(list1);
List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5);
process(list2);
}
这个示例中,process
方法使用了泛型通配符<?>
,表示接受任意类型的List对象。在方法内部,我们使用instanceof
关键字来判断元素的类型,从而进行相应的处理。
示例2:泛型的继承
public interface Comparable<T> {
int compareTo(T o);
}
public class Student implements Comparable<Student> {
private String name;
private int age;
private double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public int compareTo(Student o) {
return Double.compare(this.score, o.score);
}
}
public static void main(String[] args) {
List<Student> list = Arrays.asList(
new Student("Tom", 20, 89),
new Student("Jerry", 22, 78),
new Student("Mary", 19, 95)
);
Collections.sort(list);
for (Student student : list) {
System.out.println(student.getName() + " " + student.getAge() + " " + student.getScore());
}
}
这个示例中,Student
类实现了Comparable
接口,并重写了compareTo
方法,用于按照成绩大小排序。在main
方法中,我们使用Collections.sort
方法对学生列表进行了排序,由于该列表元素都是Student
类型,所以可以按照compareTo
方法排序。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java泛型最全知识总结 - Python技术站