反射

基本概念:

把内存代码区的class(字节码文件)看作是一个类,该类包含所有当前字节码文件的内容,通过一些方式可以获取到里面的Consturctor(构造方法),Method(成员方法)和Filed(成员变量)

获取Class类对象的方式
  1. Class.forName("完整的包名.类名")
    (最常用、各种驱动加载,jdbc、Mybaits)
  2. 类.class
  3. 类对象。getClass()
构造函数的反射

Constructor构造方法类:

  1. Constructor[] getConstructors()
    --获取类内非私有化的构造方法
  2. Constructor[] getDeclaredConstructors();
    --暴力反射可以获取私有化构造函数
  3. Constructor getConstructor(Class...paramterTypes);
    --.getConstructor(int.class);
  4. Constructor[] getConstructors(Class... parameterTypes);
    --不定长参数列表。不限制参数个数,但是类型必须是Class
    -- 根据传入的类型,来确定要返回的构造函数是哪一个
    -- int class ==> Integer.class.String.class
  5. Object newInstance(Object...initargs)
    --无定长参数,参数类型是Object,传入各种类型都可以
  6. object.setAccessible(boolean access);
    --给予暴力反射获取的构造方法操作权限
    --privateConstroctor.setAccessible(true);
成员方法的反射

Method成员方法类

  1. Method[] getConstructors()
    --除了private修饰的方法,其他都可以获取,静态方法也能获取
    --继承自Object的方法也能获取
  2. Method[] getDeclaredConstructors();
    --获取类内的所有方法,但是不包括继承而来的方法
  3. Method method = Class.object.getMethod(String name,Class...paramterTypes);
    --getMethod("方法名", 参数);
    --paramterTypes不定长参数,传入的的Class对象,是重载的原理
  4. Method[] getDeclaredMethod()
    --获取private修饰的
  5. invoke(Object obj,Object...args);
    --通过反射执行类内的成员方法
  6. object.setAccessible(boolean access);
    --给予暴力反射获取的构造方法操作权限
    --privateConstroctor.setAccessible(true);
成员变量的反射

Field


反射的内存分析.png

GetClassConstructor:

package d_reflex;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;



/**
 * 通过Class类对象获取当前类的构造方法
 * Constructor 构造方法类
 * 
 * 获取Class对象的方式:
​   推荐用法,最常用用法:
​   Class.forName("完整的包名.类名");
    用来这个方法就不需要导包了
    
    获取非私有化构造函数
    获取私有化的构造函数
    获取有参数的构造函数
    获取无参数的构造函数
 */
public class GetClassConstructor {

    public static void main(String[] args) throws ClassNotFoundException, 
    NoSuchMethodException, SecurityException, InstantiationException, 
    IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        /*
         * 【加载】指定类的字节码文件,获取对应的Class对象
         * 
         */
        //获取Class对象
        Class cls = Class.forName("d_reflex.Person");//第一个异常:ClassNotFoundException
        
