MyException - 我的异常网
当前位置:我的异常网» 综合 » java反射小结

java反射小结

www.MyException.Cn  网友分享于:2013-11-10  浏览:1次
java反射总结

关于java反射之前也用到过,去了解一下发现网上也有很多写的很好的博客和例子,觉得看他们的就行了,没必要自己再写。但过一段时间以后,再用反射的时候发现好多都忘了,记不得了,还得重新去看,这才决定自己再用自己的理解总结一下,以方便自己记忆。

1、理论介绍:

java是先编译在解释的语言。java代码的运行过程是:java代码经过编译器变为字节码,即*.class的文件。字节码加载到虚拟机中变成机器码,机器码被计算机识别运行。如下图,这事我根据自己的理解画的一个简易图:


正常情况下java代码是先编译成*.class文件后再加载到虚拟机中运行的,也就是说虚拟机识别的是*.class文件格式的字节码。所以一般代码都是写好后需要经编译器编译然后向虚拟机中加载运行。但有的时候我们想在运行中即时使用一个新的类,而运行时编译的过程已经过去,怎么办,我们缺少了这个新类的字节码。这就需要用到反射,通过反射来随时动态生成一个类的.class文件,来弥补未编译的不足。通过反射来生成的字节码和编译器生成的一样可以被虚拟机认识。对虚拟机来说,他们是一样的。于是虚拟机就可以加载这个新的类的字节码继续往下走程序。

所以,java反射可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods

要注意的是此Class非定义class类的小写class.Class类是对java各个类的抽象.类一般都是有对象的,那Class类的对象具体是什么呢?Class类的具体对象是各个类在内存中的字节码.每一个类被类加载器加载到内存中都会占据一定的空间,而这个空间里的内容就是字节码,不同的字节码类是不同的,而这些空间都可以用对象来表示.也就是Class上类的对象例如: Class  clsDate=Date.class   其中clsDate就是表示Date类在内存中的字节码.clsDate的类型是Class类型.上面是一种获取字

2、具体应用1-----操作对象

针对具体到代码的话,首先就是对Class对象的获得,Class对象的获得有4种方式:如下图:

以上是自己画的简易图,其中我们最常用的就是第四种Class.forName("com.***")的方式。

得到Class对象只是第一步,紧接着就是根据Class对象获取该类的对象。即Object o = c.newInstance();的方式。从应用角度来说,只要这样做就可以拿到一个类的对象了

说到对象,下面顺便说一下,生成类对象的四种方式,如下图:


其中第二种方式就是运用反射的手段来创建一个对象,这种方式里提到了两点,一就是调用Class对象的newInstance()方法。二就是调用Constructor 对象的newInstance()方法。举个例子如下:


//可以反射创建出含参初始化对象 
Public class ConstructorTest{
    publicstaticvoidmain(String[] args) {
       try {
           //获得指定字符串类对象
           Classcla=Class.forName("reflect.Tests");
           //设置Class对象数组,用于指定构造方法类型
           Class[]cl=new Class[]{int.class,int.class};
           //获得Constructor构造器对象。并指定构造方法类型
           Constructorcon=cla.getConstructor(cl);
           //给传入参数赋初值
           Object[]x={new Integer(33),newInteger(67)};
           //得到实例
           Objectobj=con.newInstance(x);
       } catch(Exception e) {
           e.printStackTrace();
       }
    }
}
class Tests{
 
    publicTests(int x,int y){
 
       System.out.println(x+"    "+y);
 
    }
 
}
运行的结果是” 33    67”。说明我们已经生成了Tests这个类的一个对象。

构造方法一旦被调用就会产生一个对象,所以可以看出来,利用Constructor的对象来得到的实例可以产生一个有初始值的对象,而利用Class对象来创建出来的对象无法自定义初始值。

3、具体应用2------操作属性

此外反射还有一个用处就是改变对象数据字段的值。reflection 可以从正在运行的程序中根据名称找到对象的字段并改变它,下面的例子可以说明这一点

import java.lang.reflect.*;  
 
public class Field2 { 
   public double d;  
 
