文章目录
- Java反射
- 一、泛型
- 1、何为泛型?
- 2、泛型通配符
- Q:泛型擦除是什么?
- 3、泛型上限和下限
- 二、反射
- 1、何为反射?
- 2、反射有什么用?
- 3、反射应用场景有哪些?
- Q:反射的优缺点?
- 4、反射获取Class类对象的4种方式
- 5、反射API有几类?
- 6、反射获取实例化对象
- 三、代理模式
- 1、代理模式
- 2、静态代理
- 3、动态代理
- 1、JDK动态代理机制
- Q:为什么 JDK 动态代理要基于接口实现?而不是基于继承来实现?
- Q:JDK 动态代理中,目标对象调用自己的另一个方法,会经过代理对象吗?
- Q:为什么不使用静态代理而使用动态代理?
- 2、CGLIB动态代理机制
- 3、JDK动态代理和CGLIB动态代理比较
- 4、静态代理和动态代理比较
- 四、注解
- 1、何为注解?
- Q:注解的解析方法有?
Java反射
一、泛型
1、何为泛型?
泛型(Generics),是指在定义时不指定信息的具体数据类型,而是暂时用一个 标识符 来代替,当外部实例化对象的时候再来指定具体的数据类型 (定义时不指定,使用标识符代替,使用时指定)。
优点: 极大提升程序的灵活性,提升类/接口的拓展性,泛型可以指代类中成员变量的数据类型,方法的返回值类型以及方法的参数类型。
2、泛型通配符
? 表示可以任意类型的泛型对象。
Q:泛型擦除是什么?
所谓的泛型擦除,官方名叫“类型擦除”。
Java的泛型是伪泛型,这是因为Java在编译期间,所有的类型信息都会被擦掉。
也就是说,在运行的时候是没有泛型的。
3、泛型上限和下限
- 泛型上限(最大类型,小于等于上限才可以):表示实例化时具体的数据类型,可以是 上限类型的子类或者时上限类型本身 ,用 extends 表示。
使用:类名 <泛型标识 extends 上限类名> - 泛型下限(最小类型,大于等于下限都可以):表示实例化时具体的数据类型,可以是 下限类型的父类或者是下限类型本身,用 super 表示。
使用:类名 <泛型标识 super 下限类名>
二、反射
1、何为反射?
JAVA反射机制是在 运行状态 中,对于任意一个类,都能够知道这个 类的所有属性和方法 ;对于任意一个对象,都能够调用它的任意一个方法和属性;这种 动态获取的信息以及动态调用对象方法的功能 称为java语言的反射机制。
反射就是在运行时获取类的 所有属性和方法(如构造器、成员变量、成员方法),得到编译后的class文件对象 是Java反射的核心。
2、反射有什么用?
通过java语言中的反射机制可以 操作字节码文件(可以读和修改字节码文件。)通过反射机制可以操作代码片段(class文件)。
3、反射应用场景有哪些?
如常见的 SSM框架中、动态代理、注解 等。
Q:反射的优缺点?
4、反射获取Class类对象的4种方式
5、反射API有几类?
反射 API 用来生成 JVM 中的 类、接口或对象 的信息。
① Class类: 反射的核心类,可以获取类的属性,方法等信息。
② Field类: Java.lang.reflect 包中的类,表示类的成员变量,可以用来获取和设置类中的属性值。
③ Method类: Java.lang.reflect 包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。
④ Constructor类: Java.lang.reflect 包中的类,表示类的构造方法。
⑤ Annotation类: 类的注解。
6、反射获取实例化对象
取得Class类对象的一个最直接的好处就是 通过反射实例化对象,该方法为:
- 对象.newInstance()
注:newInstance()方法内部实际上调用了无参数构造方法,必须保证无参构造存在才可以 ,否则会抛出java.lang.InstantiationException异常。
三、代理模式
注意: JDK 动态代理有一个最致命的问题是其 只能代理实现了接口的类。(即一个类没有实现接口,那么JDK动态代理无法代理)
1、代理模式
2、静态代理
静态代理:手动编写代理类,实现接口(接口一旦改动,代理类和实现类都需要修改)
3、动态代理
动态代理是在 运行时 动态生成类字节码,并加载到JVM中,不需要手动创建代理类、实现接口,可以直接代理实现类。
常见的动态代理,如 JDK动态代理、CGLIB动态代理 等。
1、JDK动态代理机制
通过 反射 来接收被代理的类,在不改变原来目标方法功能的前提下,在代理中增强自己的功能代码。并且要求 被代理的类必须实现一个接口 。
JDK动态代理的核心 是InvocationHandler接口和Proxy类。
Q:为什么 JDK 动态代理要基于接口实现?而不是基于继承来实现?
答:因为JDK动态代理生成的对象 默认是继承代理Proxy ,Java不支持多继承,所以JDK动态代理要基于接口来实现。
Q:JDK 动态代理中,目标对象调用自己的另一个方法,会经过代理对象吗?
答:不会,内部调用方法使用的对象是目标对象本身,被调用的方法不会经过代理对象。
Q:为什么不使用静态代理而使用动态代理?
静态代理是代理类在编译期间就创建好了,在编译时就已经将接口,被代理类,代理类等确定下来。如果有很多类很多接口需要代理,那么就只能使用代码提前写死,不够灵活;
使用了动态代理之后,不需要手动创建代理类,全部交给代理去完成对代理类的创建,实现无侵入式的代码扩展,这也是符合面向对象编程原则的操作。
2、CGLIB动态代理机制
3、JDK动态代理和CGLIB动态代理比较
- JDK动态代理只能代理实现了接口的类或者直接代理接口。而CGLIB可以代理未实现任何接口的类。另外,CGLIB动态代理是通过生成—个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为finall类型的类和方法。
- 就二者的效率来说,大部分情况都是JDK动态代理要更优秀,随着JDK版本的升级,这个优势更加明显。
4、静态代理和动态代理比较
- 灵活性: 动态代理更加灵活,不需要必须实现接口,可以直接代理实现类,并且可以不需要针对每个目标类都创建一个代理类。另外,静态代理中,接口一旦新增加方法,目标对象和代理对象都要进行修改,这是非常麻烦的!
- JVM层面: 静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的class文件。而动态代理是在运行时动态生成类字节码,并加载到JVM中的。
四、注解
1、何为注解?
注解是一种标记,使类或接口附加额外信息,帮助编译器和JVM完成一些特定功能,例如 @Override —— 标识一个方法是重写方法。
元注解 是自定义注解的注解,例如:
@Target : 约束作用位置;
@Rentention : 约束生命周期;
@Documented : 表明这个注解应该被 javadoc 记录。
注解生命周期有3大类,分别是:
- RetentionPolicy.SOURCE:给编译器用的,不会写入class文件。
- RetentionPolicy.CLASS:会写入class文件,在类加载阶段丢弃,也就是运行的时候就没这个信息了。
- RetentionPolicy.RUNTIME:会写入class文件,永久保存,可以通过反射获取注解信息。