反射机制
简介
通过Java语言中的反射机制可以操作字节码文件,反射机制允许程序在执行期间借助ReflectionAPI获取任何类内部的信息,并能直接操作任意对象的内部属性以及方法
反射机制存在java.lang.reflect.*;
包下
反射机制重要的类
-
java.lang.Class:代表整个字节码,代表一个类型,代表整个类。
-
java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。
-
java.lang.reflect.Constructor:代表字节码中的构造方法字节码。代表类中的构造方法
-
java.lang.reflect.Field:代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)。
获取Class实例对象的三种方法
第一种:已知一个类的全名,且该类在类路径下,可以通过Class类的静态方法获取forName()获取
Class c = Class.forName("完整类名");
第二种:已知一个类的实例,调用该实例的getClass()方法获取Class对象
Class c = 引用对象.getClass();
第三种:已知具体的类,通过获取类的class属性
Class c = 任何类.class;
- 首先有一个实体类User
package pojo;
public class User {
private int id;
public String name;
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
-
三种获取方式
import pojo.User; public class Demo03 { public static void main(String[] args) throws ClassNotFoundException { //第一种方法 Class c = Class.forName("pojo.User"); System.out.println(c.getName()); //第二种方式 User user = new User(); Class c2 = user.getClass(); System.out.println(c2.getName()); //第三种方式 Class c3 = User.class; System.out.println(c3.getName()); } }
可以用Class类的类型为
- class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
- interface:接口
- []:数组
- enum:枚举
- annotation:注解
- primitive type:基本数据类型
- void
Class c1 = Object.class;//类
Class c2 = Comparable.class;//接口
Class c3 = String[].class;//一维数组
Class c4 = int[][].class;//二位数组
Class c5 = Override.class;//注解
Class c6 = ElementType.class; //枚举类型
Class c7 = Integer.class; //基本数据类型
Class c8 = void.class;
Class c9 = Class.class;
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
//只要元素类型与维度一样,就是同一个Class
int[] a = new int[10];
int[] b = new int[100];
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
通过反射来创建对象
第一种方式:通过调用Class对象的newInstance()方法
- 类必须含有无参构造器
- 类的构造器访问权限足够
//第一种方式
Class c1 = Class.forName("pojo.User");
User user = (User)c1.newInstance();
System.out.println(user);//获取类名
第二中方式:通过获得构造器,再通过newInstance来创建对象
//第二种方式
Constructor declaredConstructor = c1.getDeclaredConstructor();//获取构造器
Constructor constructor = c1.getConstructor(int.class,String.class);//获取指定的构造器
User user1 = (User)declaredConstructor.newInstance();
User user2 = (User)constructor.newInstance(1,"1");//传递参数
System.out.println(user1);
System.out.println(user2);
通过反射调用指定的方法
- 获取类的全名
Class c1= User.class;
System.out.println(c1.getName());//获取类的全名
- 获取类的全部方法
Method[] methods = c1.getMethods();//获取类的全部方法
System.out.println("----获取类的全部方法----");
for (Method method : methods) {
System.out.println(method);
}
- 获取类的全部属性
Field[] fields = c1.getDeclaredFields();//获取类的全部属性
System.out.println("----获取类的全部属性----");
for (Field field : fields) {
System.out.println(field);
}
- 获取类属性的修饰符列表
Field[] fields = c1.getDeclaredFields();//获取类的全部属性
System.out.println("----获取类的全部属性----");
for (Field field : fields) {
int modifiers = field.getModifiers();//返回的修饰符是一个数组,每一个数字是一个修饰符的代号
//可以将代号转换为字符串-得到属性的修饰符
String modifierStr = Modifier.toString(modifiers);
//获取属性的类型
String simpleName = field.getType().getSimpleName();
System.out.println(modifierStr + " " + simpleName);
}
通过反射机制反编译一个类的属性
Class c1= User.class;
//创建对象
User user = (User)c1.newInstance();
//获取指定的类属性
Field name = c1.getField("name");
//给name属性复制
name.set(user,"1");
System.out.println(name.get(user));
对私有属性进行访问的时候,需要打破封装,这里使用setAccessible,设置参数为true
Field id = c1.getDeclaredField("id");
id.setAccessible(true);
id.set(user,1);
System.out.println(id.get(user));
完整的访问代码
package pojo;
import java.lang.reflect.Field;
public class Demo04 {
public static void main(String[] args) throws Exception {
Class c1= User.class;
//创建对象
User user = (User)c1.newInstance();
//获取指定的类属性
Field name = c1.getField("name");
//给name属性复制
name.set(user,"1");
System.out.println(name.get(user));
Field id = c1.getDeclaredField("id");
id.setAccessible(true);
id.set(user,1);
System.out.println(id.get(user));
System.out.println(user);
}
}
name.set(user,"1");
System.out.println(name.get(user));
Field id = c1.getDeclaredField("id");
id.setAccessible(true);
id.set(user,1);
System.out.println(id.get(user));
System.out.println(user);
}
}