黑马程序员技术交流社区
标题: 反射怎么理解啊? [打印本页]
作者: 黑马-李勇 时间: 2012-7-29 15:07
标题: 反射怎么理解啊?
看得很晕,有什么好的方法吗?
作者: 刘同超 时间: 2012-7-29 15:16
对象1生对象2。对象2生对象3。 ……
最后根据对象N找到对象1。这是我的理解。
归结起来,就是找到对象的祖宗。。
作者: 田向向 时间: 2012-7-29 15:18
http://search.itheima.com/
里面很多,搜一下,看看有没有好理解的
作者: 金_鑫 时间: 2012-7-29 15:23
本帖最后由 金_鑫 于 2012-7-29 20:08 编辑
下面是我的理解,看完视频之后的。
什么是反射?
根据类的信息来加载这个类,然后构造这个对象,然后再调用这个类中的属性和方法。(这句话是老师说的)
我个人理解就是,反射就是让你可以随便调用你没有实例化的东西,因为类在实例化之后就固定了,而反射就打破了这种固定模式,即使你的类没有被实例化加载到内存中,你一样可以在你要使用的时候找到它。
张孝祥说:“反射就是把Java类中的各种成分映射成相应的java类”,其细节方面就是你通过自己编写代码来将类加载到java虚拟机中,也有人称“反射”为“类的自解析”。
通过反射可以让程序变得更加灵活。
反射的应用?
在.net中连接数据库时为了让程序可以灵活的连接不通的数据库,操作不同的数据库我们使用了抽象工厂+反射+配置文件来实现。
这意味着反射可以用在对“松耦合”要求很高的场合。
还有一个很常见的例子,就是无论你用微软的“死丢丢”也就是vs了,还是java的IDE——eclipse,你编写好一个类之后你调用时,你只需将类实例化,然后实例化对象后面点一下就能出来看访问的属性和方法的列表,这个也是通过反射来实现的。
我冒昧的猜测一下其中的原理,首先你写好一个类之后,编译器一边都会直接进行检查的,也就是进行编译,如果存在编译时期错误就会提示。当你实例化这个类的时候它会进行编译,但这里不是执行,不会加载到内存中。这时你再使用你已经实例化好的类时,它会根据你你提供的类的信息,也就是你类的类型,通过反射找到里面的方法和属性,然后生成列表实现出来。(这段文字还待我探讨,大家踊跃拍砖)
反射的实现?
java中主要是通过四种方式来进行class的加载的:
1.classLoader
2.类名.class.
3.对象名.getClass()
4.Class.forName();
我个人觉得1、4是比较常用的,因为这两个可以通过类的信息找到类,进而将类加载的JVM中。你只需传递给他们字符串就ok。
下面是两个小练习可以练习一下:
1. classLoader
[java] view plaincopyprint?import java.lang.reflect.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
Class c1;
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
try {
//加载student类
c1 = classLoader.loadClass("demo1.Student");
System.out.println(c1);
//获得加载类的所有方法
Field[] fields = c1.getFields();
//遍历输出
for (int i = 0; i < fields.length; i++) {
System.out.println(fields.getName());
System.out.println(fields.getType());
System.out.println(fields.getModifiers());
}
Field stuName = c1.getField("name");
//获得c1中的方法
Class[] parameterTypes = {};
Method method = c1.getMethod("say", parameterTypes);
//实例化c1对象
Object obj = c1.newInstance();
//通过实例化后的对象调用c1中方法
method.invoke(obj,null);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Student {
public String name;
public int age;
protected String nicai;
private int hh;
public void say() {
System.out.println("I‘m student");
}
}
import java.lang.reflect.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
Class c1;
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
try {
//加载student类
c1 = classLoader.loadClass("demo1.Student");
System.out.println(c1);
//获得加载类的所有方法
Field[] fields = c1.getFields();
//遍历输出
for (int i = 0; i < fields.length; i++) {
System.out.println(fields.getName());
System.out.println(fields.getType());
System.out.println(fields.getModifiers());
}
Field stuName = c1.getField("name");
//获得c1中的方法
Class[] parameterTypes = {};
Method method = c1.getMethod("say", parameterTypes);
//实例化c1对象
Object obj = c1.newInstance();
//通过实例化后的对象调用c1中方法
method.invoke(obj,null);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Student {
public String name;
public int age;
protected String nicai;
private int hh;
public void say() {
System.out.println("I‘m student");
}
}
2. forName方式
只需要把上面的
c1 = classLoader.loadClass("demo1.Student");
改成c1 = Class.forName("demo1.Student");即可。
通过这两段代码可以看出使用反射,我只需要知道我要调用的类的名字,就可以加载并使用它,并且这样可以更加灵活。你可以把字符串”demo1.Student”这个信息放到一个文件中,或者是放到数据库中,这样程序就不会那么死板了。
来自CSDN
作者: 金龙 时间: 2012-7-29 16:25
我就简单说一下反射的好处以及应用场景吧,或许不太准确,但我觉得有助于理解。
很多时候,当我们写一个程序的时候,类与类之间是相互调用的,有可能我的测试类已经写好了,但是被调用的类还没有写好,或者被调用的类也是需要被改动的,可是如果因为每次的改动而去修改源代码是不现实的,毕竟,一个项目弄好之后,我们提供出去的是class文件,那么,这时候,我们只需要把需要改动的内容写到配置文件中去,以后如果需要再增加什么新的内容时,只改动配置文件就可以了,我们可以读取配置文件中的信息,再通过反射使用次信息所属类的属性以及方法,应该是属于,提高了代码的拓展性和可维护性吧
作者: 肖琦 时间: 2012-7-29 16:27
反射的个人理解:
为什么要用反射?学的时候我是抱着这种心态的,后来也慢慢有所领悟。在我们写程序中,可能一段代码就写死执行的就是一个结果,如果用反射的话,我们代码不变,改变加载项,运行结果就大不同,这样我们执行改变配置文件就行了。举个很简单的例子(伪代码):
class A{
public void show(){}//功能一:show
}
class Test{
public static void main(String[] args){
new A().show();
}
}
Test执行过程中只能看到功能一的结果。但如果客户要求一变,我们又要写个类改变方案。
如果用反射的话
class B{
public void run();
}
class Test{
public static void main(String[] args){
Class clazz = class.forName(args[0]);//得到类的字节码
clazz.getMethod(args[1]).invoke(clazz.newInstance()) ;//得到方法,并指定实例掉用
}
}
此时我们只需要在程序加载前 给main方法的String[] 配好参数,指定是哪个类,哪个方法,就可以得到想要的,要改变功能时,只需要改变配置文件就行。这样的话,我们整篇代码不需要定那个具体的类,方法,属性,只需要改配置就有不同的效果,这样用起来就很方便(以上为伪代码,没有经测试)。
还有就是搞清楚反射的几个常用的类Class,Constructor,Feild,Method吧.这个查API.
我也就是这么理解的,后续再深入学习的话时可能还有不同的体会。
可能大部分人开始学这个知识点时有点困惑吧,熬过去,挺下去,照着视频敲个几遍代码,边敲边想,慢慢就好了,自己动手比神马都强
作者: 徐帅 时间: 2012-7-29 17:42
本帖最后由 徐帅 于 2012-7-29 17:44 编辑
想要深刻理解反射,当然必须理解反射的基石Class类:
Java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class
1. Class类的各个实例对象
对应各个类在内存中的字节码,例如Person类的字节码等
2. 一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类
的字节码,不同的里的字节码是不同的,所以它们在内存中的内容是不同的,这一
个个空间可以分别用一个个的对象来表示,这些对象显然具有相同的类型,这个类型就是Class类型
反射:
就是把java类中的各种成分映射成相应的java类。
通过Class类提供的一系列方法来活得其中的变量,方法,修饰符,包等信息,他们是
Filed,Method,Constructor,Package等,
只是通过函数名和参数类型的不同来区别,一个java类中会有很多种
方法,只要传入函数名,和参数类型,就能够明确所要获取的方法,
反射的作用--> 实现框架功能,
就像房子与门的关系,房子是框架,将门窗插入框架中,房子就可以使用了。
当然房子是在早期就盖好的,我们为了能够在房子框架的基础上使用它,只要调用用户的
提供的一个个模块,比如客厅,厨房,卧室,把他们当做一个个类,他们有各种不同的功能
与方法,是我们来定义的,就像装修一样,每个人装修都会有不同的风格,但是厨房还是做饭的
卧室还是休息的,但房子的框架是固定的,可以通过方法来调用这些功能,就像java中通过一些
方法来获取方法,变量的字节码一样,类是我们后期定义的,通过框架我们都可以使用它们。
对于反射的学习,
个人觉得是把视频多看两遍,但是一定要记笔记,虽然张老师没有给我们总结的
很详细,但是他说的话都很深刻,而且很多重点,所以及时记录下来,多思考,把概念弄清楚了。我想
学习起来就容易多了,因为之后就是方法的使用,java学习,就是在学习一种思想,当然在理解的过程
中不断实践。敲代码分析,会更加深入的理解。
以上只是个人的理解,希望对楼主有帮助。有不对的地方,还请指正
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |