目录
泛型定义的语法
一、泛型类
语法
自定义示例
注意
二、泛型接口
语法
泛型接口使用分两种情况
三、泛型方法
语法
示例
特殊的泛型
泛型使用的语法
特性
泛型即——“参数化类型”
它允许我们定义一个类、接口或方法,使它们可以接受指定类型的参数,从而提高了代码的复用性和安全性。
泛型定义在类上的时候,整个类都可以使用泛型(除了静态的)
比如:List、Set、Map..
class 类名 <泛型标识符>{
}
public class Student {
private T name;
private U age;
public Student(T name, U age) {
this.name= name;
this.age= age;
}
public T getName() {
return name;
}
public U getAge() {
return age;
}
public void setName(T name) {
this.name= name;
}
public void setAge(U age) {
this.age= age;
}
}
在上面的代码中,我们定义了一个泛型类Student
在Student类的构造函数和方法中,我们可以使用类型参数T和U,从而实现了通用性。
例如:
Student student= new student<>("BroRiver", 20);
String s = student.getName();
Integer i = student.getAge();
在上面的代码中,我们创建了一个Student
get我们可以使用get方法来获取该对中的值,并在不需要进行类型转换的情况下使用它们。
自定义泛型类可以让我们在定义类时指定类型参数,从而实现通用性和可重用性。
1、泛型的类型参数只能是类类型,不能是基本数据类型
2、不能对加泛型的类类型使用instanceof操作,编译时不会通过
interface 接口名<标识>{
}
定义泛型接口
public interface MyInterface{
public T next();
}
1.未传入泛型实参
//通用类
public class MyGenericClass implements MyInterface {
@Override
public T next() {
return null;
}
}
2.传入泛型实参
//指定String
public class MyStringClass implements MyInterface {
@Override
public String next() {
return “hello world”;
}
}
类实现了一个泛型接口,在类名后面传入了一个具体的泛型实参String
泛型方法要比前面两个更复杂
首先我们要清楚一点:【泛型方法和泛型类当中的方法,是不一样的概念】
1、只有当方法中使用了泛型类型参数时,该方法才是泛型方法
2、泛型类或泛型接口中的方法,是没有定义泛型的,它们是使用定义在类或接口上的范型。
3、普通类可以定义泛型方法;泛型类也可以定义泛型方法,但是要换一个标识。
修饰符 返回类型 方法名(形参列表){
}
只有声明了
的方法才是泛型方法
public class ArrayUtils {
public static void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
}
在上面的示例中,printArray()
是一个泛型方法,它接受一个泛型数组作为参数,并将数组中的元素打印出来。
是类型参数列表,用于定义泛型类型参数,它可以在方法的返回值类型、参数类型等位置使用。在方法内部,我们使用了for
循环遍历数组,并使用System.out.print()
方法打印每个元素。
泛型方法,可以接受不同类型的数组作为参数,从而实现了代码的重用。
1、可以一次性定义多个泛型标识,中间用逗号分隔 形如:
2、可以指定传入的范型的边界,比如它是谁的子类; 形如:
3、也可以指定多个边界,比如T必须继承谁,同时要实现哪些接口。 语法:
注意:
如果要指定T的父类是谁,只能写一个,且是第一个; 如果要指定T的接口,不指定父类,那么顺序无所谓。
1、在给泛型指定数据类型的时候,不能是基本数据类型;
2、如果在使用的时候没有给泛型指定数据类型,那么它会默认为Object类型;
3、JDK11中不能使用 instanceof 判断 某个对象是否属于某个类的带泛型类型;JDK17允许了。
gc instanceof GenericClass
4、类型推断【当我们调用一个泛型方法时,如果方法的参数类型是一个泛型类型,那么编译器就可以根据该参数的实际类型推断出泛型类型】
5、在使用泛型的时候,还有一种特殊语法叫做:通配符与上下边界。
Java的泛型被称为“伪泛型”,说白了它就是一个语法糖,只能影响编译器(无法影响运行期)。
泛型相对于Java虚拟机来说是透明的,编译器编译后生成的二进制代码有没有泛型都是一样的。
类型擦除
类型擦除是指在编译器编译泛型代码时,将所有 泛型类型 替换成其 对应的边界类型 或Object类型,从而生成字节码文件。
这样做是为了保持Java语言的向后兼容性,因为泛型是在Java 5中引入的,而Java 5之前的版本并不支持泛型。
类型擦除的结果是,在运行时无法访问泛型类型的具体信息,例如泛型类型参数的实际类型、边界类型等。
示例:
public class GenericClass {
private T value;
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
在上面的示例中,GenericClass 是一个泛型类,它的类型参数为T。
在编译时,由于类型擦除的原因,T将被替换成Object类型,所以实际上value字段的类型是Object,而get、set方法的参数和返回值类型也是Object。这意味着,无论我们在运行时将GenericClass 实例化成什么样的类型,它们都将具有相同的字节码,只是字段和方法的参数和返回值的类型不同。这也是类型擦除的一个副作用,即无法在运行时访问泛型类型参数的具体信息。