   public static void main(String args[]) { 
      try { 
           Class cls = Class.forName("Field2"); 
           Field fld = cls.getField("d"); 
           Field2 f2obj = new Field2(); 
           System.out.println("d = " + f2obj.d); 
           fld.setDouble(f2obj, 12.34); 
           System.out.println("d = " + f2obj.d); 
      } 
      catch (Throwable e) { 
           System.err.println(e); 
      } 
   } 
} 
然后就可以发现字段值被改变了。但一般来说,类里面的实体都是私有的private,给外界提供一个接口setter,getter方法。我们需要知道如何使用反射操作类里面的方法

4、具体应用3------操作方法

举例如下:

//反射出某类的方法,并调用方法,输入参数(比如用于属性的设定)
publicclassMethodTest {
    publicstaticvoidmain(String[] args) {
       try {
           //获得窗体类的Class对象
           Classcla=Class.forName("javax.swing.JFrame");
           //生成窗体类的实例
           Objectobj=cla.newInstance();
       //获得窗体类的setSize方法对象,并指定该方法参数类型为int,int
           MethodmethodSize=cla.getMethod("setSize",newClass[]{int.class,int.class});
           /*
            * 执行setSize()方法,并传入一个Object[]数组对象,
            * 作为该方法参数,等同于  窗体对象.setSize(300,300);
            */
           methodSize.invoke(obj,new Object[]{newInteger(300),new Integer(300)});
       //获得窗体类的setSize方法对象,并指定该方法参数类型为boolean
 
      MethodmethodVisible=cla.getMethod("setVisible",new Class[]{boolean.class});
           /*
            * 执行setVisible()方法,并传入一个Object[]数组对象,              *作为该方法参数。等同于  窗体对象.setVisible(true)
            */
 
           methodVisible.invoke(obj,new Object[]{newBoolean(true)});
       } catch(Exception e) {
           e.printStackTrace();
       }
    }
}
下面再举一个简单的类似的小例子:

反射中的invoke
class hello {
    public static void main(String[] args) {
        Class<?> demo = null;
        try {
            demo = Class.forName("Reflect.Person");
        } catch (Exception e) {
            e.printStackTrace();
        }
        try{
            //调用Person类中的sayChina方法
            Method method=demo.getMethod("sayChina");
            method.invoke(demo.newInstance());
            //调用Person的sayHello方法
            method=demo.getMethod("sayHello", String.class,int.class);
            method.invoke(demo.newInstance(),"Rollen",20);
             
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  【运行结果】:
 
hello ,china
 
Rollen  20


声明:


以上就是我本人在反射使用当中经常遇到的应用,还会有一些其他的应用,只是我不是很经常遇到,就举这几个。

以上几个代码例子全部来自于网络,对该博主表示感谢。

以上文字,代码如有错误敬请指正。不甚感激。德国有句谚语,犯错使人聪明。




文章评论

十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
漫画:程序员的工作
漫画:程序员的工作
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
代码女神横空出世
代码女神横空出世
我是如何打败拖延症的
我是如何打败拖延症的
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
那些争议最大的编程观点
那些争议最大的编程观点
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
老程序员的下场
老程序员的下场
10个调试和排错的小建议
10个调试和排错的小建议
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序员和编码员之间的区别
程序员和编码员之间的区别
鲜为人知的编程真相
鲜为人知的编程真相
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
一个程序员的时间管理
一个程序员的时间管理
程序员必看的十大电影
程序员必看的十大电影
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
为什么程序员都是夜猫子
为什么程序员都是夜猫子
每天工作4小时的程序员
每天工作4小时的程序员
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
程序员的鄙视链
程序员的鄙视链
程序员都该阅读的书
程序员都该阅读的书
总结2014中国互联网十大段子
总结2014中国互联网十大段子
中美印日四国程序员比较
中美印日四国程序员比较
我的丈夫是个程序员
我的丈夫是个程序员
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
程序员应该关注的一些事儿
程序员应该关注的一些事儿
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
编程语言是女人
编程语言是女人
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
 程序员的样子
程序员的样子
如何成为一名黑客
如何成为一名黑客
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有