反射

基本概念:

把内存代码区的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("喝咖啡");
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容

  • 转自https://blog.csdn.net/sinat_38259539/article/details/71...
    扎Zn了老Fe阅读 463评论 0 4
  • 课程地址:Java基础之 — 反射(非常重要) (使用的前提条件:必须先得到代表的字节码的Class,Cla...
    叨唧唧的阅读 683评论 0 2
  • (转自csdn) 反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示...
    尼尔君阅读 225评论 0 1
  • 风是一位流浪的诗人他吟哦着在夜色里穿行夜的华丽退场后那些比黑色更黑的忧伤开始粉墨登场作为一个真实的记录者我看着他们...
    简单王檬阅读 365评论 4 31