一、Java反射的概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象
二、反射的使用
获取class对象的三种方法:
- Object ——> getClass();
- 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
- 通过Class类的静态方法:forName(String className)(常用)
在运行期间,一个类,只有一个Class对象产生。
三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。
定义一个类供我们反射获取
package java_reflect;
import java.io.Serializable;
public class UserBean implements Serializable {
public UserBean(){
System.out.println("无参构造");
}
public UserBean(String username){
System.out.println("有参构造(username)="+username);
}
private UserBean(int id){
System.out.println("private有参构造(id)="+id);
}
public UserBean(int id,String username){
System.out.println("有参构造(id,username)="+id+"~"+username);
}
public String aString;
private int id;
private String username;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
System.out.println("username="+username);
}
public String getResult(){
return "结果";
}
private void testMethod(String message){
System.out.println("testMethod(String)");
}
}
1、获取类的class对象
try {
Class userClass = Class.forName("java_reflect.UserBean");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2、构造器的获取和运行
通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;
1.批量的方法:
public Constructor[] getConstructors():所有”公有的”构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
2.获取单个的方法,并调用:
public Constructor getConstructor(Class… parameterTypes):获取单个的”公有的”构造方法:
public Constructor getDeclaredConstructor(Class… parameterTypes):获取”某个构造方法”可以是私有的,或受保护、默认、公有;
调用构造方法:
Constructor–>newInstance(Object… initargs)
暴力访问(忽略掉访问修饰符)
Constructor–>setAccessible(true);
private static void getConstructor1() throws ClassNotFoundException {
Class class1 = Class.forName("java_reflect.UserBean");
System.out.println("===========获取所有公有构造方法=============");
Constructor[] constructor = class1.getConstructors();
for (Constructor obj : constructor) {
System.out.println(obj);
}
System.out.println("==========所有的构造方法(包括:私有、受保护、默认、公有)==============");
Constructor[] constructor2 = class1.getDeclaredConstructors();
for (Constructor obj : constructor2) {
System.out.println(obj);
}
}
private static void RunConstructor() throws Exception {
Class class1 = Class.forName("java_reflect.UserBean");
System.out.println("===========运行公有无参构造方法=============");
Constructor constructor = class1.getConstructor(null);//因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型
constructor.newInstance();
System.out.println("===========运行公有有参构造方法=============");
Constructor constructor2 = class1.getConstructor(String.class);
constructor2.newInstance("jerry");
System.out.println("===========运行公有多参构造方法=============");
Constructor constructor3=class1.getConstructor(int.class,String.class);
constructor3.newInstance(1,"jerry");
System.out.println("===========运行私有有参构造方法=============");
Constructor constructor4=class1.getDeclaredConstructor(int.class);
constructor4.setAccessible(true);//暴力访问(忽略掉访问修饰符)
constructor4.newInstance(2);
}
3、成员变量的获取和赋值
1.批量的
Field[] getFields():获取所有的”公有字段”
Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
2.获取单个的:
public Field getField(String fieldName):获取某个”公有的”字段;
public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
设置字段的值:
Field –> public void set(Object obj,Object value):
参数说明:
1.obj:要设置的字段所在的对象;
2.value:要为字段设置的值
/暴力反射,解除私有限定
Field –> setAccessible(true);
private static void getField1()throws Exception{
Class class1 = Class.forName("java_reflect.UserBean");
System.out.println("==========所有的公有成员变量==============");
Field[] fields=class1.getFields();
for(Field f:fields){
System.out.println(f);
}
System.out.println("==========所有成员变量(包括:私有、受保护、默认、公有)==============");
Field[] fields2=class1.getDeclaredFields();
for(Field f:fields2){
System.out.println(f);
}
}
private static void setField1()throws Exception{
Class class1 = Class.forName("java_reflect.UserBean");
System.out.println("==========获取公有成员变量并赋值==============");
Field field1=class1.getField("aString");
Object object=class1.newInstance();//生产对象
field1.set(object, "aaa");//将aaa赋值给成员变量aString
UserBean userBean=(UserBean)object;
System.out.println(userBean.aString);//验证
System.out.println("==========获取私有成员变量并赋值==============");
Field field2=class1.getDeclaredField("username");
Object object2=class1.newInstance();
field2.setAccessible(true);//暴力反射,解除私有限定
field2.set(object2, "jerry");
UserBean userBean2=(UserBean)object2;
System.out.println(userBean2.getUsername());//验证
}
4、方法的获取和执行
1.批量的:
public Method[] getMethods():获取所有”公有方法”;(包含了父类的方法也包含Object类)
public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
2.获取单个的:
public Method getMethod(String name,Class<?>… parameterTypes):
参数:
name : 方法名;
Class … : 形参的Class类型对象
public Method getDeclaredMethod(String name,Class<?>… parameterTypes)
调用方法:
Method –> public Object invoke(Object obj,Object… args):
参数说明:
obj : 要调用方法的对象;
args:调用方式时所传递的实参;
暴力反射
Method –> setAccessible(true);
private static void getMethod1()throws Exception{
Class class1 = Class.forName("java_reflect.UserBean");
System.out.println("==========获取所有公有方法(包含了父类的方法也包含Object类)==============");
Method[] methods= class1.getMethods();
for(Method method:methods){
System.out.println(method);
}
System.out.println("==========获取所有方法,包括私有的(不包括继承的)==============");
Method[] methods1= class1.getDeclaredMethods();
for(Method method:methods1){
System.out.println(method);
}
}
private static void runMethod1()throws Exception{
Class class1 = Class.forName("java_reflect.UserBean");
System.out.println("==========获取公有方法,并运行拿到返回值==============");
Method method=class1.getMethod("getResult", null);
Object obj=class1.newInstance();//生产对象
Object result=method.invoke(obj, null);//调用方法
System.out.println("返回值="+result);//验证方法返回值
System.out.println("==========获取公有方法,传值并运行拿到返回值==============");
Method method2=class1.getMethod("setUsername", String.class);
Object obj2=class1.newInstance();//生产对象
Object result2=method2.invoke(obj2, "jerry");//调用方法
System.out.println("返回值="+result2);//验证方法返回值(void返回值为null)
System.out.println("==========获取私有方法,并运行拿到返回值==============");
Method method3=class1.getDeclaredMethod("testMethod", String.class);
method3.setAccessible(true);
Object obj3=class1.newInstance();//生产对象
Object result3=method3.invoke(obj3, "参数信息");//调用方法
System.out.println("返回值="+result3);//验证方法返回值
}