JAVA反射机制、注解JAVA反射机制一. 概念二. 优缺点三. Class类的常用方法四. 通过反射机制获取获取Class对象获取构造方法的信息(Constructor)Constructor类中的常用方法获取成员变量的信息(Field)Field类中的常用方法获取方法的信息(Method)Method类中的常用方法注解一. 概念二. 注解的用途三. 注解类型元注解@Retention@Target@Documented@Inherited@Repeatable内置注释(用于预警)自定义注解注解的属性注解的快捷方式注解不支持继承
JAVA反射机制
一. 概念
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的功能称为Java语言的的反射机制。
二. 优缺点
优点: 在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
缺点:(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
三. Class类的常用方法
方法名 | 功能说明 |
static Class forName(String name) | 返回指定类名的Class对象 |
Object newInstance() | 调用缺省构造函数,返回Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类,接口,数组类或void)的名称 |
Class getSuperClass() | 返回当前Class对象的父类的Class对象 |
Class[] getInterfaces() | 获取当前Class对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Constructor[] getConstructors() | 返回一个包含某些Construtor对象的数组 |
Method getMethod(String name, Class<?>… T) | 返回一个指定名称和参数列表的Method对象 |
Field getDeclaredFields() | 返回一个Field对象的数组 |
四. 通过反射机制获取
获取Class对象
任何一个类都有一个隐含的静态成员变量class,通过该静态成员获取Class对象的引用。
1. 类名.class Class c1 = Student.class;
使用对象的getClass()方法获取Class对象的引用
2. 对象.getClass() Student stu = new Student(); Class c2 = stu.getClass();
使用Class类的静态方法forName(),它使用一个包含目标类的字符串作为输入,返回一个Class对象的引用。通过该方法获取Class对象时需要处理ClassNotFoundException异常,该异常代表找不到类或者类无法加载。
3. Class.forName(类的全限定名) // 全限定名:包名.类名 Class c3 = Class.forName("包名.类名");
4. 基本类型的包装类可以直接使用 类名.Type
获取构造方法的信息(Constructor)
方法 | 功能描述 |
getConstructors() | 返回一个Constructor对象的数组,这些对象为此Class对象所表示的类的所有公共构造方法; |
getDeclaredConstructors() | 返回一个Constructor对象的数组,这些对象为此Class对象所表示的类的所有构造方法 |
getConstructor(Class<?>...parameterTypes) | 返回一个Constructor对象,他代表此Class对象所表示的类的指定公共构造方法 |
getDeclaredConstructor(Class<?>...parameterTypes) | 返回一个Constructor对象,他代表此Class对象所表示的类或接口的指定公共构造方法 |
Constructor类中的常用方法
方法 | 功能描述 |
newInstance() | 使用Constructor对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。 |
isVarArgs() | 如果声明此构造方法可以带可变数量的参数,则返回true;否则,返回false |
setAccessible(boolean flag) | 返回值为true表示反射的对象在使用时应该取消Java语言访问检查;返回值为false则表示反射的对象应该实施Java语言访问检查 |
getParameterTypes() | 返回一组Class对象,这些对象表示此Constructor对象所表示的构造方法的形参类型 |
获取成员变量的信息(Field)
方法 | 功能描述 |
getField(String name) | 返回一个Field对象,它反映此Class对象所表示的类或接口的指定公共成员字段 |
getFields() | 返回一个Field对象的数组,这些对象反映此Class对象所表示的类或接口的所有可访问公共字段(public),包括父类中的字段(all + 非私有) |
getDeclaredField(String name) | 返回一个Field对象,该对象反映此Class对象所表示的类或接口的指定已声明字段。name参数是一个String,它指定所需字段的简称 |
getDeclaredFields() | 返回一个Field对象的数组,这些对象反映此Class对象所表示的类或接口的所声明的所有字段。包括公共、保护、默认访问和私有字段,但不包括继承的字段(自身 + 私有) |
Field类中的常用方法
方法 | 功能描述 |
get(Object obj) | 返回指定对象上此Field表示的字段的值 |
set(Object obj,Object value) | 将指定对象变量上此Field对象表示的字段设置为指定的新值 |
getName() | 返回此Field对象表示的字段的名称 |
getType() | 返回一个Calss对象,他代表此Field对象所表示字段的声明类型 |
getInt(Object obj) | 获取int类型或另一个通过扩展转换可以转换为int 类型 的基本类型的静态或实例字段的值。 |
setInt(Object obj,int i) | 讲字段的值设置为指定对象上的一个int值 |
getBoolean(Object obj) | 获取一个静态或实例boolean字段的值 |
setBoolean(Object obj,boolean z) | 将字段的值设置未指定对象上的一个boolean值 |
getFloat(Object obj) | 获取float类型或另一个通过扩展转换可以转换为float类型的基本类型的静态或实例字段的值 |
setFloat(Object obj,float f) | 将字段的值设置为指定对象上的一个float值 |
获取方法的信息(Method)
方法 | 功能描述 |
getMethods() | 返回一个Method对象的数组,这些对象反映此Class对象所表示的类或接口的公共方法(all + 非私有) |
getDeclaredMethods() | 返回一个Method对象的一个数组,这些对象反映此Class对象表示的类或接口声明的所有方法,包括公共、保护、默认访问和私有方法,但不包括继承的方法(自身+私有) |
getMethod(String name,Class<?>..parameterTypes) | 返回一个Method对象,它反映此Class对象所表示的类或接口的指定公共成员方法 |
getDeclaredMethod(String name,Class<?>..parameterTypes) | 返回一个Method对象,它反映此Class对象所表示的类或接口的指定已声明方法 |
Method类中的常用方法
方法 | 功能描述 |
getName() | 以String形式返回此Method对象表示的方法名称 |
getParameterTypes() | 按照声明顺序返回Class对象的数组,这些对象描述了此Method对象所表示的方法的形参类型 |
getReturnType() | 返回一个Class对象,该对象描述此Method对象所表示的方法的正式返回类型 |
getExceptionTypes() | 返回Class对象的数组,这些对象描述了声明将此Method对象表示的底层方法抛出的异常类型 |
invoke(Object obj,Object...args) | 对带有指定参数的指定对象该调用由此Method对象表示的底层方法 |
注解
一. 概念
注解也叫元数据,即一种描述数据的数据。,用于对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解。
一个注解准确意义上来说,只不过时一种特殊的注释而已。
注解的本质就是一个继承了Annotation接口的接口。
二. 注解的用途
1.生成文档,通过代码里的标识的元数据生成javadoc文档。
2.编译检查,通过代码里表示的元数据让编译器在编译期间进行检查验证。
3.编译时动态处理,编译时通过代码里标识的元数据动态处理,例如动态生成代码。
4.编译时动态处理,运行时通过代码里标识的元数据动态处理,例如使用反射注入实例。
三. 注解类型
- 元注解(用于定义注解的注解)
- 内置注解(Java自带的标准注解)
- 自定义注解
元注解
元注解是用于修饰注解的注解,元注解有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5 种。
@Retention
当@Retention应用到一个注解上的时候,它解释说明了这个注解的存活时间。
方法名 | 功能 | ||
RetentionPolicy.SOURCE | 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。 | ||
RetentionPolicy.CLASS | 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。 | ||
RetentionPolicy.RUNTIME | 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。 | ||
@Target
Target 是目标的意思,@Target 指定了注解运用的地方。
方法名 | 功能 |
ElementType.ANNOTATION_TYPE | 可以给一个注解进行注解 |
ElementType.CONSTRUCTOR | 可以给构造方法进行注解 |
ElementType.FIELD | 可以给属性进行注解 |
ElementType.LOCAL_VARIABLE | 可以给局部变量进行注解 |
ElementType.METHOD | 可以给方法进行注解 |
ElementType.PACKAGE | 可以给一个包进行注解 |
ElementType.PARAMETER | 可以给一个方法内的参数进行注解 |
ElementType.TYPE | 可以给一个类型进行注解,比如类、接口、枚举 |
@Documented
Documented和文档有关,它的作用是能够将注解中的元素包含到Javadoc中去。
@Inherited
Inherited是继承的意思,如果一个超类使用了@Inherited注解,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。
@Repeatable
Repeatable是可重复的意思,@Repeatable在需要对同一种注解多次使用时使用。
内置注释(用于预警)
注解类型 | 说明 |
@Override | 检查该方法是否是重新加载 |
@Deprecated | 标记已过时的方法 |
@SuppressWarning | 只是表一起忽略注解中声明的警告 |
@FunctionalInterface | 函数式接口 (Functional Interface) 就是一个具有一个方法的普通接口 |
自定义注解
public @interface 注解名{ //属性 }
注解的属性
注解的属性也叫做成员变量。注解只有成员变量没有方法。
注解的成员变量在注解的定义中以"无形参的方法"形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
int id();
String msg();
}
注解的快捷方式
所谓的快捷方式就是注解中定义了名为value的元素,并且在使用该注解时,如果该元素是唯一需要赋值的一个元素,那么此时无需使用key=value的语法,而只需在括号内给出value元素所需的值即可。
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface IntegerVaule{
int value() default 0;
String name() default "";
}
public class QuicklyWay {
@IntegerVaule(20)
public int age;
@IntegerVaule(value = 10000, name = "MONEY")
public int money;
}
注解不支持继承
注解是不支持继承的,因此不能使用关键字extends来继承某个@interface,但注解在编译后,编译器会自动继承java.lang.annotation.Annotation接口