反射学习笔记

类加载器

  • 程序使用某个类,系统会通过加载、连接、初始化三步来实现对这个类进行初始化
  • 何为加载:将class文件读入内存,并为之创建一个Class对象
  • 何为连接:
  1. 验证是否有正确内部结构,并和其他类协调一致
  2. 准备:负责为类的静态成员分配内存并设置默认初始化值
  3. 解析:将类的二进制数据中的符号引用替换为直接引用
  • 何为初始化:初始化步骤

类的初始化时机:

  • 创建实例时
  • 访问类的静态变量,或为其赋值
  • 调用静态方法
  • 使用反射创建某个类或接口的Class对象
  • 初始化某个类的子类
  • 直接使用java.exe命令来运行某个主类

三种类加载器

  • BootStrap ClassLoader根类加载器:负责java核心类加载(rt包中的核心类)
  • Extension ClassLoader扩展类加载器:负责JRE扩展目录中jar包的加载
  • System ClassLoader系统类加载器:负责在JVM启动时加载来自java命令的class文件,以及classpath所指定的jar包和类路径

反射的概念

  • 反射机制是运行状态中,对于任意类,都能调用其任意一个方法和属性,这种动态获取信息和调用对象的方法称为反射机制
  • 解剖一个类,需要先获取到每一个字节码文件对应的Class类型的对象
  • 先获取某个类的class类对象,然后通过这个Class对象去使用该文件中的成员变量、构造方法和成员方法

获取某个类的Class对象

  1. 方法1:Object类的getClass()方法
  2. 方法2:数据类型的静态成员变量class
  3. 方法3:Class.forName(""),类名称必须为带包名的类全称

开发过程优先选方法3,可通过配置文件动态加载类

获取某个类的构造方法Construor对象

Constructor[] cons = c4.getConstructors();
//获取所有公共构造方法对象
Constructor[] cons2 = c4.getDeclaredConstructors();
//获取所有构造方法对象
Constructor cons3 = c4.getConstructor();
//获取无参数构造方法对象
Constructor cons4 = c4.getConstructor(String.class, int.class);
//获取某个有参数构造方法
Constructor cons5 = c4.getDeclaredConstructor(String.class, int.class, String.class);
cons5.setAccessible(true);
//获取私有构造方法
  • 创建实例:
Object obj = cons3.newInstance();
//通过无参数构造方法对象来获取对象实例
Object obj2 = cons4.newInstance("刘耕",29);
//通过有参数构造方法对象来获取对象实例

获取某个类的成员变量Field对象

Object personLiu = cons5.newInstance("刘耕", 29, "成都");
Field address = c4.getField("address"); //获取指定名字的成员变量对象
Object obj = address.get(personLiu);
//获取某对象成员变量的值
System.out.println(obj);
address.set(personLiu, "重庆");
//通过反射方法,对某对象的成员变量进行复制
obj = address.get(personLiu);
System.out.println(obj);

结果显示:
成都
重庆

获取某个类的成员方法Method对象

Method m1 = c4.getMethod("show", null);
//通过方法名字和所需要传入的参数的class对象,来获取Method对象
m1.invoke(personLiu, null);
//通过Method对象调用该方法

Method m2 = c4.getMethod("getString", String.class,int.class);
System.out.println(m2.invoke(personLiu, "我是刘庚",28));
//通过反射调用有参数成员方法并获取返回值

结果显示:
show:name=刘耕,age=29,address=重庆;
我是刘庚---28

思考:

这个例子中的反射未使用泛型,想想如果使用泛型会有哪些不同?

通过反射运行配置文件

在java工程中设置配置文件,将需要动态加载的类名称设置在配置文件中

Properties prop = new Properties();
//通过Properties对象解析配置文件
FileReader fr = new FileReader("class.txt");
prop.load(fr);
//加载相应文件的输入流
fr.close();
String className = prop.getProperty("className");
//读取配置文件中定义的类名
Constructor consFile = Class.forName(className).getConstructor(String.class, int.class);
Object obj = consFile.newInstance("刘耕",28);
System.out.println(obj);

注意:配置文件必须放置在java工程目录下

反射应用

反射的应用十分广泛

写一个方法,将某对象中名为PropertyName属性的值进行赋值

public void setProperty(Object obj, String propertyName, Object value) throws Exception, SecurityException {
         Class objClass = obj.getClass();
         Field objField = objClass.getDeclaredField(propertyName);
         objField.setAccessible(true);
         objField.set(obj, value);
     }

动态代理

程序运行过程中生成动态代理

public class Test {
    public static void main(String[] args) {
        UserDao ud = new UserDaoImpl();
        Student st = new NewStudent();
        MyInvocationHandler udhandler = new MyInvocationHandler(ud);
        MyInvocationHandler sthandler = new MyInvocationHandler(st);
        UserDao userDaoProxy = (UserDao)Proxy.newProxyInstance(ud.getClass().getClassLoader(), ud.getClass().getInterfaces(),udhandler);
        Student studentProxy = (Student)Proxy.newProxyInstance(st.getClass().getClassLoader(), st.getClass().getInterfaces(),sthandler);
        //获得的对象是进过修饰的代理对象,将原对象的方法进行了修饰
        userDaoProxy.add();
        System.out.println("--------------------");
        studentProxy.study();
    }
}

public class MyInvocationHandler implements InvocationHandler{
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
        //指定需要代理的对象
    }
    @Override
    public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
        System.out.println("进入系统");
        Object obj = arg1.invoke(target, arg2);
        //利用反射调用需要代理的对象的方法
        System.out.println("退出系统");
        //对需要代理的对象中的方法进行修饰
        return obj;
    }
}

public interface UserDao {
    public abstract void add();
    public abstract void find();
    public abstract void update();
    public abstract void delete();
}
public class UserDaoImpl implements UserDao{

    @Override
    public void add() {

        System.out.println("增加");
    }

    @Override
    public void find() {

        System.out.println("查找");
    }

    @Override
    public void update() {

        System.out.println("修改");
    }

    @Override
    public void delete() {

        System.out.println("删除");
    }
}
public class NewStudent implements Student{

    @Override
    public void study() {
        // TODO Auto-generated method stub
        System.out.println("学习");
    }

    @Override
    public void play() {
        // TODO Auto-generated method stub
        System.out.println("玩耍");
    }
}
public interface Student {
    public abstract void study();
    public abstract void play();
}

运行结果:
进入系统
增加
退出系统


进入系统
学习
退出系统

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

推荐阅读更多精彩内容

  • 今天一早就在心姐妹成长营里跟大家分享昨日因着晓玲姐的作业点评而得来的收获。没想到带出好几个姐妹共同的受伤经历。总结...
    谭小哞Tanya阅读 174评论 0 3
  • 回到成都,他要去工作了。 晚上我们住春熙路铂泊客.拖板鞋社交旅行酒店里,这个酒店类似青年旅行社,但感觉比旅行社更多...
    渔湘菜丝阅读 210评论 0 1
  • 我的事业目标:和谐的团队,共同的使命,通过分享智慧帮助更多的企业和人们有好的幸福美满的人生。 1、在泰国静修营学习...
    蕙兰坊阅读 207评论 0 0
  • 今天是加入007的第一次作业,不知道从什么地方写起。那就来谈谈明朝的最后一个皇帝——崇祯皇帝朱由检,朱由检在即位之...
    Mike_810e阅读 172评论 0 2