`

Java反射入门

    博客分类:
  • java
阅读更多
Java反射入门
Java为我们提供了反射机制,反射——在生物中被这样解释:动物通过中枢神经系统对刺激的一种应答式反应,在物理中它被这样解释:声波、光波或其他电磁波遇到障碍物或别种媒质面而折回,那么它在Java中又该怎么解释呢?首先我们来看看它能做什么:
1.         在运行时判断任意一个实例的所属类。
2.         在运行时构造任意一个类的实例。
3.         在运行时获取任意类所具有的属性和方法。
4.         在运行时调用任意对象的方法。
不知道大家有没有注意到“运行时”这三个字,它能让我们的程序更加动态,更加的灵活,好了,废话少说,我们一个一个来实现上面所说的功能。
在解决以上问题之前,我们先看看java为我们提供了哪些类来实现反射:
Class:它代表一个类,JVM每加载一个类都会实例一个相应的Class对象,如何取得它我们后话再讲。
Field:它代表类的属性。
Method:它代表类的方法。
Constructor:它代表类的构造方法。
1.在运行时判断任意一个实例的所属类。
首先我们准备一个用于测试的Javabean:
package vo;
public class UserVo {
           private String name;
           public UserVo(){}
           public String getName(){
              return this.name;
           }
           public void setName(String name){
              this.name=name;
           }
}
我们将围绕这个类来进行测试。我们再写一个类名叫:TestReflection,代码如下:
package reflection;
import vo.UserVo;
public class TestReflection {
           /**
            * 打印类的信息
            */
           public void refClassInfo(Object o){
              Class c=o.getClass();
              System.out.println(c.getName());
           }
           public static void main(String[] args) {
              UserVo t=new UserVo();
              new TestReflection().refClassInfo(t);
           }
}
现执行下看看效果,是不是动态的获取了类名?接着我们来看看它的实现。
           public void refClassInfo(Object o){
              Class c=o.getClass();
              System.out.println(c.getName());
           }
主要就是这个方法了,它有一个Object型的参数,在执行它之前我们并不知道它是属于那个类的,但程序运行时我们就可以通过Class.getName()这个方法来得到。
前面我们说过Class代表一个类,我们在这个例子中,通过调用对象的getClass(),来获取此对象的Class对象,既然它代表类,那么它肯定拥有这个类的所有信息,getName()这个方法就能获得它的类名。
后面的一切操作都是以它为基础的,在java中如果要反射,我们就得现获得Class对象,这个道理很简单,如果你连哪个类都不知道,你怎么去找它的方法?呵呵。
2.在运行时构造任意一个类的实例。
           在这个例子中,假设我们知道类名,但没有这个对象,我们通过反射机制来动态的获取一个对象。
           public static Object getInstance(String className){
              try {
                  Class c=Class.forName(className);
                  return c.newInstance();
              } catch (ClassNotFoundException e) {
                  e.printStackTrace();
              } catch (InstantiationException e) {
                  e.printStackTrace();
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              }
              return null;
           }
           这个例子中,我们接触一种新的获取Class的方法,通过Class.forName(String className)这个方法,得到Class对象后,再调用它的newInstance()即可获得此类的对象。
           我们怎么调用这个方法呢?
           public static void main(String[] args) {
              UserVo t=(UserVo)TestReflection.getInstance("vo.UserVo");
           }
           上面我们确实获取了实例,但这种方法有个缺点,就是只支持无参的构造函数,如果我们要实例的类它的构造函数是有参的我们该怎么办,这里我们要用到Constructor类,还记得它吗?前面说过它代表构造方法,我们来看代码。
           public static Object constructInstance(String className){
              try {
                  Class c=Class.forName(className);
                  Class[] paramList={String.class};//参数列表
                  Constructor ctor=c.getConstructor(paramList);
                  Object[] param={"hello"};
                  return ctor.newInstance(param);
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return null;
           }
           首先我先介绍下String.class这个写法,这种方法也可以获取某类的Class对象,这里获取的String的Class对象,至此我们学习三种获取Class的方法。
1.         Object.getClass();
2.         Class.forName(className);
3.         new Object().class;
——接下来我们继续分析代码。
构造好参数列表(形参)后,我们可以通过这个这个参数列表来找一个构造方法:
Constructor ctor=c.getConstructor(paramList);
Class类的getConstructor()方法可以获取指定参数列表的构造方法类:Constructor,Constructor类同样有一个newInstance()的方法,只不过这次得传参数了,这里必须传Object的数组,但我们构造方法的参数是String型的怎么办?根据多态的特性,我们知道父类的引用可以指向子类的对象,这里我们只需在Object数组中放入String的对象就OK了。
Object[] param={"hello"};
           最后调用ctor.newInstance(param);获得该对象的实例。
           要使用本函数,className所对应的类必须有一个有参的构造方法才行,否则会抛出异常。
3.在运行时获取任意类所具有的属性和方法。
           这一节我们讨论如何动态的获取属性和方法,首先我们先讲获取属性吧。
           Class类提供我们四个方法获取某类的属性:
           Field[] getDeclaredFields() 获取所有此类自己声明的字段,包括任何访问级别。
Field getDeclaredField(String fieldName) 获取指定名字的自己申明的对象。
Field[] getFields() 获取所有(包括父类的)访问级别为public的字段。
Field getField(String fieldName) 获取指定名字访问级别为public的字段,包括父类的。
看完API后,我相信大家应该能够写出来了,我就附上一个例子吧。
           public static void showFields(Object o){
              Class c=o.getClass();
              Field[] fields=c.getDeclaredFields();
              for(Field f : fields){
                  try {
                     System.out.println("类型:"+f.getGenericType().toString()
                            +"字段名:"+f.getName()
                            +"值"+f.get(o));
                  } catch (Exception e) {
                     e.printStackTrace();
                  }
              }
}
           上面的例子有读取字段的值,但如果访问级别不够将会出异常,如要测试,请把相应的字段访问级别改为public.
           有关Field类请大家自行查询帮助文档,本文只是起个抛砖引玉的作用,很多东西还得考大家自己去帮助文档中找。
           接下来我们学习下动态获取某类的方法。在Class类中也提供了相应的方法,这组方法与获取Field的方法相似,我们来看看:
           Method getDeclaredMethod(String name, Class... parameterTypes)
           Method[] getDeclaredMethods()
           Method getMethod(String name, Class... parameterTypes)
           Method[] getMethods()
            对这些方法我就不多做介绍了,和获取Field的方法是对应的,请大家参阅JAVA API文档,我给大家一个例子吧:
               public static void showMethod(Object o){
                  Class c=o.getClass();
                  Method[] methods=c.getDeclaredMethods();
                  for(Method me : methods){
                      System.out.println(me.getName());
                   }
               }
           它可以打印出指定对象属于类中申明定义的所有方法(不包括父类的)。
4.在运行时调用任意对象的方法。
           最实用的来了,动态调用方法。通过它我们可以实现很多很智能的东西,比如Hibernate中的Session,只要调用它的save方法,把一个VO对象放进去它就能帮我们自动生成sql语句,并将其插入到数据库中,酷吧!呵呵,学完这个特性后,我们完全可以实现同样的功能。
           我们来看个例子:
         public static void invokeMethod(Object o){
            Class c=o.getClass();
            try {
Method method=c.getMethod("setName", new Class[]{String.class});
                method.invoke(o, new Object[]{"yjgoo"});
            } catch (Exception e) {
                e.printStackTrace();
            }
         }
           这个例子演示了动态的调用方法的方法,首先得到Method对象,这里使用Class对象的getMethod()方法,它有两个参数,第一个是要获取的方法名,第二个是这个方法的参数类型,这里用的是String型,这里应该没问题吧?有问题的话把代码多琢磨下,写下。
           找到Method对象后,调用它的invoke()方法,它也需要两个参数,第一个是从中调用这个方法的对象,这里写的是o,因为我们要调用o的setName方法,第二个参数是参数,也是Object的数组,这里setName方法需要的参数是String对象,就传一个String的对象就可以了。
           全文就OVER了,不知道大家都看懂了没有,呵呵,希望大家多去看看java API文档,在那里面可以详细的了解反射,通过反射可以做很多事情,本文只介绍了很小一部分。


其中主方法完整的如下:         public static void main(String[] args) {
              //动态构造UserVo对象
              UserVo uv=(UserVo)TestReflection.getInstance("vo.UserVo");
              TestReflection.refClassInfo(uv);//动态获取uv对象是哪个类的实例
              System.out.println("所有的方法:");
              TestReflection.showMethod(uv);//显示uv对象所属类自己定义的所有方法
              uv.setName("no name");
              TestReflection.showFields(uv);//显示uv对象的所有属性和值
              TestReflection.invokeMethod(uv);//动态执行方法,调用setName方法,改变name的值
              TestReflection.showFields(uv);//再显示
           }
源文件来自:http://hi.baidu.com/cxmjjyizuxbcuvd/item/146688cbda7d7c2c46d5c0d5
分享到:
评论

相关推荐

    java反射入门

    Java反射是Java语言的一个重要特性,它允许程序在运行时检查和操作类、接口、对象等的内部结构。反射机制使得代码能够动态地获取类的信息并调用其方法,增加了程序的灵活性和可扩展性。以下将详细介绍Java反射中的几...

    java 反射入门-属性方法调用实例

    这篇博文将带你入门Java反射,并通过属性和方法的调用来实践这一概念。 首先,理解反射的基础概念。在Java中,`Class`类代表了运行时的类信息。通过`Class`对象,我们可以获取到类的名称、构造器、方法和字段。例如...

    JDBC_Java反射技术入门

    在这个“JDBC_Java反射技术入门”资源中,初学者可以了解到如何使用Java进行数据库操作的基础知识,包括连接数据库、执行SQL语句、处理查询结果等。 1. **JDBC基础**: - **加载驱动**:在使用JDBC之前,我们需要...

    JAVA反射机制的入门代码

    总的来说,"JAVA反射机制的入门代码"是初学者理解Java反射机制的好教材,通过它,你可以学习如何动态地操作Java类,提高代码的灵活性,并掌握处理`properties`文件的基础方法。在深入学习和实践中,你将进一步理解...

    java从入门到精通PPT

    最后,PPT可能还介绍了Java的高级话题,如反射、注解、泛型和设计模式。这些内容有助于提升你的编程技巧,使你能更好地应对复杂项目的需求。 总的来说,“java从入门到精通PPT”提供了一个全面的学习路线,从基础到...

    java反射机制

    - [Baeldung:Java反射入门](https://www.baeldung.com/java-reflection) - [Stack Overflow上的相关讨论](https://stackoverflow.com/questions/tagged/java-reflection) 总之,Java反射机制是理解Java动态特性的...

    JAVA基础入门到精通pdf

    本资源“JAVA基础入门到精通pdf”提供了一条系统学习Java的路径,适合初学者作为入门教程。以下是对Java基础知识的详细解读: 1. **Java概述**:Java是由Sun Microsystems(现为Oracle公司)于1995年推出的一种面向...

    Java基础入门.rar

    "Java基础入门"这个压缩包提供了学习Java编程的基础资源,包括经典的入门书籍源码和JDK11的中文版API文档。 首先,让我们来了解一下Java API。API(Application Programming Interface)是一系列预先定义的函数,...

    完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt

    完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...

    Java基础入门四泛型反射注解.pdf

    Java基础入门系列是帮助初学者掌握Java编程的重要学习材料,本篇主要介绍了泛型、反射和注解这三大高级特性。 泛型是Java SE 5版本引入的一个新特性,它的主要目的是允许在使用类、接口和方法时能够引用到任何类型...

    《Java从入门到精通(第4版)》随书PPT

    12. **反射与注解**:讲解Java反射机制,如何动态访问和修改类、接口、方法,以及注解的使用和自定义注解的创建。 13. **Java高级特性**:如模块化系统(Project Jigsaw)、Optional类、并发工具类(如...

    java反射 详解 入门到掌握

    Java反射是Java编程语言中的一个强大工具,它允许程序在运行时检查并操作类、接口、字段和方法的信息。这使得开发者能够在不事先知道具体类名或方法名的情况下,动态地创建对象并调用方法。Java反射机制是Java动态性...

    完整版 Java基础入门教程 Java程序语言设计 全套PPT课件资源 共17个章节 含源代码.rar

    完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...

    完整版 Java基础入门教程 Java程序语言设计 04 IO流 输入输出流(共31页).ppt

    完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...

    java 从入门到精通 源代码

    如异常处理、集合框架(ArrayList、LinkedList、HashMap等)、IO流(用于文件读写和网络通信)、多线程编程(线程同步、线程池)、反射机制、设计模式(如单例模式、工厂模式、观察者模式等)以及Java的高级API,如...

    Java入门到精通pdf

    《Java入门到精通》是一本面向Java初学者的权威指南,旨在帮助读者快速掌握Java编程语言的基础知识并逐步深入到高级技术。这本书涵盖了从安装Java开发环境,理解基本语法,到构建复杂应用程序的全过程,是学习Java...

    完整版 Java基础入门教程 Java程序语言设计 03 java对象 集合框架(共18页).ppt

    完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...

    Java语言入门书籍

    第九章通常会涉及一些高级主题,如反射、注解、JNI(Java Native Interface)等,这些可以帮助开发者更好地理解和利用Java的底层机制。 每一章都会包含大量的实例代码和练习,以帮助读者巩固理论知识,提高实际编程...

    完整版 Java基础入门教程 Java程序语言设计 03 java对象 类和对象1(共23页).ppt

    完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...

Global site tag (gtag.js) - Google Analytics