关闭

java里的反射机制

标签: javaclassjvmobject语言ejb
2013人阅读 评论(0) 收藏 举报
分类:

题外话:

下个周末世界杯就开始了,对于一个地道的球迷而言,这无疑是一个期盼以久的盛大的节日,无论从生理上还是心理上我都做好了充分的准备,准备全身心的投入到这个四年一度的节日中去,祝天下球迷朋友们节日快乐,好好享受吧!

什么是反射机制

正像物理中的反射一样,就像我们站在镜子面前能看到自己的模样。但是这里的反射机制又有别于物理中的反射,这里的反射机制着重强调的是“动态的”。反射机制是指能在class(自己)运行的情况下,看到自己主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。由于设计的时候加入了这种机制使得java语言具有了一定的动态能力(所谓一定的动态能力是指:java语言并不能象python,ruby那样在程序运行时,允许改变程序结构和变量的类型,但是他可以在程序运行的时候检测自己的状态和行为,并能修改字段的值)。正是由于反射机制的存在,所以java语言又有别于“硬编码”的c,c++,同时也正是这个机制的优势,使得微软在后来模仿java语言发明了c#语言,同样c#语言也具备了这个优势。

如何实现:

java里面所有对象都继承于一个基本对象class object,这个对象不是我们通过程序手动写出来的,他是在每一个class使用的时候由jvm自动生成的。这个类提供了若干个Reflection API,我们可以调用这些Reflection API来检查class的相关方法,变量,名字,接口以及继承…………相关信息。而我们通过SUN提供的这些Reflection API来检查各种各样的class信息的过程就是反射(下面我写的这个例子就是做的这件事),象这种事,每天JVM都在做,任何一个时候都在不停的做,只要有一个class生成,被操作,jvm都会调用反射API去得到他的方法,属性,变量。罗列几个常用的API有:getName() 得到class/interface 名称;getDeclaredMethods() 得到方法;getDeclaredFields() 得到变量……。

例子(三个例子,得到字段,方法,名字)

以下是我使用反射机制的三个例子,分别是得到名字,方法,以及属性和修改属性。

例子一:

/*得到方法名字*/

Class c = null;

c = Class.forName(args[0]);

Package p;

p = c.getPackage();

if (p != null)

System.out.println("package "+p.getName()+";");

執行結果(例):

package java.util;

该例子摘自侯捷老师一书《java反射机制》“Java Reflection API 運用示例”一节,正像我们常常问的那样,我们在EJB里面写了个方法,或者引入了一个包,客户端怎么知道是哪一个包,是哪一个方法,就像上面一样,JVM其实在背后做了上面这段代码的事,然后打印了上面这个结果,也就是说JVM通过反射知道了他想知道的信息。明白了吧,JVM就是这样得到了这些信息。刚开始我学习反射的时候,有一个疑问在我脑海里困惑了很久“反射只能动态的时候看自己的方法,函数,变量,又不能象动态语言那样操作,这样做意义何在,似乎找不到一点好处”,通过这里,我明白了,其实反射不是给你看的,是给JVM看的,让他或者容器(例如EJB)知道到底该得到什么方法,什么class

例子二:

/*得到所有方法*/

package src;

 

import java.lang.reflect.*;

 

public class reflectiontest {   

 

    public static void main(String args[]) {

        try {           

 

            Class c = Class.forName("java.lang.String");//转化为class object对象,可以反射。

            Method m[] = c.getDeclaredMethods();

            System.out.println(m[0].toString());

/****查看自己的所有方法******/

            for (int i = 0; i < m.length; i++)

                System.out.println(m[i].toString());

/****************************/

 

 

/****查看自己的第一个方法****/

System.out.println(m[0].toString());

/****************************/

           }

               catch (Throwable e) {

            System.err.println(e);  

            }   

 

    }

}

由于java是完全面相对象的编程,所以在java里面string型,int型,这些常量类型也是对象化了的,我们可以把他们当作一个对象来看待和操作。通过上面的例子得到的结果是所有string的公共方法。

例子三:

/*得到属性以及修改属性,也就是我们常常使用的setget方法*/

public class Test {

public double d;

public static void main(String args[])

{

Class c = Class.forName("Test");

Field f = c.getField("d"); //指定field 名稱

Test obj = new Test();

System.out.println("d= " + (Double)f.get(obj));

f.set(obj, 12.34);

System.out.println("d= " + obj.d);

}

}

该例子摘自侯捷老师一书《java反射机制》倒数第二小节“執行期變更fields 內容”,这个方法大家用得多了吧,其实里面也包含了反射机制得原理,即使说我们通过实名把我们要操作的对象转换成class object对象Class c = Class.forName("Test");然后通过c.getField()方法(该方法就是反射制的体现) 就可以动态(这里所谓的动态就是指在程序在运行的时候)取得自己的变量,并且修改和设置。

为什么用reflection,他有什么好处:

其实JNDI就是reflection的一个具体表现。举个例:ejb里面我们放了一个类,客户端怎么知道我们要使用什么类的什么方法,我们知道用的是jndi,其实JNDI就是反射机制的一个具体表现,Class c = Class.forName("java.lang.String");双音号里面是调用的函数或者方法的名字,通过名字来找到我们要调用的方法,这就是我们说的JNDIJVM在内部实例化了一个class object,正如我们上面提到的这个class object里面有很多方法,通过这些方法就可以看到他得到的那个类的所有的公用方法,并且调用相应的方法。否则客户端也不能知道我们调用的是什么类。

同样我们常常使用getXXX()setXXX()方法也是一样的道理。

总结起来可以概括为:“动态的来选择执行的方法和变量,不是静态的写出来。”

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:82696次
    • 积分:1218
    • 等级:
    • 排名:千里之外
    • 原创:33篇
    • 转载:1篇
    • 译文:1篇
    • 评论:47条
    文章分类
    最新评论
    友情连接