JavaSE-反射、注解、断言
反射(Reflection)
反射是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
- java.lang.Class:代表一个类
- java.lang.reflect.Constructor:构造器
- java.lang.reflect.Field:成员变量
- java.lang.reflect.Method:方法
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息,我们可以通过这个对象看到类的结构
- 一个类在内存中只有一个Class对象
- 一个类被加载后,类的整个结构都会被封装在Class对象中
获取反射对象
反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分
获取CLass对象的方法
- 若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高
Class clazz = Person.class;- 类:Object.class 或者 Class.class
- 接口:Comparable.class
- 数组:String[].class 或者 int[][].class
- 枚举:Override.class
- 注解:ElementType.class
- 基本数据类型:Integer.class
- void空类型:void.class
- 已知某个类的实例,调用该实例的Object类的getClass()方法获取Class对象
Class clazz = person.getClass();
- 已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()方法获取,可能抛出ClassNotFoundException异常
Class clazz = Class.forName("com.demo.pojo.Person");
- 内置基本数据类型可以直接用类名.Type
- 利用ClassLoader
Class类常用方法
| 常用方法 | 返回值类型 | 说明 |
|---|---|---|
| newInstance() | T | 创建由此类对象表示的类的新实例 |
| forName(String className) | static Class | |
| forName(String name,boolean initialize,ClassLoader loader) | static Class | |
| getClassLoader() | ClassLoader | |
| asSubclass(Class clazz) | Class | |
| getComponentType() | Class | |
| getDeclaringClass() | Class | |
| getEnclosingClass() | Class | |
| getSuperclass() | Class | 返回该Class对象对应类的超类的Class对象 |
| getInterfaces() | Class[] | 返回该Class对象对应类所实现的全部接口 |
| getClasses() | class[] | |
| getDeclaredClasses() | Class[] | 返回该Class对象对应类所在的外部类 |
| getConstructors() | Constructor[] | 返回所有构造器对象的数组(只能拿public的) |
| getDeclaredConstructors() | Constructor[] | 返回所有构造器对象的数组,存在就能拿到 |
| getConstructor(class... parameterTypes) | Constructor | 返回单个构造器对象(只能拿public的) |
| getDeclaredConstructor(Class... parameterTypes) | Constructor | 返回单个构造器对象,存在就能拿到 |
| getEnclosingConstructor() | Constructor | |
| getFields() | Field[] | 返回所有成员变量对象的数组(只能拿public的) |
| getDeclaredFields() | Field[] | 返回所有成员变量对象的数组,存在就能拿到 |
| getField(String name) | Field | 返回单个成员变量对象(只能拿public的) |
| getDeclaredField(String name) | Field | 返回单个成员变量对象,存在就能拿到 |
| getMethods() | Method[] | 返回所有成员方法对象的数组(只能拿public的) |
| getDeclaredMethods() | Method[] | 返回所有成员方法对象的数组,存在就能拿到 |
| getMethod(String name,class... parameterTypes) | Method | 返回单个成员方法对象(只能拿public的) |
| getDeclaredMethod(String name,class... parameterTypes) | Method | 返回单个成员方法对象,存在就能拿到 |
| getEnclosingMethod() | Method | |
| getAnnotations() | Annotation[] | |
| getDeclaredAnnotations() | Annotation[] | |
| getAnnotation(Class annotationClass) | A | |
| getDeclaredAnnotation(class annotationClass) | A | |
| getAnnotatedInterfaces() | AnnotatedType[] | |
| getAnnotatedSuperclass() | AnnotatedType | |
| getAnnotationsByType(Class annotationClass) | A[] | |
| getDeclaredAnnotationsByType(class annotationClass) | A[] | |
| getTypeName() | String | |
| getTypeParameters() | TypeVariable[] | |
| getGenericInterfaces() | Type[] | |
| getGenericSuperclass() | Type | |
| getName() | String | 以字符串形式返回此Class对象所表示的类的名称 |
| getSimpleName() | String | 以字符串形式返回此Class对象所表示类的简称 |
| getCanonicalName() | String | |
| getModifiers() | int | 返回此类的所有修饰符;由public/protected/private/final/static/abstract组成 |
| getPackage() | Package | 获取此类的包 |
| getResource(String name) | URL | 查找具有给定名称的资源 |
| getResourceAsStream(String name) | InputStream | 查找具有给定名称的资源 |
| getProtectionDomain() | ProtectionDomain | |
| getSigners() | Object[] | 获得这个类的签名者 |
| getEnumConstants() | T[] | |
| cast(Object obj) | T | |
| desiredAssertionStatus() | boolean | |
| isAnnotation() | boolean | 判断是否表示一个注解类型 |
| isAnnotationPresent(class annotationClass) | boolean | 判断此Class对象是否使用了Annotation修饰 |
| isAnonymousClass() | boolean | 返回此Class对象是否是一个匿名类 |
| isArray() | boolean | 判断此Class对象是否是一个数组类 |
| isAssignableFrom(class cls) | boolean | 判断此Class对象是否是一个匿名类 |
| isEnum() | boolean | 判断此Class对象是否是一个枚举 |
| isInterface() | boolean | 判断此Class对象是否是一个接口 |
| isInstance(Object obj) | boolean | 判断obj是否是此Class对象的实例 |
| isLocalClass() | boolean | 判断此Class对象是否是一个本地类 |
| isMemberClass() | boolean | 判断此Class对象是否是一个成员类 |
| isPrimitive() | boolean | 判断此Class对象是否是一个基本类型 |
| isSynthetic() | boolean | 判断此Class对象是否是一个合成类 |
| toGenericString() | String | 返回描述此类的字符串,包括有关修饰符和类型参数的信息 |
| toString() | String | 将对象转换为字符串 |
Constructor常用方法
| 常用方法 | 返回值类型 | 说明 |
|---|---|---|
| equals(Object obj) | boolean | |
| getAnnotatedReceiverType() | AnnotatedType | |
| getAnnotatedReturnType() | AnnotatedType | |
| getAnnotation(Class annotationClass) | T | |
| getDeclaredAnnotations() | Annotation[] | |
| getDeclaringClass() | Class | |
| getExceptionTypes() | Class[] | |
| getGenericExceptionTypes() | Type[] | |
| getGenericParameterTypes() | Type[] | |
| getModifiers() | int | |
| getName() | String | |
| getParameterAnnotations() | Annotation[][] | |
| getParameterCount() | int | |
| getParameterTypes() | Class[] | |
| getTypeParameters() | TypeVariable[] | |
| hashCode() | int | |
| isSynthetic() | boolean | |
| isVarArgs() | boolean | |
| newInstance(Object... initargs) | T | |
| toGenericString() | String | |
| toString() | String |
Field常用方法
| 常用方法 | 返回值类型 | 说明 |
|---|---|---|
| equals(Object obj) | boolean | |
| get(Object obj) | Object | |
| getAnnotatedType() | AnnotatedType | |
| getAnnotation(Class annotationClass) | T | |
| getAnnotationsByType(Class annotationClass) | T[] | |
| getBoolean(Object obj) | boolean | |
| getByte(Object obj) | byte | |
| getChar(Object obj) | char | |
| getDeclaredAnnotations() | Annotation[] | |
| getDeclaringClass() | Class | |
| getDouble(Object obj) | double | |
| getFloat(Object obj) | float | |
| getGenericType() | Type | |
| getInt(Object obj) | int | |
| getLong(Object obj) | long | |
| getModifiers() | int | |
| getName() | String | |
| getShort(Object obj) | short | |
| getType() | Class | |
| hashCode() | int | |
| isEnumConstant() | boolean | |
| isSynthetic() | boolean | |
| set(Object obj,Object value) | void | |
| setBoolean(Object obj,boolean z) | void | |
| setByte(Object obj,byte b) | void | |
| setChar(Object obj,char c) | void | |
| setDouble(Object obj,double d) | void | |
| setFloat(Object obj,float f) | void | |
| setInt(Object obj,int i) | void | |
| setLong(Object obj,long l) | void | |
| setShort(Object obj,short s) | void | |
| toGenericString() | String | |
| toString() | String |
Method常用方法
| 常用方法 | 返回值类型 | 说明 |
|---|---|---|
| equals(Object obj) | boolean | |
| getAnnotatedReturnType() | AnnotatedType | |
| getAnnotation(Class annotationClass) | T | |
| getDeclaredAnnotations() | Annotation[] | |
| getDeclaringClass() | Class | |
| getDefaultValue() | Object | |
| getExceptionTypes() | Class[] | |
| getGenericExceptionTypes() | Type[] | |
| getGenericParameterTypes() | Type[] | |
| getGenericReturnType() | Type | |
| getModifiers() | int | |
| getName() | String | |
| getParameterAnnotations() | Annotation[][] | |
| getParameterCount() | int | |
| getParameterTypes() | Class[] | |
| getReturnType() | Class | |
| getTypeParameters() | TypeVariable[] | |
| hashCode() | int | |
| invoke(Object obj, Object... args) | Object | |
| isBridge() | boolean | |
| isDefault() | boolean | |
| isSynthetic() | boolean | |
| isVarArgs() | boolean | |
| toGenericString() | String | |
| toString() | String |
注解(Annotation)
注解是从JDK5开始引入的新技术,Java增加了对元数据的支持,也就是Annotation.注解其实是代码里的特殊标记,这些标记可以在编译、类加载、运行时被其他程序(比如编译器等)读取,并执行相应的处理.通过使用注解,程序开发人员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充的信息.从某些方面来看,Annotation就像修饰符一样,可用于修饰包/类/构造器/方法/成员变量/参数/局部变量的声明,这些信息被存储在Annotation的"name=value"对中,然后可以通过反射机制编程实现对这些元数据的访问
基本注解
Java提供了5个基本的注解,这5个基本注解都定义在java.lang包下
| 基本注解 | 说明 |
|---|---|
| @Override | 重写父类方法;告诉编译器检查这个方法,保证父类要包含一个被该方法重写的方法,否则就会编译出错 |
| @Deprecated | 已过时;用于表示某个类/方法已过时,编译器会给出警告 |
| @SuppressWarnings | 抑制编译器警告;表示取消显式指定的编译器警告,可用于该程序元素的所有子元素 |
| @SafeVarargs | 抑制堆污染警告;泛型擦除时,把一个不带泛型的对象赋值给一个带泛型的变量,就会发生堆污染 |
| @FunctionalInterface | 函数式接口;如果接口中只有一个抽象方法,该接口就是函数式接口(可以包含多个默认方法或静态方法) |
- @SuppressWarnings("all")
- @SuppressWarnings("unchecked")
- @SuppressWarnings(value={"unchecked","deprecation"})
元注解
Java在java.lang.annotation包下提供了6个元注解(meta annotation)
| 元注解 | 说明 |
|---|---|
| @Target | 约束自定义注解只能在哪些地方使用 |
| @Retention | 申明注解的声明周期 |
| @Documented | 指定该注解类将被javadoc工具提取成文档 |
| @Inherited | 指定被它修饰的注解类将具有继承性;如果某个类使用了@XXX注解修饰,则其子类将自动被@XXX修饰 |
| @ | |
| @Repeatable | 重复注解(JDK8) |
@Target详解
public @interface Target {
ElementType[] value();
}
| @Target支持的值 | 说明 |
|---|---|
| ElementType.TYPE | 类/接口 |
| ElementType.CONSTRUCTOR | 构造器 |
| ElementType.FIELD | 成员变量 |
| ElementType.LOCAL_VARIABLE | 局部变量 |
| ElementType.METHOD | 成员方法 |
| ElementType.PARAMETER | 方法参数 |
| ElementType.PACKAGE | 包定义 |
| ElementType.ANNOTATION_TYPE | 只能修饰Annotation |
@Retention详解
public @interface Retention {
RetentionPolicy value();
}
| @Retention支持的值 | 说明 |
|---|---|
| RetentionPolicy.CLASS | 注解只作用在源码阶段,生成的字节码文件中不存在注解 |
| RetentionPolicy.RUNTIME | [默认值]注解作用在源码阶段/字节码文件阶段,运行阶段不存在注解 |
| RetentionPolicy.SOURCE | [开发常用]注解作用在源码阶段,字节码文件阶段,运行阶段 |
@Documented详解
public @interface Documented {
}
@Inherited详解
public @interface Inherited {
}
自定义注解
注解可用于修饰任何程序元素,包括类/接口/方法等
- value属性(特殊属性):如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写
- 但是如果有多个属性, 且多个属性没有默认值,那么value名称是不能省略的
- 如果没有默认值,就必须给注解赋值
public @interface 注解名{
public 属性类型 属性名() default 默认值;
}
public @interface MyTag {
String name() default "admin";
int age() default 18;
String value();
}
提取Annotation信息
断言
断言机制允许在测试期间向代码中插入一些检查语句.当代码发布时,这些输入的检测语句将会被自动地移走.断言失败是致命的,不可回复的错误.断言检查只用于开发和测试阶段
Java引入了 assert 关键字,assert使用语法:
- assert 条件; // 如果条件判断为true,程序继续执行;如果条件判断为false,则会终止程序并报出AssertionError异常
- assert 条件:表达式; // 如果条件判断为true,程序继续执行;如果条件判断为false,则会终止程序并报出你所输入的错误信息