        // Constructor,获取Constructor方法
        /*
         * Constructor[] getConstructors();
         * 获取类内非私有化的构造方法
         */
        Constructor[] constructors = cls.getConstructors();// 返回构造方法类对象的数组
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
            // 如果上述参数不存在,会抛出异常
            // 抛出异常:java.lang.ClassNotFoundException: reflex.Person
            }   
        
        /*
         *  Constructor[] getDeclaredConstructors();
         * 暴力反射可以获取私有化构造函数
         */
        System.out.println("##########可以获取私有化构造函数");
        Constructor[] declaredConstructors = cls.getDeclaredConstructors();
        for (Constructor constructor : declaredConstructors) {
            System.out.println(constructor);
        }
        
        /**
         * 根据参数类型来获得对应的构造方法
         * Constructor[] getConstructors(Class... parameterTypes);
         * 不定长参数列表。不限制参数个数,但是类型必须是Class
         * 根据传入的类型,来确定要返回的构造函数是哪一个
         * int class ==> Integer.class.String.class
         */
        System.out.println("##########获取指定类型的构造函数");
        Constructor intConstructor = cls.getConstructor(int.class);
        Constructor stringConstructor = cls.getConstructor(String.class);
        Constructor bothConstructor = cls.getConstructor(int.class,String.class);
        System.out.println(intConstructor);
        System.out.println(stringConstructor);
        System.out.println(bothConstructor);
        /*
         * 获取无参构造
         */
        System.out.println("##########获取【无参】构造函数");
        Constructor privateConstroctor = cls.getDeclaredConstructor(null);
        System.out.println(privateConstroctor);
        
        /**
         * 此时已经获取Constructor的对象
         * 通过Constructor对象,创建一个Person对象
         * Object newInstance(Object...initargs)
         * 无定长参数,参数类型是Object,传入各种类型都可以
         */
        System.out.println("##########通过构造函数类的对象,创建类对象");
        Person p = (Person) intConstructor.newInstance(999);
        System.out.println(p.getName());
        System.out.println(p.getId());
        
        Person p1 = (Person) bothConstructor.newInstance(33,"小明");
        System.out.println(p1.getName());
        System.out.println(p1.getId());
        
        /*
         * 给予暴力反射获取的构造方法操作权限
         * object.setAccessible(boolean access);
         */
        System.out.println("##########给予暴力反射获取的构造方法操作权限");
        privateConstroctor.setAccessible(true);
        Person pp = (Person) privateConstroctor.newInstance();
        // 无参构造没有值可查看,赋值操作
        pp.setId(22);
        pp.sleep(8);
        pp.setName("大名");
        
        
        }
}
package d_reflex;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
 * 通过Class类对象获取当前类的成员变量
 * Field  成员变量类
 * @author Administrator
 *
 */
public class GetClassField {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
        // TODO Auto-generated method stub
        
        Class cls = Class.forName("d_reflex.Person");
        
        /*
         * Filed[] getFields();
         * 返回非私有化成员变量
         */
        Field[] fields = cls.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("#################");
        
        /*
         * getDeclaredFields
         * 暴力反射,获取私有化
         */
        Field[] declaredFields = cls.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        System.out.println("#################");
        
        /*
         * Filed getField(String FiledName)
         */
        Field afield = cls.getField("test");
        System.out.println(afield);
        Field bfield = cls.getField("testStatic");
        System.out.println(bfield);
        
        /*
         * 暴力反射
         */
//      Field field = cls.getField("id");
//      System.out.println(field);
        Field declaredField = cls.getDeclaredField("id");
        System.out.println(declaredField);
        
        /*
         * set(Object obj,Object value);
         * 第一个参数:要操作的当前成员变量对象
         * 第二个参数:赋予的数据
         */
        System.out.println("########################赋值操作");
        Person p = (Person) cls.getConstructor(int.class,String.class).newInstance(1,"类对象");
        afield.set(p, 999);
        System.out.println(p.getId());
        System.out.println(p.getName());
        System.out.println(p.test);
        
        //赋予私有化成员变量权限
        declaredField.setAccessible(true);
        declaredField.set(p, 789);
        System.out.println(p.getId());
        
    }

}
package d_reflex;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 通过Class对象获取类内的成员方法
 * Method成员方法类
 * @author Administrator
 *
 */
