java反射笔记
程序员文章站
2022-10-04 23:09:48
反射(reflect) 1. Class对象 1.1 什么是Class对象 当JVM加载某个class文件的时候,会自动创建一个唯一的Class对象(注意:由同一个类加载器加载的class文件),这个Class对象包含了整个class类的信息(例如:类的名称、访问修饰符、字段、字段描述、方法等等一切 ......
反射(reflect)
1. class对象
1.1 什么是class对象
当jvm加载某个class文件的时候,会自动创建一个唯一的class对象(注意:由同一个类加载器加载的class文件),这个class对象包含了整个class类的信息(例如:类的名称、访问修饰符、字段、字段描述、方法等等一切信息)。当使用new关键字创建这个类的实例时,jvm都会使用这个class对象来创建类的实例。
1.1 获取class对象方式
方式 | 说明 |
---|---|
test.class | 通过类名.class直接获取 |
t1.getclass() | 通过对象的getclass()方法获取 |
class.forname("...") | 使用class类的forname静态方法获取,参数给的是完整类名(包名+类名) |
2. 反射
2.1 什么是反射
所谓的反射,是在程序运行时动态获得任何一个class对象的成员信息(类信息、字段、构造方法、成员方法等),并且能在运行时依据某个class对象创建当前类的实例。
2.2 class常用api
方法 | 说明 |
---|---|
newinstance() | 创建类实例 |
getname() | 获取类的完整类名 |
getsimplename() | 获取类的简单类名 |
getpackage() | 获取类对应的包信息 |
getsuperclass() | 获取父类的class对象 |
getinterfaces() | 获取实现的所有接口 |
getclassloader() | 获取当前类的类加载器 |
getconstructor(..) | 获取公共且明确参数类型的构造方法 |
getdeclaredconstructor(..) | 获取受保护且明确参数类型的构造方法 |
getconstructors() | 获取所有公共的构造方法 |
getdeclaredconstructors() | 获取所有(包括受保护)的构造方法 |
getfield(..) | 根据字段名称获取某一个公共的字段 |
getdeclaredfield(..) | 根据字段名称获取当前类某一个的字段(包括受保护的) |
getfields() | 获取所有公共的字段,包括继承自父类的公共字段 |
getdeclaredfields | 获取当前类所有字段,包括受保护的(不包括继承父类的字段) |
getmethod(..) | 根据方法名以及参数类型获取一个公共的方法 |
getdeclaredmethod(..) | 根据方法名以及参数类型获取当前类的一个受保护的方法 |
getmethods() | 获取所有公共的方法(包括继承自父类的公共方法) |
getdeclaredmethods() | 获取当前类的所有方法,包括受保护的(不包括继承父类的方法) |
isannotation() | 此class是否是一个注解 |
isannotationpresent(..) | 当前class时是否定义了某个注解 |
getannotation(..) | 获取当前类上定义的某个注解 |
getannotations() | 获取当前类上定义的所有注解 |
isenum() | 此class是否是一个枚举 |
isarray() | 此class是否是一个数组类型 |
isinterface() | 此class是否是一个接口 |
... | 其他api请参照官方文档 |
public class testclass { public static void main(string[] args) throws exception{ class<?> clazz = class.forname("edu.nf.reflect.users"); //通过class对象来创建实例,当前类必须提供一个公开并且无参的构造方法 users user = (users) clazz.newinstance(); //获取类的完整类名 system.out.println(clazz.getname()); //获取类的简单类名 system.out.println(clazz.getsimplename()); //获取类所在的包名 system.out.println(clazz.getpackage().getname()); //获取当前类的父类的class system.out.println(clazz.getsuperclass()); //获取当前类实现的所有接口 system.out.println(clazz.getinterfaces()); //获取加载这个类的类加载器 system.out.println(clazz.getclassloader()); //获取公共并且参数类型为string的构造方法 clazz.getconstructor(string.class); //获取私有并且参数为int类型的构造方法 clazz.getdeclaredconstructor(integer.type); //获取所有公共的构造方法 constructor[] consarray1 = clazz.getconstructors(); //获取所有构造方法,包括公共和是有的 constructor[] consarray2 = clazz.getdeclaredconstructors(); //获取某一个公共的字段,参数指定字段的名字 field f1 = clazz.getfield("address"); system.out.println(f1.getname()); //获取某一个受保护的字段 field f2 = clazz.getdeclaredfield("tel"); system.out.println(f2.getname()); system.out.println("-----------------------"); //获取所有公共的字段,包括继承自父类的公共字段 field[] fieldarray1 = clazz.getfields(); for (field field : fieldarray1) { system.out.println(field.getname()); } system.out.println("-----------------------"); //获取所有字段,包括受保护的(不包括继承父类的字段) field[] fieldarray2 = clazz.getdeclaredfields(); for (field field : fieldarray2) { system.out.println(field.getname()); } system.out.println("-----------------------"); //获取某一个公共的方法(第一个参数指定方法名,第二个参数指定方法参数的类型,这是一个可变参数,有多少个参数就要指定多少个类型) method m1 = clazz.getmethod("say", string.class); system.out.println(m1.getname()); //获取某一个受保护的方法 method m2 = clazz.getdeclaredmethod("call"); system.out.println(m2.getname()); system.out.println("-----------------------"); //获取所有公共的方法(包括继承自父类的公共方法) method[] methodarray1 = clazz.getmethods(); for (method method : methodarray1) { system.out.println(method.getname()); } system.out.println("-----------------------"); //获取本类的所有方法,包括受保护的(不包括父类的方法) method[] methodarray2 = clazz.getdeclaredmethods(); for (method method : methodarray2) { system.out.println(method.getname()); } } }
2.3 class对象中的成员
成员 | 说明 |
---|---|
constructor | 用于描述类的构造方法 |
field | 用于描述类的字段 |
method | 用于描述类的方法 |
parameter | 用于描述方法或构造方法的参数信息 |
2.3.1 constructor常用api
api | 说明 |
---|---|
getname() | 获取当前构造方法的名称 |
getparametercount() | 获取构造方法的参数个数 |
getdeclaringclass() | 获取声明此构造方法的class类 |
setaccessible(..) | 设置访问开关 |
newinstance(..) | 使用当前的constructor构建实例 |
... | 其他api请参照官方文档 |
public class testcons { public static void main(string[] args) throws exception{ //加载users的class信息,并构建class对象 class<?> clazz = class.forname("edu.nf.reflect.users"); //通过class对象访问构造方法信息, // 根据构造方法的参数类型获取某一个公共的构造方法 constructor cons1 = clazz.getconstructor(int.class); // 访问受保护的构造方法 constructor cons2 = clazz.getdeclaredconstructor(int.class); //构造方法的名称 system.out.println(cons1.getname()); //获取构造方法的参数个数 system.out.println(cons1.getparametercount()); //获取定义这个构造方法的class类 system.out.println(cons1.getdeclaringclass()); //通过构造方法来创建类的实例 //由于构这个造方法是私有的,因此必须强制打开访问开关 cons1.setaccessible(true); //然后通过newinstance方法来创建类的实例,并传入构造方法所需的参数 users user = (users)cons1.newinstance(21); //获取所有的构造方法(包括私有和公有的) constructor[] cons = clazz.getdeclaredconstructors(); for (constructor con : cons) { system.out.println("参数个数: "+con.getparametercount()); } } }
2.3.2 field常用api
api | 说明 |
---|---|
gettype() | 获取当前字段类型 |
getname() | 获取当前字段名称 |
get(..) | 获取当前字段的值 |
set(..) | 给当前字段赋值 |
setaccessible(..) | 设置访问开关 |
... | 其他api请参照官方文档 |
public class testfield { public static void main(string[] args) throws exception{ class<?> clazz = class.forname("edu.nf.reflect.users"); //创建类的实例 object instance = clazz.newinstance(); //获取一个受保护的字段 field f = clazz.getdeclaredfield("tel"); //打开访问开关 f.setaccessible(true); //给字段赋值(第一个参数指定当前类的实例,第二个参数是具体的值) f.set(instance, "123456"); //取值(get方法的参数也是指定当前类的实例) system.out.println(f.get(instance)); //获取字段的类型 system.out.println(f.gettype()); //获取字段的名称 system.out.println(f.getname()); } }
2.3.3 method常用api
api | 说明 |
---|---|
getname() | 获取当前方法名称 |
getreturntype() | 获取当前方法的返回值 |
getparametercount() | 获取当前方法参数的个数 |
getparameters() | 获取当前方法的参数对象 |
getparametertypes() | 获取当前方法的所有参数类型 |
setaccessible(..) | 设置访问开关 |
invoke(..) | 回调当前的method |
... | 其他api请参照官方文档 |
public class testmethod { public static void main(string[] args) throws exception { class<?> clazz = class.forname("edu.nf.reflect.users"); //构建当前类的实例 object instance = clazz.newinstance(); //获取受保护的call方法 method method = clazz.getdeclaredmethod("call", string.class); //获取方法的名称 system.out.println(method.getname()); //获取方法的返回值类型 system.out.println(method.getreturntype()); //获取方法参数的个数 system.out.println(method.getparametercount()); //获取方法的所有参数对象 system.out.println(method.getparameters()); //获取方法中所有参数的类型 class<?>[] paramstype = method.getparametertypes(); for (class<?> aclass : paramstype) { system.out.println(aclass); } //调用当前方法(第一个参数是当前类的实例,第二个参数开始是方法所需的参数) //invoke方法返回的是当前调用的方法的返回值 //这个方法是受保护的,因此需要先打开访问开关 method.setaccessible(true); object returnvalue = method.invoke(instance, "12345678"); system.out.println(returnvalue); } }
2.3.4 parameter常用api
api | 说明 |
---|---|
gettype() | 获取参数类型 |
getname() | 获取参数的名称(说明:jdk8默认编译的时候是不会将参数名信息保存在字节码中,如果想要获取参数名,那么在编译时就需要加上编译参数 ,如:javac -parameters users.java) |
... | 其他api请参照官方文档 |
public class testparameter { public static void main(string[] args) throws exception { class<?> clazz = class.forname("edu.nf.reflect.users"); //先获取指定的受保护的方法 method callmethod = clazz.getdeclaredmethod("call", string.class); //获取该方法的参数信息 parameter[] params = callmethod.getparameters(); for (parameter param : params) { //获取参数的类型 system.out.println(param.gettype()); //获取参数的名称(在jdk8之前是没有办法获取参数名的,必须通过第三方字节码工具来获取) //jdk8默认编译的时候是不会讲参数名信息保存在字节码中 //如果想要获取参数名,那么在编译时就需要加上编译参数 //如:javac -parameters users.java system.out.println(param.getname()); } } }
上一篇: angularJs select选择控件代码实例分析
下一篇: 02-Mysql数据库----初识