Learn && Live
虚度年华浮萍于世,勤学善思至死不渝
前言
Hey,欢迎阅读Connor学Java系列,这个系列记录了我的Java基础知识学习、复盘过程,欢迎各位大佬阅读斧正!原创不易,转载请注明出处:http://t.csdn.cn/aqid0,话不多说我们马上开始!
1.什么是泛型?为什么要使用泛型?
泛型,即参数化类型,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(称为类型形参),在使用或调用时传入具体的类型(类型实参)
泛型的本质是为了参数化类型,即在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型,这种参数类型可以用在类、接口、方法中,分别被称为泛型类、泛型接口、泛型方法
2.泛型是如何工作的?什么是类型擦除?
泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息,如List<String>在运行时仅用一个List表示
类型擦除:泛型信息只存在于代码编译阶段,在进入JVM之前,与泛型相关的信息会被擦除掉。在泛型类被类型擦除时,之前泛型类中的类型参数如果没有指定上限,如<T>则会被转译成普通的Object类型,如果指定了上限如<T extends String>则类型参数被替换成类型上限,这样做主要是为了能够与之前的Java版本代码兼容共存
3.什么是泛型中的限定通配符和非限定通配符?
限定通配符对类型进行了限制。有两种限定通配符,一种是<? extends T>,它通过确保类型必须是T的子类来设定类型的上界;另一种是<? super T>,它通过确保类型必须是T的父类来设定类型的下界
限定通配符为<?>,因为它可以用任意类型来替代
泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误
4.List<? extends T>和List<? super T>的区别?
List<? extends T>可以接受T和任何继承自T类型的对象
List<? extends T>可以接受T和任何是T的父类的对象
5.static方法与泛型?
静态方法无法访问类上定义的泛型,如果静态方法操作的引用数据类型不确定时,必须将泛型定义在该方法上,否则报错:Test cannot be referenced from a static context,这是因为泛型的T仅作为一个类型形参,只有在创建实例对象时才会被传递一个类型实参,此时才能真正确定下来类型
public class Test<T> {
...
public static <T> void show(T t) {
...
}
}
6.泛型使用时的几点注意
(1)泛型类可有多个参数<E1, E2, E3>
(2)构造器不用加
(3)泛型不同不可相互赋值,如List<String>和List<Integer>
(4)异常类不可用泛型
(5)T[] a = new T[n]; 🚫 T[] a = (T[]) new Object[n]; ⚪️
(6)List<Object>和List<Integer>无继承关系
7.介绍一下Java的反射机制?
每个类都有一个Class对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的.class文件,该文件内容保存着Class对象。类加载相当于Class对象的加载,类在第一次使用时才动态加载到JVM中,也可以通过Class.forName(“com.mysql.jdbc.Driver”)来手动控制类的加载,该方法会返回一个Class对象。
反射可以提供运行时类的信息,并且这个类可以在运行时才加载进来,甚至在编译期该类的.class不存在也可以加载进来。
反射机制相关的重要的类
类 | 含义 |
---|---|
java.lang.Class | 代表整个字节码、整个类 |
java.lang.reflect.Method | 代表字节码中的方法字节码、类中的方法,可以使用invoke()方法调用与Method对象关联的方法 |
java.lang.reflect.Constructor | 代表字节码中的构造器字节码、类中的构造器,可以使用Constructor创建新的对象 |
java.lang.reflect.Field | 代表字节码中的属性字节码、类中的成员变量,可以使用get()、set()方法读取和修改Field对象关联的方法 |
反射机制的应用场景
(1)工厂模式,使用反射机制,根据全限定类名获得某个类的Class实例
(2)Android Activity的创建过程
[https://mp.weixin.qq.com/s/bDe-6KiTbazC5FhUi-Z65A](https://mp.weixin.qq.com/s/bDe-6KiTbazC5FhUi-Z65A)
8.反射的优缺点?
优点
(1)可实现运行期的类型判断与操作
(2)Class.forName()可根据不同的全限定类名创建相应的Class对象,实现类的动态加载,提高代码的灵活度
缺点
(1)性能开销:反射涉及了动态类型的解析,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射
(2)安全限制:反射机制的特性导致使用反射技术要求程序必须在一个没有安全限制的环境中运行。
(3)内部暴露:由于反射允许代码执行一些在正常情况下不被允许的操作,如访问私有的属性和方法。因此反射可能会导致代码功能变化并破坏可移植性,因为反射代码可能破坏抽象性,当平台改变时,代码的行为就有可能也随着变化