public class GetClassMethod {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
        // Class对象
        Class cls = Class.forName("d_reflex.Person");
        /*
         * Method[] getMethods();
         * 除了private修饰的方法,其他都可以获取,静态方法也能获取
         * 继承自Object的方法也能获取
         */
        Method[] methods = cls.getMethods();
        for (Method method : methods) {
//          System.out.println(method);
        }
        System.out.println(methods.length);
        /*
         * Method[] getDeclaredMethods();
         * 获取类内的所有方法,但是不包括继承而来的方法
         */
        System.out.println("#####################暴力反射");
        Method[] declaredMethods = cls.getDeclaredMethods();
        for (Method method : declaredMethods) {
//          System.out.println(method); 
        }
        System.out.println(declaredMethods.length);
        /*
         * 获取指定方法
         * Method method = Class.object.getMethod(String name,Class...paramterTypes);
         * getMethod("方法名", 参数);
         * paramterTypes不定长参数,传入的的Class对象,是重载的原理
         */
        Method method1 = cls.getMethod("game", null);
        System.out.println("method1:"+method1);
        
        Method method2 = cls.getMethod("game", String.class);
        System.out.println("method2:"+method2);
        
        /*
         *  获取私有的
         *  getDeclaredMethod()
         *  获取private修饰的
         */
        Method privateMethod = cls.getDeclaredMethod("testPrivate", null);
        System.out.println(privateMethod);
        
        /*
         * 通过反射执行类内的成员方法
         * invoke(Object obj,Object...args);
         * Object obj:调用该方法的类对象
         * Object... args:调用该方法需要的参数
         */
        method2.invoke(cls.getConstructor(int.class,String.class).newInstance(1,"小明"),"方法了里ganme");
        privateMethod.setAccessible(true);
        privateMethod.invoke(cls.getConstructor(int.class,String.class).newInstance(111,"成员"),null);
        
        /*
         * 调用静态方法
         */
    }

}

package d_reflex;
/**
 * 反射:
 *      当一个Java文件编译之后生成的.class文件(字节码文件),当这个字节码文件加载到内存,会在内存的【代码区】运行。
 *      这个字节码文件,包含了所有的当前对应类的内容。
 *      Java的反射机制就是根据字节码文件,创建一个Class类对象,通过Class类对象获取在字节码文件中的内容
 * 
 * 【Class对象】包含该字节码文件的所有成员变量(Field),成员方法(Method),构造方法(Constructor)
 * 
 *
 */
public class GetClassObject {

    public static void main(String[] args) throws ClassNotFoundException {

        // 获取Class对象
        /*
         * 第一种方法:Class.forname("完整的包名.类名");
         * 最常用
         * JDBC MyBaits
         */
        Class cls1 = Class.forName("d_reflex.Person");
        System.out.println(cls1);
        
        /*
         * 第二种:类名.class
         */
        Class cls2 = Person.class;
        System.out.println(cls2);
        
        /*
         * 第三种:通过当前类的对象获取Class类对象
         * getClass();
         */
        Class cls3 = new Person(1,"夏明").getClass();
        System.out.println(cls3);
        
        /*
         * 三个是否相等:同一个类的Class对象是一样的
         */
        System.out.println(cls1==cls2);
        System.out.println(cls1==cls3);
        System.out.println(cls1==cls3);
    }

}
              
package d_reflex;


public class Person {

    private int id;
    private String name;
    
    public int test;
    public static int testStatic = 10;
    
    private Person() {
        super();
    }
    public Person(int id){
        super();
        this.id = id;
    }

    public Person(String name) {
        super();
        this.name = name;
        
    }
    
    public Person(int id, String name) {
        super();
        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;
    }

    public int getTest() {
        return test;
    }

    public void setTest(int test) {
        this.test = test;
    }

    public static int getTestStatic() {
        return testStatic;
    }

    public static void setTestStatic(int testStatic) {
        Person.testStatic = testStatic;
    }
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", test=" + test + "]";
    }
    
    
    public void sleep(int num){
        System.out.println(name+"每天睡"+num+"个小时");
    }
    
    public void game(){
        System.out.println("ganme()方法执行");
    }
    
    public void game(String gname){
        System.out.println(this.name+"在玩"+gname);
    }
    private void testPrivate(){
        System.out.println("类内私有化方法");
    }
    
    public static void drink(){
        System.out.println("喝咖啡");
    }
}

你可能感兴趣的:(反射)