Java反射(reflect)

一、Java反射概述

1、Java反射是框架设计的灵魂,可以在框架的基础上进行软件开发

2、反射机制
Java反射机制是在运行状态中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法和属性

3、如何获取类的属性和方法
要想解剖一个类,必须要获取到该类的字节码文件对象,而解剖使用的就是 Class 类中的方法,所以要解剖一个类,要先获取到每一个字节码文件对应的 Class 类型的对象

4、好处

  • 可以在程序运行过程中操作这些对象
  • 可以解耦,提高程序的可扩展性

总结
反射就是把 Java 类中的各种成分 映射成 一个个的 Java 对象

二、获取 Class 对象

1、先查看一个 Class 类的 API
Java反射(reflect)_第1张图片
2、获取 Class 对象的三方式

  • 1、Class.forName("全类名"):将字节码文件加载进内存,返回Class对象,多用于配置文件,将类名定义在配置文件中;读取文件,加载类
  • 2、类名.class:通过类名的属性class获取,多用于参数的传递
  • 3、对象.getClass():getClass()方法在Object类中定义着,多用于对象的获取字节码的方式
    Java反射(reflect)_第2张图片

3、实例
Java反射(reflect)_第3张图片
新建两个测试文件 Person.java 、 Student.java

package domain;

public class Person {
    private String name;
    private int age;
    public String a;
    protected String b = "字符串b";
    String c = "c 字符串";
    private String d = "d 字符串";

    public Person(){

    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }

    public void eat(){
        System.out.println("人在吃饭");
    }

    public void eat(String food){
        System.out.println("eat..."+food);
    }
}
package domain;

public class Student {
    public void sleep(){
        System.out.println("学生睡觉!!!");
    }
}

写测试类 ReflectDemo1.java

package reflect;

import domain.Person;
import org.junit.Test;

public class ReflectDemo1 {
    @Test
    public void testClass(){
        //第一种方式获取Class对象
        Class s1 = null;//获取Person的 Class 对象,要抛异常
        try {
            s1 = Class.forName("domain.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //第二种方式获取Class对象
        Class s2 = Person.class;

        //第三种方式获取Class对象
        Person p = new Person();//这是new 产生一个 Person 对象,一个Class 对象
        Class s3 = p.getClass();

        System.out.println(s1 == s2);//true
        System.out.println(s1 == s3);//true
    }
}

总结以上三种方式获取 Class 对象

  • 一个类,只有一个Class 对象产生
  • 这三种方式获取 Class 对象,通常使用 Class.forName();

三、Class 对象的功能——Field

Field:原意:字段

1、获取成员变量们

  • Field[] getFields() :获取所有public修饰的成员变量
  • Field getField(String name) 获取指定名称的 public修饰的成员变量
  • Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
  • Field getDeclaredField(String name)
package reflect;

import org.junit.Test;

import java.lang.reflect.Field;

public class ReflectDemo2 {
    @Test
    public void test1() throws Exception {
        Class cla = Class.forName("domain.Person");//获取Class对象,将字节码文件加载进内存
        Field[] fields = cla.getFields();//获取所有public修饰的成员变量
        for (Field field : fields) {//循环输出,快捷键 iter
            System.out.println(field.getName());
        }
    }

    @Test
    public void test2() throws Exception {
        Class cla = Class.forName("domain.Person");//获取Class对象,将字节码文件加载进内存
        Field[] fields = cla.getDeclaredFields();//获取所有成员变量,不考虑修饰符
        for (Field field : fields) {//循环输出,快捷键 iter
            System.out.println(field.getName());
        }
    }
}

2、Field 的成员变量

  • void set(Object obj, Object value) 设置值
  • get(Object obj) 获取值
  • setAccessible(true)暴力反射,可以访问私有
package reflect;

import domain.Person;
import org.junit.Test;

import java.lang.reflect.Field;

public class ReflectDemo2 {
    @Test
    public void test1() throws Exception {
        Class cla = Class.forName("domain.Person");//获取Class对象,将字节码文件加载进内存
        Field[] fields = cla.getFields();//获取所有public修饰的成员变量
        for (Field field : fields) {//循环输出,快捷键 iter
            System.out.println(field.getName());
        }

        Person p = new Person();
        p.a = "a 字符串";
        Field f = p.getClass().getField("a");
        System.out.println(f.get(p)); //获得a变量的值

        Field f2 = p.getClass().getDeclaredField("d");//d私有变量
        f2.setAccessible(true); //暴力反射,访问私有变量和方法,一般不推荐,不符合oop
        System.out.println(f2.get(p));
    }

    @Test
    public void test2() throws Exception {
        Class cla = Class.forName("domain.Person");//获取Class对象,将字节码文件加载进内存
        Field[] fields = cla.getDeclaredFields();//获取所有成员变量,不考虑修饰符
        for (Field field : fields) {//循环输出,快捷键 iter
            System.out.println(field.getName());
        }
    }
}

四、Class 对象的功能——Constructor

1、获取构造方法们

  • Constructor[] getConstructors()
  • Constructor getConstructor(类... parameterTypes)
  • Constructor getDeclaredConstructor(类... parameterTypes)
  • Constructor[] getDeclaredConstructors()
package reflect;

import domain.Person;
import org.junit.Test;

import java.lang.reflect.Constructor;
import java.util.Arrays;

public class ReflectDemo3 {
    @Test
    public void Test() throws Exception{
        Class cla = Class.forName("domain.Person");
        //得到所有构造函数
        Constructor[] constructors = cla.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "\t" + Arrays.toString(constructor.getParameterTypes()));
        }

        //得到一个构造函数
        Constructor con1 = cla.getConstructor(String.class, int.class);
        //调用构造函数产生对象
        Person p1 =  (Person) con1.newInstance("Lemon", 100);
        System.out.println(p1);

        //得到一个构造函数
        Constructor con2 = cla.getConstructor(); //无参构造函数
        //调用构造函数产生对象
        //Person p2 =  (Person) con2.newInstance();
        Person p2 = (Person) cla.newInstance(); //调用无参构造函数
        System.out.println(p2);
    }
}

五、Class 对象的功能——Method

1、获取成员方法们

  • Method[] getMethods()
  • Method getMethod(String name, 类... parameterTypes)
  • Method[] getDeclaredMethods()
  • Method getDeclaredMethod(String name, 类... parameterTypes)
package reflect;

import org.junit.Test;

import java.lang.reflect.Method;

public class ReflectDemo4 {
    @Test
    public void test() throws Exception{
        Class cla = Class.forName("domain.Person");

        Method[] methods = cla.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        System.out.println("---------");
        //使用反射产生对象
        Object bean = cla.newInstance();

        //得到一个方法
        Method m1 = cla.getMethod("eat", String.class);
        //调用方法
        m1.invoke(bean, "骨头");

        Method m2 = cla.getMethod("eat");
        m2.invoke(bean);
    }
}

你可能感兴趣的:(Java)