Reflection(反射)非常强大,甚至能直接操作程序的私有属性。被private封装的资源只能类内部访问,外部是不行的,但这个规定被反射打破。
反射像一面镜子,它可以在运行时获取一个类的所有信息,可以获取任何定义的信息(包括成员变量,成员方法,构造器),并且可以操纵类的字段,方法,构造器等部分。
总结:类不是你创建的,是你同事或者直接是第三方公司,此刻你要或得这个类的功能调用,就得需要反射技术实现。
在后面的学习中,会学习框架,有一个框架Spring就是一个非常专业且功能强大的产品,它可以帮我们创建对象,管理对象。以后我无需手动new对象,直接从Spring提供的容器中的Beans获取即可。Beans底层其实就是一个Map<String,Object>,最终通过getBean(“user”)来获取。而这其中最核心的实现就是利用反射技术。
反射需要用到的API
第一步:获取字节码对象
- 类名.class
- 对象.getClass
- Class.forName("类的全路径");
//测试类(随意编造)
public class Student {
public String name;
public int age;
public Student() {
}
public Student(String name, int age) {
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 +
'}';
}
}
//反射获取
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
// method();
// method1();
//method2();
method3();
}
public static void method(){
Class<Student> stu = Student.class;
System.out.println(stu.getName());//全路径名
System.out.println(stu.getSimpleName());//类名
System.out.println(stu.getPackage().getName());//包名
}
public static void method1(){
//获取public修饰的成员变量
Class<Student> stu = Student.class;
Field[] fields = stu.getFields();
// System.out.println(Arrays.toString(fields));
for(Field d:fields){
System.out.println(d.getName());// 成员变量名
System.out.println(d.getType().getName());//成员变量类型
}
}
public static void method2(){
//获取构造方法
Class<Student> stu = Student.class;
Constructor<?>[] constructors = stu.getConstructors();
for (Constructor d:constructors){
System.out.println(d.getName());//构造方法名
Class[] parameterTypes = d.getParameterTypes();//获取构造方法参数类型
System.out.println(Arrays.toString(parameterTypes));
}
}
private static void method3() {
//获取普通方法
Class<Student> stu = Student.class;
Method[] methods = stu.getMethods();
//System.out.println(Arrays.toString(methods));
for (Method a:methods
) {
System.out.println(a.getName());
Class<?>[] parameterTypes = a.getParameterTypes();//成员方法名
System.out.println(Arrays.toString(parameterTypes));//获取普通方法参数类型
}
}
}
通过单元测试来测试反射创建对象!!!
package cn.tedu.test2;
import java.lang.reflect.Constructor;
/*
前提通过反射得知对面有参构造的参数类型!!!
才能传入参数的字节码文件!!!
才能进行有参构造!!!*/
public class Test1 {
public static void main(String[] args) throws Exception {
Class<Student> stu = Student.class;//获取字节码对象
Student student = stu.newInstance();//触发无参构造
System.out.println(student);
Constructor<Student> constructor =
stu.getConstructor(String.class,int.class);//指定构造方法,传入参数字节码文件
Student student1 = constructor.newInstance("liwenbin",13);//有参构造new对象
System.out.println(student1);
student1.eat(2);
/*无参构造
Constructor<Student> constructor1 = stu.getConstructor();
Student dd = constructor1.newInstance();
System.out.println(dd);
*/
}
}
暴力反射
指的是可以将程序中私有的属性或者方法通过反射技术,暴力的获取到资源!!!!!!
//测试类
public class Student {
private String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
private void eat(int n) {
System.out.println("饿了吃"+n+"点火锅吧");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Test2 {
public static void main(String[] args) throws Exception {
method();
//method1();
}
public static void method() throws Exception {
//获取私有属性,默认属性
Class<Student> stu = Student.class;
Field[] declaredFields = stu.getDeclaredFields();
for (Field a:declaredFields){
System.out.println(a.getName());
System.out.println(a.getType().getName());
}
//获取私有属性
Field name = stu.getDeclaredField("name");
//私有属性可见
name.setAccessible(true);
Student student = stu.newInstance();
//私有属性。set
name.set(student,"liwenbin");
System.out.println(name.get(student));
}
public static void method1() throws Exception {
//查看该类所有私有方法
Class<Student> stu = Student.class;
Method[] declaredMethods = stu.getDeclaredMethods();
Student student = stu.newInstance();
for (Method a:declaredMethods){
System.out.println(a.getName());//私有方法名字
Class<?>[] parameterTypes = a.getParameterTypes();
System.out.println(Arrays.toString(parameterTypes));//私有方法参数类型
}
//获取私有eat方法
Method eat = stu.getDeclaredMethod("eat", int.class);
Student student1 = stu.newInstance();//new 对象
//想要执行私有方法,需要先设置私有可见!!!!!
eat.setAccessible(true);
//反射技术invoke(),执行目标对象obj的目标方法method
eat.invoke(student1,100);
}
}