理解java中反射,区别Class.forName(),Class.forName().instance() ,new

先了解一下反射(这玩意着实让我理解了很久啊)博文参考(http://blog.csdn.net/cookieweb/article/details/7056277)

先了解一些基本的概念:运行时,编译时,编译型,解释型,类加载器,动态加载类 
什么是编译?将原程序翻译成计算机语言,就是二进制代码,在java中是将.java文件也就是源程序翻译成.class的字节码 
什么是编译时?将原程序翻译成计算机语言的过程中,将.java翻译为.class文件的过程 
什么是运行时?就是在启动这个程序的时候,在java中是,类加载器加载.class文件,并交给jvm处理 
什么是编译型语言?将原程序一次性全部转换为二进制代码,然后执行程序 
什么是解释型语言?转换一句,执行一句,java是既编译又解释的语言 
编译型语言和解释型语言的区别:编译型语言效率高,依赖于编译器,但是跨平台差,解释型的效率低,依赖于解释器,但跨平台强 
什么是类加载器?类加载器就是JVM中的类装载器,作用就是将编译好的.class字节码运到检查器进行安全检查的,检查通过后开始解释执行 
什么是运行时动态加载类? 
反射就是可以将一个程序(类)在运行的时候获得该程序(类)的信息的机制,也就是获得在编译期不可能获得的类的信息,因为这些信息是保存在Class对象中的,而这个Class对象是在程序运行时动态加载的 
它 就是可以在程序运行的时候动态装载类,查看类的信息,生成对象,或操作生成对象。类在运行的时候,可以得到该类的信息,并且 可以动态的修改这些信息。class对象是在运行的时候产生的,通过class对象操作类的信息是在运行时进行的,当运行 程序的时候,类加载器会加载真正需要的类,什么是真正需要的呢?就是该类真正起作用,如:有该类的对象实例,或该类调用了静态方法属性等

过程如下:

那么如何实现反射呢

得到Class对象
Class类 
       要正确使用Java反射机制就得使用java.lang.Class这个类。它是Java反射机制的起源。当一个类被加载以后,Java虚拟机就会自动产 生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。
三种方式得到Class对象: 
1.调用对象的getClass方法,返回该对象的Class对象 
2.Class.forName(“类的完整名字”);有个受查异常 //重要,可以在类不确定的情况下实例化Class,最灵活

这个方法内部默认调用Class.forName("A",true,this.getClass().getClassLoader());

true:是否实例化该类,也就是说实际上调用Class.forName(“类的完整名字”)加载类时执行初始化

this.getClass().getClassLoader()调用类加载器

 

 

 

 

可以看到static块其实是在初始化后执行的

如果调用Class.forName("A",false,this.getClass().getClassLoader());

就会发现只加载不初始化static块没有执行,什么没有输出,所以网上很多说静态块代码在类加载时执行不准确的,其实还是在初始化后执行

需要补充的是:Class.forName("完整类名").newInstance();的用法相当于直接new();
3.Class c=类名.class

---------------------------------------------------------------------------------

Class.forName()加载一个类,返回的该类的类名

newInstance()方法可以创建一个Class对象的实例,使用该方法实例化一个类时该类必须已经被加载了

new关键字实例化一个类时先加载再实例化

获取类名:(请无视我的包名啊,懒得改了啊啊啊)

 

三种方法都可以获取。这里要注意的是A中的构造方法值执行了一次,说明类A只加载了一次。

也就是说程序在运行时JVM先检查类是否已加载,如果已加载就不在加载第二次。

Class类应用:

这里介绍一个Constructor类,该类的对象可以通过Class中getConstructor获得,用于获取构造方法创建对象

上面的类A不变,修改Test类如下:

可以看到获取到了类A中有参的构造方法

获取类的结构:

这里需要主要的是只执行了静态初始化块中的内容,应为只加载了类但是没有实例化,static块是跟随类加载时执行的。

获取类的全部方法:

这里我在类A里加了个AA()方法

Test类

可以看到AA()方法和一些其他ang里面的方法(报错的线程错误无视掉好了)

 

取得类中的全部属性:用到Field类

getDeclaredFielsd()方法可以获取全部属性,getFields()只能获取公共属性

我先在类A中加入一些简单的属性

Test类

 

看到类A中的属性都打印出来了。

 

OK了,类似的还可以获取属性的值,类的父类和实现的接口·····当需要时查一下API就可以了,比较简单,这里就不一一列举了。

 

posted on 2015-10-28 17:19  pokid  阅读(11955)  评论(0编辑  收藏  举报

导航