Java泛型

目录

泛型定义的语法

一、泛型类

语法

自定义示例

注意 

二、泛型接口

语法

泛型接口使用分两种情况 

三、泛型方法

语法 

示例

特殊的泛型

泛型使用的语法

特性


泛型即——“参数化类型

它允许我们定义一个类、接口或方法,使它们可以接受指定类型的参数,从而提高了代码的复用性和安全性。

泛型定义的语法

一、泛型类

泛型定义在类上的时候,整个类都可以使用泛型(除了静态的)

比如: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    ,其中T,和U是类型参数。Student类,第一个值的类型是T,第二个值的类型是U。

        在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、可以指定传入的范型的边界,比如它是谁的子类; 形如 当我们这么做的时候,就可以在代码中用T的对象,调用父类的可见方法了。

3、也可以指定多个边界,比如T必须继承谁,同时要实现哪些接口。 语法:

注意:

如果要指定T的父类是谁,只能写一个,且是第一个; 如果要指定T的接口,不指定父类,那么顺序无所谓。

泛型使用的语法

1、在给泛型指定数据类型的时候,不能是基本数据类型

2、如果在使用的时候没有给泛型指定数据类型,那么它会默认为Object类型;

3、JDK11中不能使用 instanceof 判断 某个对象是否属于某个类的带泛型类型;JDK17允许了。

gc instanceof GenericClass

4、类型推断【当我们调用一个泛型方法时,如果方法的参数类型是一个泛型类型,那么编译器就可以根据该参数的实际类型推断出泛型类型】

5、在使用泛型的时候,还有一种特殊语法叫做:通配符与上下边界

  • 通配符与上边界 这个标识表示,这里能够是A类及其所有子类的对象;
  • 通配符与下边界 这个标识标识,这里能够是B类及其基类。

特性

        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 实例化成什么样的类型,它们都将具有相同的字节码,只是字段和方法的参数和返回值的类型不同。这也是类型擦除的一个副作用,即无法在运行时访问泛型类型参数的具体信息。

你可能感兴趣的:(#,Java新特性,java,泛型)