反射机制
作用
反射机制是一种操作字节码文件的方法
Spring等高级框架的底层实现都是通过反射机制。
想要操作字节码文件,首先要拿到这个字节码文件,如何获取字节码文件呢?
获取字节码文件的三种方式
- Class.forName("")
参数为类的全名称
(不带后缀名)
forName("")这个方法会导致参数内的类加载,如果只想执行一个类中的静态代码块中的方法,可以直接使用Class.forName(""),因为静态代码块只在类加载的时候执行一次。
-
对象.getClass();
每一个对象都有getClass()方法,用来获取该对象所属的类 -
xx.Class
任何一个类型都有.Class属性,代表其所属类。
Field ****反射机制较为重要的内容
通过反射机制获取到一个类后,下面再来获取这个类中的属性Field
User.java
public class User {
public String name;
protected String password;
private int telphone;
String emial;
public void login(String name,String password){
}
public User() {
}
public User(String name, String password) {
this.name = name;
this.password = password;
}
}
public class Test01 {
public static void main(String[] args) throws Exception{
Class className = Class.forName("Reflect.User");
Field[] fields = className.getFields();
System.out.println(fields[0].getName());//---->name
Field[] declaredFields = className.getDeclaredFields();
for (Field field:declaredFields) {
//获取修饰符
String s1 = Modifier.toString(field.getModifiers());
System.out.print(s1+'\t');
//获取类型
Class typeClass = field.getType();
String simpleName = typeClass.getName();
System.out.print(simpleName+'\t');
//获取属性名
System.out.println(field.getName());
}
}
通过getFileds()获取属性,只能获取到public修饰的属性
通过getDeclaredFields()可以获取到所有属性
通过getDeclaredField(Object)可以获取到某一个Field属性对象,参数为该属性对应的Field对象的名字
public String name
属性名+类型+修饰符列表 表示一个Field对象,通过这个对象中的方法我们可以获取该对象里的内容
- 通过getName()获取名字name,
- 通过getType()获取类型所属的类java.lang.String,再通过String类的getSimpleName()方法获取其简类名String
- 通过getModifiers()获取访问控制权限代号1(int类型,public代号为1),再通过Modifier类的静态toString(int)方法,将代号转换为字符串,即可得到public
读写属性的值
在上面代码的情境下,获取到User类的名className 后,通过这个类名创建实例对象,
Class className = Class.forName("Reflect.User");
Object obj = className.newInstance();//这个obj就是User对象
Field field = className.getDeclearedField("name");
field.set(obj,"张三"); //设置name属性的值为张三
field.get(obj); //获取到张三
这种方式无法访问私有属性
若想访问私有属性,可以通过Field对象的setAccessible()方法打破封装
这也是反射机制一个不安全的地方
field.setAccessible(true)
Method*****反射机制最重要的内容
通过反射机制调用方法
与获得属性对比,获得方法通过getDeclaredMethod() ,参数为方法名及其参数列表类型
eg:
Class className = Class.forName("Reflect.User");
Object obj = className.newInstance();
Method login = className.getDeclaredMethod("login",String.class,String.class);
login.invoke(obj,"张三","123456");//调用(invoke)login方法
Constructor
通过反射机制获取构造方法(getDeclaredConstructor)并创建对象(newInstance)
Constructor con1 = className.getDeclaredConstructor();//获取无参构造
Constructor con2 = className.getDeclaredConstructor(String.class, String.class);//两个参数的构造方法
//调用构造方法创建对象
con1.newInstance();
con2.newInstance("李四","12312");
其他方法
- 获取类的父类:getSuperClass();
- 获取父接口:getInterfaces(); 返回一个Class[]