泛型(Generic)到底是什么,泛型总结

前阵子公司技术分享,学习到了java8的一些新特性,给我感觉是编码变得越来越“简单”,并不是思想简单,而是实现上,像lambda,stream,编码变得越来越简单明了,的确,回想接口,继承,简单点说都是为了复用代码,泛型也一样,可能一段逻辑并不在乎你是什么类,我只在乎功能上是否满足,你来了只要符合我的规定,我就可以让你执行。

一、是什么

泛型,jdk1.5引入,即参数化类型,在声明的时候不规定实际的类型,将类型做为参数在方法调用时传递,典型的就是集合相关类

二、使用范围

泛型类:

泛型类的声明很简单,在类名后添加一对尖括号,在尖括号里声明泛型的参数名即可,可以声明多个类型参数。参数名理论上没有限制,为了方便阅读,一般的参数名命名规则:

  • E - 元素,主要由Java集合(Collections)框架使用。
  • K - 键,主要用于表示映射中的键的参数类型。
  • V - 值,主要用于表示映射中的值的参数类型。
  • N - 数字,主要用于表示数字。
  • T - 类型,主要用于表示第一类通用型参数。
  • S - 类型,主要用于表示第二类通用类型参数。
  • U - 类型,主要用于表示第三类通用类型参数。
  • V - 类型,主要用于表示第四个通用类型参数。

class xxx<T>{}

class xxx<T,U>{}

泛型方法:

泛型方法的声明是在方法的返回值前面添加尖括号。

public <T>void test(T t){}

只有在方法的返回值前面加了<>才表明为泛型方法,否则即使某个方法的参数列表含有泛型参数,也只是个普通方法,泛型方法是独立于类存在的,可以定义在普通类中也可以定义在泛型类中,所以说泛型方法中的参数与类中的参数并无关系,即使同名也一样。

并且泛型方法具有自动推断类型功能。

类型推断:泛型方法会根据参数列表和返回值自动推断出类型参数的真实类型。

public static void main(String[] mainArr){
        //相同类型参数
        String s = test01("a", "b");
        Integer i = test01(1, 1);
        //不同类型参数
        Serializable a = test01("a", 1);
        Number number = test01(1, 1.0);
        Serializable serializable = test01(new String[]{}, new ArrayList<Integer>());

        //返回参数
        List<String> strList = test02();
        List<Integer> intList = test02();
    }

    private static void test(){
        GenericMethod.<Integer>set(1);
        GenericMethod.set(1);
    }

    private static <T>T test01(T a,T a1){
        System.out.println(a.getClass());
        System.out.println(a1.getClass());
        return a1;
    }

    private static <T>List<T> test02(){
        return new ArrayList<>();
    }

其实原理很简单,就是取参数的最小公倍数。

泛型接口:

参考Comparable

三、通配符与类型限定

类型限定:extends

限定为类 
限定为接口
限定为其它类

一个类型变量或者通配符可以有多个限定,同java一样,单继承多实现,多个限定之间用 & 分隔,并且如果既有接口又有父类,父类在第一个参数位置,别问为什么,老爹最重要,

通配符:?

?
? extends String     String及其子类
? super String      String及其父类

以前总是在纠结,T明明就可以代表任意类型了,为什么还会有通配符,通配符不也是代表任意类型吗?先看例子:

情况1:List<?> list = new ArrayList();
       list.add("11");
       list.add(11);
        
情况2:list.removeAll(Collection<?> c);

情况3:ListContainer<?> container = null;
       List<?> list = null;
       ...
       list = ListContainer<ArrayList>(new ArrayList());

以上情况下,可以很好的阐述通配符的存在意义了。

四、泛型擦除

泛型只存在于编译阶段,虚拟机中没有泛型类型的对象–-所有对象都是普通的类,无论我们什么时候定义的泛型类型,
在虚拟机中都自动转换成了一个相应的原始类型.原始类型就是擦除类型变量,并替换为第一个限
定符类型(没有限定符用Object替换)后的泛型类型名,兼容jdk1.5之前的(ps:所以说我们没有做的事别人做了,并不是没有做,故c程序的运行速度不会因为使用泛型而加快)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值