A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© zeus00456 中级黑马   /  2014-8-11 10:11  /  1473 人查看  /  13 人回复  /   3 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 zeus00456 于 2014-8-11 10:13 编辑

看着张孝祥老师的视频,结合着之前其他老师的讲解,突然感觉对于反射好像明白些了。
于是我发个帖子说说自己的理解,希望能帮到一些比我还迷糊的童鞋,更希望与同样有自己理解的童鞋交流心得(反射机制貌似是框架需要用到的知识)。

这是从程序员的角度向代码看
如果每一个类都是一个公司的部门,里面的方法(或者将这个概念放大为成员也没有问题)是一个职务(在这个职务上的人应具有对应该职务的功能);
那么每个类的对象就是一个分部(功能一样,目标不同),里面的方法就是部员(用来实现某种功能);
反射机制就是公司的大老板跳过一级一级向下传递命令的过程,直接抽调哪个部门哪个职务的人去做事,
老板会先明确他想干什么(程序员要实现的需求,程序是程序员写的,操作是程序员指定的,所以程序员是老板)
然后明确这个需求应该交给哪个部门中干什么职务的人去干(挑选类,反射出它的成员)
最后明确具体交给哪个分部的行使这项职务的人,并明确具体的要求(传入对象和方法所需的参数)

这是从代码的角度向代码看
如果每一个类都是一个公司的部门,里面的方法是一个职务(在这个职务上的人应具有对应该职务的功能);
那么每个类的对象就是一个分部(功能一样,目标不同),里面的方法就是部员(用来实现某种功能);
反射机制就是公司的一个部门借调另个部门某个职务的人去做事,
"一个部门"会先明确它需要让人干什么(实现反射功能的语句终究是写在类中的,所以在反射时实际上是一个类中使用另一个类中的东西)
然后明确这个需求应该交给哪个部门中干什么职务的人去干(挑选类,反射出它的成员)
最后明确具体交给哪个分部的行使这项职务的人,并明确具体的要求(传入对象和方法所需的参数)

关于类借调类的解释
区别于一个类通过另一个类的对象来实现某种功能("通过另一类的对象调用"就是非反射的我们之前学习的常规调用方式,比如new String("asd").hashCode())
这种常规的方式是两个部门之间业务的正常交流,一个部门的部员需要[另一个部门的部员行使了他的职务后的结果]作为自己行使职务的依据。
int xx/*一个部门的部员*/ = new String("asd").hashCode()/*另一个部门的部员行使了自己的职务*/
这种方式的交流是很柔和的:一个部员来到另一个部门,找到这部门中的人:"哥,知道XXX不,您帮我查查"(先找对象)
而反射中的类调用类更像是上级部门的人来要求下级部门的人,它只考虑自己的需求
这也可以看做是部员与另一个部的部员的业务交流
但是这种方式的交流很狂暴:上级部员踹开了下级部门的门:"你们这,干XX工作的有活着的吗,站出来!"(先找功能)
下级部门给出回应:某职位是干这个的。然后上级部员会指定一个分部的对应职务的人,告诉他具体要求,指派它去做事。

评分

参与人数 1技术分 +1 收起 理由
枫儿 + 1 赞一个!

查看全部评分

13 个回复

倒序浏览
突然发现自己前天的帖子到现在居然没有人多少人回复过,沉得真快,自挽尊术!
回复 使用道具 举报
zeus00456 发表于 2014-8-13 12:59
突然发现自己前天的帖子到现在居然没有人多少人回复过,沉得真快,自挽尊术! ...

说的很形象,看来你对反射的感念认识很清晰啊?我有点不理解通过反射程序对外的接口来给程序添加功能这个应用(应该是主要应用)这个不太清楚。通过一个配置文件(.txt文档可行不?)记录类名,通过Reflect = (Reflect )clazz.newInstance()的方式反射出程序员想要添加的类,仅仅通过这一句话就能够反射出要添加类中的方法实现吗?是不是需要提前定义一个模版才能反射呢?我一直搞不明白
回复 使用道具 举报
贾浩田 发表于 2014-8-17 12:25
说的很形象,看来你对反射的感念认识很清晰啊?我有点不理解通过反射程序对外的接口来给程序添加功能这个 ...

你说的那个应该是Properties配置文件的应用吧。

仅仅靠你说的那一句话当然是不行的。而是有一套完整的流程。
让我们来捋一捋思路吧:
首先明确一点,我们希望通过反射来得到一个类的对象(添加的功能最终还是靠拥有这些方法的对象来实现的),但是我们不知道这是哪个类的对象(知道了不就不用从文件中获得了嘛)对吧。这是我们最根本的需求。
其次我们需要一个实例,但是不知道是哪个类的实例,那好吧,我们应该先获取这个对象对应的类的字节码对象(否则不就直接new了嘛,还用什么反射)。不知道具体是哪个类,这是一个大问题,我们没有对象,也不知道是那个类,这样一来,在得到类的字节码对象的三种方式中只有forName才有可能对我们有帮助。
这是我们选取的直接手段,这个手段需要一个条件,那就是获知类的名字。顺带一提,forName和类名.class两种获取字节码对象的方法最大的不同就是前者用的是一个字符串,而后者用的是一个类(你不能认为是“一个代表类名的字符串”.class;这和类名.class是有本质区别的)这就造成了后者的局限性。
forName的方式需要我们准备一个字符串,这个字符串代表了一个类。就算是代表了一个类,我们需要的也不过是一个字符串,java中非常不怕操作字符串。因为我们不知道需要什么类,所以我们本身不知道这个字符串的内容,但是,这终归是有人知道的,这些人写了配置文件,配置文件中记录的信息中包含了我们需要的字符串。

