愿天堂没有Java之框架技术
目录
JavaSE 笔记(九)
Java 是一门非常严谨的语言
反射
认识一下嘛
- 反射是指对于任何一个Class类,在运行的时候都可以直接得到这个类全部成分
- 全部成分指构造器对象
Constructor
,成员变量对象Field
,成员方法对象Method
- 这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制
关键
-
反射的第一步都是得到编译后的 Class 类对象,然后就可以得到 Class 的全部成分
1 2 3
HelloWorld.java -> javac -> HelloWorld.class Class c = HelloWorld.class;
获取类对象
-
方法一:Class类中的一个静态方法:forName(全限名:包名 + 类名)
1
Class c = Class.forName("poria.Test");
-
方法二:类名.class
1
Class c = Test.class;
-
方式三:对象.getClass() 获取对象对应类的Class对象
1 2
Test t = new Test(); Class c = t.getClass();
获取构造器对象
-
Class 类用于获取构造器的方法
方法 说明 Constructor<?>[] getConstructors()
返回所有构造器对象的数组(只能拿public的) Constructor<?>[] getDeclaredConstructors()
返回所有构造器对象的数组,存在就能拿到 Constructor<T> getConstructor(Class<?>... parameterTypes)
返回单个构造器对象(只能拿public的) Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
返回单个构造器对象,存在就能拿到 -
Constructor 类用于创建对象的方法
符号 说明 T newInstance(Object... initargs)
根据指定的构造器创建对象 public void setAccessible(boolean flag)
设置为true,表示取消访问检查,进行暴力反射
获取成员变量对象
-
Class 类用于获取成员变量的方法
方法 说明 Field[] getFields()
返回所有成员变量对象的数组(只能拿public的) Field[] getDeclaredFields()
返回所有成员变量对象的数组,存在就能拿到 Field getField(String name)
返回单个成员变量对象(只能拿public的) Field getDeclaredField(String name)
返回单个成员变量对象,存在就能拿到 -
Field 类中用于取值、赋值的方法
方法 说明 void set(Object obj, Object value)
赋值 Object get(Object obj)
获取值
获取方法对象
-
Class 类中用于获取成员方法的方法
方法 说明 Method[] getMethods()
返回所有成员方法对象的数组(只能拿public的) Method[] getDeclaredMethods()
返回所有成员方法对象的数组,存在就能拿到 Method getMethod(String name, Class<?>... parameterTypes)
返回单个成员方法对象(只能拿public的) Method getDeclaredMethod(String name, Class<?>... parameterTypes)
返回单个成员方法对象,存在就能拿到 -
Method 类中用于触发执行的方法
符号 说明 Object invoke(Object obj, Object... args)
运行方法 参数一:用obj对象调用该方法 参数二:调用方法的传递的参数(如果没有就不写) 返回值:方法的返回值(如果没有就不写)
作用
- 在运行时获得一个类的全部成分
- 破坏封装性
- 破坏泛型的约束性
- 做高级框架底层技术
注解
认识一下嘛
- Java 语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注
- 对 Java 中类、方法、成员变量做标记,然后进行特殊处理
自定义注解
-
格式
1 2 3
public @interface 注解名称 { public 属性类型 属性名() default 默认值 ; }
-
value 属性,如果只有一个 value 属性的情况下,使用 value 属性的时候可以省略 value 名称不写
元注解
-
就是用来注解注解的注解(绕口令
-
元注解有两个
- @Target:约束自定义注解只能在哪些地方使用
- 常用值
- TYPE,类,接口
- FIELD,成员变量
- METHOD,成员方法
- PARAMETER, 方法参数
- CONSTRUCTOR, 构造器
- LOCAL_VARIABLE, 局部变量
- @Retention:申明注解的生命周期
- 常用值
- SOURCE: 注解只作用在源码阶段,生成的字节码文件中不存在
- CLASS: 注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值.
- RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)
-
用例
1 2 3 4
@Target({ElementType.METHOD,ElementType.FIELD}) // 元注解 @Retention(RetentionPolicy.RUNTIME) // 一直活着,在运行阶段这个注解也不消失 public @interface MyTest { }
注解解析
-
注解的操作中经常需要进行解析,注解的解析就是判断是否存在注解,存在注解就解析出内容
-
注解相关接口
- Annotation:注解的顶级接口,注解都是 Annotation 类型的对象
- AnnotatedElement:该接口定义了与注解解析相关的解析方法
-
常用方法
方法 说明 Annotation[] getDeclaredAnnotations()
获得当前对象上使用的所有注解,返回注解数组。 T getDeclaredAnnotation(Class<T> annotationClass)
根据注解类型获得对应注解对象 boolean isAnnotationPresent(Class<Annotation> annotationClass)
判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false -
所有的类成分Class,Method,Field,Constructor,都实现了 AnnotatedElement 接口他们都拥有解析注解的能力
-
技巧
- 注解在哪个成分上,我们就先拿哪个成分对象。
- 比如注解作用成员方法,则要获得该成员方法对应的 Method 对象,再来拿上面的注解
- 比如注解作用在类上,则要该类的 Class 对象,再来拿上面的注解
- 比如注解作用在成员变量上,则要获得该成员变量对应的 Field 对象,再来拿上面的注解
单元测试
-
单元测试就是针对最小的功能单元编写测试代码,Java 程序最小的功能单元是方法,因此,单元测试就是针对 Java 方法的测试,进而检查方法的正确性
-
测试方法使用 @Test 注解标记
-
定义的测试方法必须是无参数无返回值,且公开的方法
注解 说明 @Test
测试方法 @BeforeEach
用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次。 @AfterEach
用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次。 @BeforeAll
用来静态修饰方法,该方法会在所有测试方法之前只执行一次。 @AfterAll
用来静态修饰方法,该方法会在所有测试方法之后只执行一次。
动态代理
认识一下嘛
- 代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这件事,动态代理就是用来对业务功能(方法)进行代理的
关键步骤
- 必须有接口,实现类要实现接口
- 创建一个实现类的对象,该对象为业务对象,然后为业务对象创建一个代理对象
用例
|
|
优点
- 非常的灵活,支持任意接口类型的实现类对象做代理,也可以直接为接本身做代理
- 可以为被代理对象的所有方法做代理
- 可以在不改变方法源码的情况下,实现对方法功能的增强
- 不仅简化了编程工作、提高了软件系统的可扩展性,同时也提高了开发效率