1 反射
Reflection(反射) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,也有称作“自省”。 反射非常强大,它甚至能直接操作程序的私有属性。我们前面学习都有一个概念,被private封装的资源只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。 反射就像一面镜子,它可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。
2 为什么需要反射
如果想创建对象,我们直接new User(); 不是很方便嘛,为什么要去通过反射创建对象呢?
类不是你创建的,是你同事或者直接是第三方公司,此时你要或得这个类的底层功能调用,就需要反射技术实现。有点抽象,别着急,我们做个案例,你就立马清晰。
3 反射所需要的API
3.1 获取字节码对象
Class.forName(“类的全路径”); 类名.class 对象.getClass();
3.2 常用方法
获取包名 类名 clazz.getPackage().getName()//包名 clazz.getSimpleName()//类名 clazz.getName()//完整类名
获取成员变量定义信息 getFields()//获取所有公开的成员变量,包括继承变量 getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量 getField(变量名) getDeclaredField(变量名)
获取构造方法定义信息 getConstructor(参数类型列表)//获取公开的构造方法 getConstructors()//获取所有的公开的构造方法 getDeclaredConstructors()//获取所有的构造方法,包括私有 getDeclaredConstructor(int.class,String.class)
> 获取方法定义信息
getMethods()//获取所有可见的方法,包括继承的方法 getMethod(方法名,参数类型列表) getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法 getDeclaredMethod(方法名,int.class,String.class)
反射新建实例 clazz.newInstance();//执行无参构造创建对象 clazz.newInstance(666,”海绵宝宝”);//执行含参构造创建对象 clazz.getConstructor(int.class,String.class)//获取构造方法
反射调用成员变量 clazz.getDeclaredField(变量名);//获取变量 clazz.setAccessible(true);//使私有成员允许访问 f.set(实例,值);//为指定实例的变量赋值,静态变量,第一参数给null f.get(实例);//访问指定实例变量的值,静态变量,第一参数给null
反射调用成员方法 Method m = Clazz.getDeclaredMethod(方法名,参数类型列表); m.setAccessible(true);//使私有方法允许被调用 m.invoke(实例,参数数据);//让指定实例来执行该方法
4 反射的应用
4.1 测试物料类
package cn.tedu.reflection;
public class Student {
String name;
int age;
public Student() {}
public Student(String name,int age) {
super();
this.name = name;
this.age = age;
}
public void eat(int n) {
System.out.println("饿了吃点火锅吧"+n);
}
@Override
public String toString() {
return "Student [name="+ name +",age="+ age +"]";
}
}
4.2 获取类对象
package cn.tedu.reflection;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import org.junit.Test;
public class TestReflect1 {
@Test
public void getClazz() throws Exception {
Class<?> student1 = Class.forName("cn.tedu.reflection.Student");
Class<?> student2 = Student.class;
Class<?> student3 = new Student().getClass();
System.out.println(student1);
System.out.println(student2.getName());
System.out.println(student3.getSimpleName());
System.out.println(student3.getPackage().getName());
}
}
4.3 练习 : 类获取构造方法
package cn.tedu.reflection;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import org.junit.Test;
public class TestReflect1 {
@Test
public void getConstruct() {
Class<?> clazz = Student.class;
Constructor<?>[] cs = clazz.getConstructors();
for (Constructor c : cs) {
System.out.println(c.getName());
Class[] cp = c.getParameterTypes();
System.out.println(Arrays.toString(cp));
}
}
}
4.4 练习 : 获取成员方法
package cn.tedu.reflection;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.junit.Test;
public class TestReflect1 {
@Test
public void getFunction() throws Exception {
Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
Method[] ms = clazz.getMethods();
for (Method m : ms) {
System.out.println(m.getName());
Class<?>[] pt = m.getParameterTypes();
System.out.println(Arrays.toString(pt));
}
}
}
4.5 练习 : 获取成员变量
package cn.tedu.reflection;
import java.lang.reflect.Field;
import org.junit.Test;
public class TestReflect1 {
@Test
public void getFields(){
Class<?> clazz = Student.class;
Field[] fs = clazz.getFields();
for (Field f: fs) {
System.out.println(f.getName());
System.out.println(f.getType().getName());
}
}
}
4.6 练习 : 创建对象
package cn.tedu.reflection;
import java.lang.reflect.Constructor;
import org.junit.Test;
public class TestReflect1 {
@Test
public void getObject () throws Exception {
Class<?> clazz = Student.class;
Object obj = clazz.newInstance();
System.out.println(obj);
Constructor<?> c = clazz.getConstructor(String.class,int.class);
Object obj2 = c.newInstance("海绵宝宝",3);
System.out.println(obj2);
Student s = (Student)obj2;
System.out.println(s.name);
System.out.println(s.age);
s.eat(666);
}
}
4.7 熟悉API
5 暴力反射
指可以将程序中的私有的属性或者方法通过反射技术,暴力的获取到资源。需要使用的常见方法如下:
5.1 练习 : 创建物料类
package cn.tedu.reflection;
public class Person {
private String name;
private int age;
private void save(int m,String n) {
System.out.println("save().."+m+n);
}
private void update() {
System.out.println("update()..");
}
}
5.2 创建测试类
package tedu.reflection;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestReflect2 {
@Test
public void getFields() throws Exception {
Class<?> clazz = Person.class;
Field field = clazz.getDeclaredField("name");
System.out.println(field.getType().getName());
System.out.println(field.getType());
Object obj = clazz.newInstance();
field.setAccessible(true);
field.set(obj,"派大星");
System.out.println(field.get(obj));
}
@Test
public void getFunction() throws Exception {
Class<?> clazz = Person.class;
Method method = clazz.getDeclaredMethod("save",int.class,String.class);
Object obj = clazz.newInstance();
method.setAccessible(true);
method.invoke(obj,100,"海绵宝宝");
}
}
|