【泛型】学习笔记
创始人
2025-01-15 05:36:16
0

1.工作中使用反射去创建对象

例子1     @Getter     private int type;     private Class clazz;      ActivityType(int type, Class clazz) {         this.type = type;         this.clazz = clazz;     }           public AbstractActivity newInstance(ActivityEntity activityEntity) {         try {             // 创建一个对象,并且传入一个参数             return clazz.getConstructor(ActivityEntity.class).newInstance(activityEntity);         } catch (Exception e) {             logger.error("ActivityType newInstance catch error:", e);             return null;         }     }

2.反射+泛型创建对象的例子

step1.声明泛型方法和反射去创建对象的代码:     public static  T f(Class clazz, int num) throws Exception {         // 使用时,我们要知道调用的类型是啥,进行指定即可,int.class其实我们可以用限定符指定         return clazz.getConstructor(int.class).newInstance(num);     }   step2.使用 // 通过指定类型参数+传入参数     Integer num = f(int.class, 3);    System.out.println(num);

3.guava TypeToken // 解决类型擦除

Guava的TypeToken在泛型编程中的应用_guava typetoken-CSDN博客

4.Fastjson中TypeTolen的使用 // 指定TypeToken保证解析出的类型为指定的,而不是Object

public static void main(String ... args) {         String personString = "[{\"id\":1,\"name\":\"Irene\",\"password\":\"123456\"},{\"id\":2,\"name\":\"Aiden\","             + "\"password\":\"123456\"}]";          List persons = JSON.parseObject(personString, new TypeToken>(){}.getType());     }      @Data     public static class Person {         private int id;         private String name;         private String password;     }

5.黑马学习笔记

/* 1)没有泛型时:     没有泛型前: 使用Object可以存放任意的元素     泛型的出现:和集合有很大的关系      需要强转     使用上:读取时是Object,具体使用需要强转。     严重问题:虽然类型转换有错误,但是编译期没问题,运行期异常。  2)引入泛型     作用:编译器的检查。 在使用时必须按照指定的类型来存储。  3)泛型的好处:     1.编译期检查类型     2.无需数据类型转换  4)     会自动装箱(添加时)。     会自动拆箱(从集合取出数据时)。   5)泛型集合     有点像:类型的形参。  6)泛型的本质:就是参数化类型。类型的形参。  7)泛型标识: T,E,K,V  8)泛型类没有指定类型,则按照Object。  9)泛型类,不支持int,编译期的时候,转化为Object,因为int不继承Object,因此不能是基本数据类型!  10)打印xx.getClass():     同一个泛型类,根据不同的数据类型创建的对象,本质是同一类型。  11)泛型在逻辑上可以看成是不同的类型,但是实际上都是相同的类型,也就是Xxx.class  12)泛型类继承:     子类有泛型的话,必须有一个类型和父类提供的一样,当然自己可以新增别的泛型类型。     子类无泛型的话,则必须明确父类的泛型类型。  13)泛型接口     实现类不是泛型类     实现类是泛型类  14)泛型方法     泛型方法:在调用方法的时候,指明泛型的具体类型。        注意:         只使用了泛型类中的类型的方法不是泛型方法,而是成员方法。         泛型方法是独立于泛型类中的类型的,可以加static。 成员方法类型使用的是类中指定的泛型,不能加static。      泛型类则是:在实例化的时候指明泛型的具体类型。  15)类型通配符     上限:         ? : 表示实参,但是我们可以指定边界,比如: , 就是:Number或者Number的子类。          问题: 不能填充元素。因为我们不知道它到底是什么类型,所以我们不能new一个元素填充进去。      下限:           16)泛型擦除:     1.5版本才引入的,之前没有泛型,为了和之前代码兼容,泛型只存在于编译阶段,在进入jvm之前,与泛型相关的信息会被擦除掉。      证明:         intList.getClass().getSimpleName();         strList.getClass().getSimpleName();         打印信息:发现都是ArrayList  17)拿到字节码文件     Class clazz = erasure.getClass();      获取到所有的成员变量:         Field[] fields : clazz.getDeclaredFields();          field.getType().getSimpleName() 发现 是Object // 也就是通过反射再去看的时候,类型被擦除成了Object      有限制的类型擦除:T extens Number,就会被擦除为Number      桥接方法的生成:         类型擦除和多态发生了冲突,为了解决这个问题,编译器会产生一个桥接方法,在虚拟机中会由参数好返回值类型不同而产生2个不同的字节码文件,             但是虚拟机能够正确的处理这种情况。         info:Integer         info:Object  18)泛型数组     可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象。     可以通过:Array.newInstance(Class, int)创建T[]数组      在编译期会进行类型擦除,而数组则是一直持有,所以2者设计是冲突的,java这直接不让那么做。      创建:         T[] arr = new T[3]; // 直接失败,因为我们根本不知道T是什么类型。           @SuppressWarnings("all")         public static  T[] createArr(Class clazz, int len) {             return (T[]) Array.newInstance(clazz, len);         }  19)泛型和反射     Class personClass = Person.class;     Constructor constructor = personClass.getConstructor();     Person person = constructor.newInstance();  */

6.桥接方法

在某些情况下,基本类型擦除会导致方法重写的问题,为了防止出现这种情况,Java编译器有时会生成桥接方法。问题来了,什么是桥接方法?

public interface Parent {     public void set(T t); }

接着定义一个类实现Parent类,并指向泛型类型为String

public class Child implements Parent {      @Override     public void set(String s) {         System.out.println("child");     } }


在上面的代码中,Child中的set方法实现并重写了Parent中的set方法
到那时,泛型在编译之后就会被类型擦除,Parent中的set(T t)会被擦除编程set(Object t),这与Child中的set(String s) 方法具有不同的参数类型,那么就不是方法重写,而是方法重载了。
问题来了,Child类实现了Parent接口,但是并没有实现其中的set(Object t)方法,这是怎么回是?
其实,这个问题在泛型设计之初就被考虑到了,编译器通过Child类中插入一个桥接方法set(Object t) 来解决这个问题,
我们把Child编译成class文件,再使用jad工具反编译成Java文件,得到如下内容

public class Child     implements Parent {      public Child()     {     }      public void set(String s)     {         System.out.println("child");     }      public volatile void set(Object obj)     {         set((String)obj);     } }


在Child类中,JVM自动帮我们生成了一个set(Object obj)方法,并且调用了set(String s) 方法,这个set(Object obj)方法就是桥接方法
所以当一个字类在继承(或实现)一个父类(或接口)的泛型方法时,在字类中明确指定了泛型类型,编译器为了让字类有一个与父类的方法签名一致的方法,就会在子类中自动生成一个与父类的方法签名一致的桥接方法

相关内容

热门资讯

第6分钟了解!奕乐贵州麻将有挂... 第6分钟了解!奕乐贵州麻将有挂确实有辅助(辅助)美味冰淇淋开挂辅助平台-总是有挂辅助1、奕乐贵州麻将...
第七分钟了解!杭州都莱破解版(... 第七分钟了解!杭州都莱破解版(辅助)启悦开挂辅助下载-一直是真的修改器一、杭州都莱破解版可以开透视的...
五分钟了解!天酷互娱有辅助工具... 五分钟了解!天酷互娱有辅助工具嘛(辅助)富赢开挂辅助软件-确实真的是有脚本一、天酷互娱有辅助工具嘛游...
6分钟了解!圣游辅助器(辅助)... 6分钟了解!圣游辅助器(辅助)金虎爷开挂辅助辅助器-一直是有工具圣游辅助器破解侠是真的助透视。每个模...
第4分钟了解!微乐小程序辅助插... 第4分钟了解!微乐小程序辅助插件(辅助)左右棋牌开挂辅助工具-切实真的有插件1、每一步都需要思考,不...
第七分钟了解!蛮王大厅透视辅助... 第七分钟了解!蛮王大厅透视辅助(辅助)搓白武汉麻将开挂辅助平台-真是真的有修改器第七分钟了解!蛮王大...
4分钟了解!小程序广东雀神智能... 4分钟了解!小程序广东雀神智能插件安装下载(辅助)新老夫子开挂辅助辅助-真是真的是有插件1、点击下载...
三分钟了解!新道游透视黑科技(... 三分钟了解!新道游透视黑科技(辅助)同城麻将开挂辅助平台-一直真的是有修改器运新道游透视黑科技辅助工...
第5分钟了解!云南捞腌菜辅助(... 第5分钟了解!云南捞腌菜辅助(辅助)春秋开挂辅助安装-确实是真的工具1、每一步都需要思考,不同水平的...
5分钟了解!中至黑科技辅助软件... 5分钟了解!中至黑科技辅助软件(辅助)开元棋牌开挂辅助神器-果然是真的平台中至黑科技辅助软件透视方法...