Java高级特性之泛型


用简单通俗的话来记录自己对架构的理解
在这里插入图片描述

1.为什么

啥都不说,大家先来看下ugly代码:

    public int sum(int a, int b) {
        return a + b;
    }

    public float sum(float a, float b) {
        return a + b;
    }

大家看到上面的代码,可能会微微一笑,我是不会写这样的代码,因为,我会使用extend/implements的父类来实现,是的,这是一种实现方式,但是,同样的,会出现的获取的结果还要进行类型转换,这也不是最优方案,所以,在JDK1.5之后,就推出了泛型。
那么,为啥要引入泛型,就是为了解决刚才看到的问题
(1)减少方法的复写,减少方法的改动
(2)减少类型强转
(3) 大大提高类型的可拓展性

2.是什么

(1)泛型是抽象参数化类型

首先我们看下现有的数据类型

public class Student<T> implements Cloneable{

    private String name ;//引用数据类型
    private int age;//基本数据类型
    private List<Lesson> lessonList;//引用数据类型
    private T t;//泛型的参数类型,可以是任意类型

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

由上可见:泛型实际上就是抽象的参数类型。
如何理解这里的抽象和参数类型呢?
抽象就是这个类型是后来指定,在调用时进行指定,而不是预先指定。
参数类型就是它也是一种数据类型(这是我个人的理解),只是作为调用时参数传递进来确定而已

(2)泛型的分类与应用

根据在一个类中的应用,泛型分为:
泛型类
泛型接口
泛型方法
如下:

泛型类:
public class Student<T> implements Cloneable{

    private String name ;//引用数据类型
    private int age;//基本数据类型
    private List<Lesson> lessonList;//引用数据类型
    private T t;//泛型的参数类型,可以是任意类型

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}
泛型接口:

泛型方法:
    public <T> T getFristResult(T t){
        return  t;
    }
    public <K,V> V getSecondResult(K k){
        V t = null;
        return  t;
    }

(3)通配符?和上下限的限定

1.权限限定在声明中应用
在泛型类的声明中,只能使用?extends T,但是不能使用? super T。如下代码:
同理,泛型接口亦是如此。
在泛型方法中,不支持?extend T。只能是 T extends Number这样

   private class Generic2<T extends A>{

    }

//报异常
    private class Generic3<? super A>{

    }
    class A{};
    class B extends A{}
    class C extends B{}
    class D extends C{}

//异常,编译无法通过
    public <? extends A> T getKey(Class<T> tClazz){
        try {
            return tClazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }finally {
            return null;
        }
    }

2.权限的限定可以在具体的实现中应用,如下代码:

	//通用的子类实现方式
      List<A> list = new ArrayList<>();
        list.add(new C());
        list.add(new A());


		//泛型的是实现,会导致添加异常
        List<? extends A> listAA = new ArrayList<>();
        listAA.add(new B());//不支持任何类型的添加
        A a = list.get(0);
		
		//添加和获取都支持
        List<? super C> listCsuper  = new ArrayList<>();
        listCsuper.add(new D());
        listCsuper.add(new C());
        listCsuper.add(new A());//不支持子类的实现
        Object obj = listCsuper.get(0);

3.通配符的& 操作:
(1)这个操作只能单实现多继承,和类的继承原理保持一致
(2)使用这个字符后,子类必须是要同时实现继承这些类及接口

数字狗来验证:
  private class Generic1<T extends Number & Dog>{
        private     T t;
        public void deal(){
            t.intValue();
            t.shout();
        }

    }

    private interface Dog{
        void shout();
    }
    
    /**
     *   数字狗的校验 &
     */
    private class NumberDog extends Number implements Dog{

        @Override
        public int intValue() {
            return 0;
        }

        @Override
        public long longValue() {
            return 0;
        }

        @Override
        public float floatValue() {
            return 0;
        }

        @Override
        public double doubleValue() {
            return 0;
        }

        @Override
        public void shout() {
            Log.d("haha","狂吠");
        }
    }

3.怎么实现

(1)泛型我更倾向于是个语法糖,在我们除了有基本数据和引用数据外,引入了一个任意类型的方式,但是,它的存在是在编译器,运行期是会泛型擦除。
可以通过三种方式进行验证:
(a)不同泛型的Class字节码对象名是否是一致?

 List<Integer> integerList = new ArrayList<>();
        List<String> stringList = new ArrayList<>();
        String integerListName = integerList.getClass().getName();
        String stringListName = stringList.getClass().getName();
       System.out.println("integerListName.equals stringListName:"+(integerListName.equals(stringListName)));

(b)jad 工具进行反编译查看:
https://download.csdn.net/download/fullstackdeveloper/11665390:
反编译处理的字节码

public class MyClass
{

    public MyClass()
    {
    }

    public static void main(String args[])
    {
        java.util.List integerList = new ArrayList();
        java.util.List stringList = new ArrayList();
        String integerListName = integerList.getClass().getName();
        String stringListName = stringList.getClass().getName();
        System.out.println((new StringBuilder()).append("integerListName.equals stringListName:").append(integerListName.equals(stringListName)).toString());
    }
}

©javac的编译后,再使用javap 反编译查看
这个是同理,我就不反编译了。

4.巨人肩膀

(1)泛型
https://blog.csdn.net/jeffleo/article/details/52250948
(2)为何要引入泛型擦除
https://blog.csdn.net/qq_30878303/article/details/79639904

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值