Java基础——泛型之通配符与类型擦除

Java基础——泛型之通配符与类型擦除

一、通配符?

  Java泛型的通配符有三种形式,但究其根本只有"?“这一种形式,其他两种形式都是由”?"衍生出来的。
  1、?:可以接收任意类型——只能作用于方法上,不能修改值
    表示参数可以接收任意类型的泛型类,只能取得类中数据,不能修改数据,因为类型不确定,无法设置确定类型。(只知道是个泛型,连具体是什么类都不知道,肯定不能修改set值)
  2、 ? extends 类:设置/取得泛型上限——可用在类或方法上,不能修改值
    用在类上:T extends 类:T必须为类或者类的子类(不能用?)
    用在方法上:? extends 类:只能接收类或者其子类的泛型类,只能取得类中属性值,不能修改值(会发生父类到子类的向下转型,需要强转,由于具体子类不确定,因此无法转型)
	? extends Number:表示泛型必须是Number及其子类
  3、 ? super 类:取得泛型下限——只能用于方法中,可以修改值
    除了可以取值,也可以设置属性值(子类到父类是自动的向上转型)
	? super String:表示此方法只能取得String以及其父类(Object)	
  这个?代表的就是某个泛型类,若是2/3的情况,则看?代表的那个 类和后面类的关系,若是继承了后面的类,则根据后面的类(父类)并不能确定该子类到底是哪一个类(向下转型),而若是后面的类的父类,则可以设置后面的类(修改值),因为会发生向上转型(自动的)
  4、通配符的关系
    ①只有extends才能用在泛型类上(还是T)
    ②只有super才能设置值

二、类型擦除(语法糖)

  1、先说一下语法糖的概念
    语法糖(为了方便开发):仅存在与源码阶段,编译后就消失不见。Java中典型的语法糖有泛型,自动拆装箱,String的"+"。
  2、类型擦除: 泛型信息仅存在于代码的编译阶段,编译以后就没了,进入JVM之前,与泛型相关的信息会被擦除掉(泛型类与普通类在Java虚拟机(JVM)内没有任何区别
package com.xiaoaxiao.test.GenericTest;

/**
 * Created by xiaoaxiao on 2019/7/10
 * Description: 类型擦除测试
 */

class Point <T>{
    private T x;
}

public class TypeErasureTest {
    public static void main(String[] args) {
        Point<String> point1 = new Point<>();
        Point<Integer> point2 = new Point<>();
        // point1和point2的class相同说明:泛型被类型擦除了,实际进入JVM的都是普通类
        System.out.println(point1.getClass()==point2.getClass());
    }
}
  3、类型擦除的具体实现: 泛型类进入JVM之前会进行类型擦除,之前泛型类的类型参数若没有指定上限,会被擦除为Object类型若指定上限,则类型参数被替换为相应的类型上限
package com.xiaoaxiao.test.GenericTest;

import java.lang.reflect.Field;

/**
 * Created by xiaoaxiao on 2019/7/10
 * Description: 泛型类的类型参数若没有指定上限,会被擦除为Object类型。
 *              如果指定上限,则类型参数被替换为相应的类型上限。
 */

class MyClass<T,E extends Number>{
    private T message;
    private E text;

    public T getMessage() {
        return message;
    }

    public void setMessage(T message) {
        this.message = message;
    }

    public E getText() {
        return text;
    }

    public void setText(E text) {
        this.text = text;
    }
}

public class TypeErasurePlus {

    public static void main(String[] args) {
        MyClass<String,Integer> myClass = new MyClass<>();
        Class cls = myClass.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (Field field:fields) {
            System.out.println(field.getType());
        }
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值