刚刚是从需求向下的分析,我们这回正着从代码实现的角度分析一回:
1 有一个配置文件,它通常是.properties文件(txt也行,但是外行),里面记录了代表了我们需要的类的字符串。这些信息是通过键值对的形式存放的
2 我们需要一个文件读取流来关联文件,我们需要Properties来载入流中的文件,我们应该获取到文件中的键值对信息并找到我们需要的加载类的描述字符串
3 通过字符串我们知道了我们要加载的类,(终于知道我们要干什么了)于是我们使用Class.forName(字符串)的方式得到所需的类的字节码对象
4 通过字节码对象获取对象(newInstance或者getConstructor任君选择),通过对象实现我们需要的功能
(你看,你说的那一句话其实是我们的最后一步)

就这样吧,不知道我说的是不是你想交流的,也不知道我说明白了没
回复 使用道具 举报
zeus00456 发表于 2014-8-18 14:55
你说的那个应该是Properties配置文件的应用吧。

仅仅靠你说的那一句话当然是不行的。而是有一套完整的流 ...

说的很清楚,获取到了.class文件就可以解刨类了(获取构造函数,方法和字段),这个我明白。但是就是为什通过么newInstance(“字符串”)就可以获取到对应的.class字节码文件呢? 它是去哪里找这个.class文件啊?反射的初衷不是为了用户添加功能吗?用户应该只添加配置文件就可以了啊(用户哪里懂.class文件啊)?
回复 使用道具 举报
赞一个{:3_47:}
回复 使用道具 举报
很不错,学习了。大家都来看看。
回复 使用道具 举报
gmz158 中级黑马 2014-8-18 20:46:30
8#
zeus00456 发表于 2014-8-13 12:59
突然发现自己前天的帖子到现在居然没有人多少人回复过,沉得真快,自挽尊术! ...

路过            
回复 使用道具 举报
本帖最后由 zeus00456 于 2014-8-19 11:32 编辑
贾浩田 发表于 2014-8-18 15:39
说的很清楚,获取到了.class文件就可以解刨类了(获取构造函数,方法和字段),这个我明白。但是就是为什 ...

首先,我说用newInstance就能获取字节码了吗?那是用字节码获取对象的功能
其次,.classs指的不是文件,是字节码对象,这是两个完全不同的概念,请注意区分,来源自然是通过配置文件读取配置信息,得到要加载的类,通过反射得到其字节码对象
其三,反射的初衷(常规用处)是给我们已经编写好的工程添加功能,它也是搭建框架的必备技术
其四,没错,用户只添加配饰文件,但是跟你有什么关系,你不是用户,你应该干所有的活,甚至用户的配置文件怎么配置都是你告诉用户的。你要亲自定义配置文件的格式内容,你要编写对配置文件的读取和信息提取操作,你要通过提取的信息得到对应的字节码文件,你要用字节码文件创建对象,使用方法……这些跟用户只会写配置文件有什么关系,就是因为他们只会写配置文件,所以我们(这些未来的)程序员才会这么累。
最后一个问题我不知道你想问什么,不过这问题真是萌了我一脸血
回复 使用道具 举报
zeus00456 发表于 2014-8-19 11:29
首先,我说用newInstance就能获取字节码了吗?那是用字节码获取对象的功能
其次,.classs指的不是文件,是 ...

呵呵。。可能我不适合学编程吧
回复 使用道具 举报
本帖最后由 zeus00456 于 2014-8-19 22:46 编辑
贾浩田 发表于 2014-8-19 16:47
呵呵。。可能我不适合学编程吧

我不擅长与人交流,看不懂你这话是在自嘲,还是在暗讽我表达不清楚(呵呵两个字确实是对很多种感情有效表达方式)。我上面的回复若有让你不爽/郁闷/困惑的地方,贫道向你道歉。
但是!
这就不适合学编程了?

我自学时分不清什么是构造方法,什么是成员方法,这算什么?
一句   "Person p = new Person(){};是多态形式“ 想了整整一个下午才想明白,这算什么?
一条”递归适用于解决树状结构问题“的小规律,在有老师的条件下两天才勉强理解,这算什么?
我想了几天的正则问题,论坛里路过的大神”稍微试了一下(人家原话)“就ko了,这个打击啊,但是又能怎样
今天下午,我自己编的交通灯系统模拟在完善时遇到了问题,调了3个小时毫无进展,明天说不得只能麻烦老师了,这又算什么??
=====这条分割线叫做”没有程序员学不会的技术,哪怕是未来的程序员“=====

反射,其实(不考虑高阶应用)很简单。
你说集合难不?一个存一个取!
你说IO复杂不?一个读一个写!
你说多线程乱不?怎么开怎么维护!
你说GUI麻烦不?构造组件、修饰组件、摆放组件、监听组件、处理监听结果!

反射?只有两条,怎么获取字节码;有了字节码后用来干什么!
你卡在了配置文件上,这是”怎么获取字节码“的其中一种方式
回复 使用道具 举报
hsy 中级黑马 2014-8-20 10:17:19
12#
Person p = new Person(){};是多态形式,怎么解?
回复 使用道具 举报
路过,,,:)
回复 使用道具 举报
hsy 发表于 2014-8-20 10:17
Person p = new Person(){};是多态形式,怎么解?

等号的右面是匿名内部类,匿名内部类的本质是其父类的子类对象,所以右面实际上是一个Person的子类对象;
父类引用指向子类对象即为多态。

以上。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马