java泛型

1.泛型的定义

  • 早期Java是使用Object来代表任意类型的,但是向下转型有强转的问题 ,这样程序并不安全。
  • 所有使用该泛型参数的地方都被统一化,保证类型一致。如果未指定具体类型,默认是Object类型。集合体系中的所有类都增加了泛型,泛型也主要用在集合

2.泛型类

  • 泛型类就是把泛型定义在类上 ,用户使用该类的时候,才把类型明确下来。这样的话,用户明确了什么类型,该类就代表着什么类型,用户在使用的时候就不用担心强转的问题,和运行时转换异常的问题了
public class ClassGenericity {
    public static void main(String[] args) {
        /** 创建ObjectTool对象并指定元素类型为String */
        ObjectTool<String> stringTool = new ObjectTool<>();
        stringTool.setObj("muse");
        System.out.println(stringTool.getObj());

        /** 创建ObjectTool对象并指定元素类型为Integer */
        ObjectTool<Integer> integerTool = new ObjectTool<>();
        // integerTool.setObj("muse"); // 编译报错
        integerTool.setObj(10);
        System.out.println(integerTool.getObj());
    }

    /**
     * 构建可以存储任何类型对象的工具类
     */
    static class ObjectTool<T> {
        private T obj;
        public T getObj() {
            return obj;
        }
        public void setObj(T obj) {
            this.obj = obj;
        }
    }
}

3.泛型方法

  • 除了在类上使用泛型,我们可能就仅仅在某个方法上需要使用泛型,外界仅仅是关心该方法,不关心类其他的属性,这 样 的话,我们在整个类上定义泛型,未免就有些大题小作了。那么此时,我们可以采用泛型方法
public class MethodGenericity<T> {
    public static void main(String[] args) {
        //创建对象
        ObjectTool tool = new ObjectTool();

        /** 调用方法,传入的参数是什么类型,T就是什么类型 */
        tool.show("hello");
        tool.show(12);
        tool.show(12.5f);
    }

    static class ObjectTool {
        //定义泛型方法
        public <T> void show(T t) {
            System.out.println(t);
        }
    }
}

4.泛型类派生的子类

  • 泛型类是拥有泛型这个特性的类,它本质上还是一个Java类,那么它就可以被继承或实现。这里分两种情况:
    第一种:子类明确泛型类的类型参数变量,则在实现时需要按指定的对象进行创建。
    第二种:子类不明确泛型类的类型参数变量,则可以按泛型规则进行创建多种类型的对象。
/**
 * 泛型类派生出的子类
 *
 * @author muse
 */
public class SubclassGenericity {
    public static void main(String[] args) {
        // 测试第一种情况
        Inter<String> i = new InterImpl1();
        i.show("hello");

        // 编译错误
//        Inter<Integer> ii = new InterImpl1();
//        ii.show(1);

        // 第二种情况测试
        Inter<String> iii = new InterImpl2();
        iii.show("100");

        Inter<Integer> ii = new InterImpl2();
        ii.show(1);
    }
}

/**
 * 把泛型定义在接口上
 */
interface Inter<T> {
    void show(T t);
}

/** 实现1:子类明确泛型类的类型参数变量 */
class InterImpl1 implements Inter<String> {
    @Override
    public void show(String s) {
        System.out.println(s);
    }
}

/** 实现2:子类不明确泛型类的类型参数变量,实现类也要定义出T的类型 */
class InterImpl2<T> implements Inter<T> {
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}

5.类型通配符

  • List< ? >表示元素类型未知的List,它可以匹配任何类型的元素。声明List< ? >list后,不能向集合中添加元素,因为无法确定集合的元素类型,唯一例外的是null
public class TypeWildcard2 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        print(list);

        List<Integer> list2 = new ArrayList<>();
        list2.add(111);
        list2.add(222);
        print(list2);
    }

    public static void print(List<?> list) {
        // 因为无法确定集合的元素类型,所以不能向集合中添加元素,会报编译错误
//        list.add(list.get(0));
//        list.add(1);
//        list.add(new Object());
//        list.add("ccc");
        list.add(null); // 唯一例外的是可以添加null
        
        for (Object obj : list) 
            System.out.println(obj);
    }
}

6.泛型的上限与下限

在这里插入图片描述

7.类型擦除

  • 泛型是提供给javac编译器使用的,它可以作为类型的限制,让编译器在源代码级别上,挡住非法类型的数据。
  • 但是在JDK1.5之前没有泛型的概念,为了能够与之前版本代码兼容,编译器编译完带有泛型的java程序后,生成的class字节码文件中将不再带有泛型信息,这个过程称之为“擦除”。

8.桥接方法

  • 由于类型擦除,泛型类的实现类中明确了类型,则会导致实现类中的类型与泛型接口不一致,所以会自动生成桥接方法,通过桥接方法进行类型的强转进行实现
  • 桥接方法是jdk1.5引入泛型后,为使java泛型方法生成的字节码与jdk1.5版本之前的字节码兼容由编译器自动生成的。可用 method.isBridge() 判断method是否是桥接方法。
    在这里插入图片描述
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值