泛型

目录

泛型类

泛型方法

通配符

泛型接口

类型擦除


泛型类

定义:泛型指的是类定义的时候,并不会设置类中的属性或方法中参数的具体类型,而是在类使用时再定义。

语法:

class MyClass<T>{

    T  value1;

}

T被称为类型参数,用于指代任何类型。实际上这个T你可以任意写,但出于规范的目的,Java还是建议我们用单个大写字母来代表类型参数,常见的有:

T:代表一般的类。

E:代表element,常用于泛型类中的属性。

K:代表Key的意思。

V:代表Value的意思,通常与K一起配合使用。

泛型类的使用:


class MyClass<T>{
    private T value1;

    public T getValue1() {
        return value1;
    }

    public void setValue1(T value1) {
        this.value1 = value1;
    }
}

public class Test{
    public static void main(String[] args) {
       MyClass<String> myClass = new MyClass<>();
       myClass.setValue1("hello");
        System.out.println(myClass.getValue1());
        MyClass<Integer> myClass1 = new MyClass<>();
        myClass1.setValue1(10);
        System.out.println(myClass1.getValue1());
    }
}

注意:泛型只允许接收类,所有基本类型必须使用包装类

如果在类中需要定义多个属性,并且属性的类型不同,可以在类中写多个类型参数。


泛型方法

例:

public <T> T MyMethod(T t){
    System.out.println(t);
}

注意:泛型可以单独定义方法,即便所在的类不是泛型类,也可以单独定义方法。

<T>只是告诉编译器这是泛型方法,并不是返回值。第一个T才是返回值。

我们来看下面的一个问题:

在泛型类中使用泛型方法,思考一下,我圈出来的三个T是一个东西吗?

在泛型类中,我们知道,泛型类的T和属性中的T一定是同一个东西,那么泛型方法是否和他们一样呢?

我们来测试一下:

public class Test{
    public static void main(String[] args) {
        MyClass<String> myClass = new MyClass<>();
        myClass.method("hello");
        myClass.method(1234);
    }
}

运行结果:

结论:当泛型类与泛型方法共存时,泛型类中的泛型参数与泛型方法中的类型参数没有关系,泛型方法始终以自己定义的类型参数为准。

规范:泛型方法类型参数与泛型类的类型参数不要同名。


通配符

1. ? ---  表示可以接收任意类型

用于方法中,表示参数可以接收任意类型的泛型类。

class MyClass<T>{
    private T value1;

    public T getValue1() {
        return value1;
    }

    public void setValue1(T value1) {
        this.value1 = value1;
    }
}

public class Test{
    public static void main(String[] args) {
        MyClass<String> myClass = new MyClass<>();
        myClass.setValue1("world");
        print(myClass);
    }
    public static void print(MyClass<?> myClass){
        System.out.println(myClass.getValue1());
    }
}

注意:只能取得类中数据,不能修改数据,因为类型不确定,无法设置确定类型。

 

2. ? extends 类:设置/取得泛型上限

eg:? extends Number:表示泛型必须是Number及其子类。

用在类上   T extends 类:T必须为类或者类的子类。

用在方法上   ? extends 类:只能接收类或者其子类的泛型类。

注:只能取得类中属性,不能修改值(发生父类到子类的向下转型,需要强转,由于子类不确定,因此无法转型)

 

3. ? super 类:取得泛型下限 --- 只能用于方法中

eg:? super String:表示此方法只能取得String及其父类Object

可以设置属性值(子类到父类是自动的向上转型)。


泛型接口

interface IInterface<T>{
        T test(T t);
}

子类有两种实现方式:

//1.子类继续保留泛型
class InterfaceImpl<T> implements IInterface<T>{}
//2.子类定义时确定好类型
class InterfaceImpl implements IInterface<String>{}

类型擦除

在此之前,我们先提出一个概念。

语法糖:仅存在于源码阶段,编译后就消失不见。作用是为了方便程序员的开发。

Java中典型的语法糖有泛型、自动拆装箱等。

泛型信息仅存在于代码的编译阶段,进入JVM之前,与泛型相关的信息会被擦除掉,专业术语:类型擦除。

换句话说,泛型类与普通类在Java虚拟机内没有任何差别。

举例说明:

class MyClass<T>{
    T t;
}

public class Test{
    public static void main(String[] args) {
      MyClass<String> myClass = new MyClass<>();
      MyClass<Integer> myClass1 = new MyClass<>();
        System.out.println(myClass.getClass() == myClass1.getClass());
    }
}

不管类型参数是String还是Integer,都会被擦除,最后还是同一个东西。

泛型类进入JVM之前会进行类型擦除,之前泛型类的类型参数若没有指定上限,会被擦除成为Object类型。如果指定上限,则参数类型被替换为相应类型上限。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值