Java的反射(reflect)机制的学习

来源:互联网 发布:shell脚本调用java类 编辑:程序博客网 时间:2024/05/29 16:19

              学习反射的知识,要从java.lang.Class类说起。

              我们都知道java是一个面型对象的语言,面向对象就是把具有相同属性的事物抽象成一个类。万物皆对象。

              那么对于Java程序中的各个Java类也是属于同一类事物,描述这类事物的Java类名就是java.lang.Class它和一般classes一样继承自Object,其实体用以表达Java程序运行时的classesinterfaces,也用来表达enumarrayprimitive Java typesboolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class loader)的defineClass()JVM调用,JVM 便自动产生一个Class object

              Class没有public constructor所以无法直接new出Class对象。

               了解了Class类,那它与反射又有什么关系呢?我们来看看反射的相关概念。

JAVA反射机制定义: JAVA反射机制是java程序在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 

反射就是把Java类中的各种成分映射成相应的Java类。

 

Java反射机制主要提供了以下功能: 

在运行时判断任意一个对象所属的类;

在运行时构造任意一个类的对象;

在运行时判断任意一个类所具有的成员变量和方法;

在运行时调用任意一个对象的方法;

生成动态代理。

我们了解了反射机制的功能,那么我们如何具体来实现它呢?

"一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过Class类的方法可以得到这些实例对象;"这句话就说明了我们可以用Class的类的方法来实现反射的功能!

我们前面说了Class类没有公共的构造函数,我们怎么样才能获得这种对象呢?别急,Java为我们提供了多种方法可以实现获得Class对象!如下所示:

运用getClass()  注:每个class 都有此函数   

String str = "abc";   

Class c1 = str.getClass();   

运用 Class.getSuperclass()

   Button b = new Button();

   Class c1 = b.getClass(); 

   Class c2 = c1.getSuperclass();   

运用static method Class.forName()   (最常被使用)

   Class c1 = Class.forName ("java.lang.String"); 

   Class c2 = Class.forName ("java.awt.Button");

   Class c3 = Class.forName ("java.util.LinkedList$Entry"); 

   Class c4 = Class.forName ("I");

   Class c5 = Class.forName (".class);   

运用 java基本数据类型包装类和voidTYPE 语法

   Class c1 = Boolean.TYPE; 

   Class c2 = Byte.TYPE; 

   Class c3 = Character.TYPE;

   Class c4 = Short.TYPE;

   Class c5 = Integer.TYPE;

   Class c6 = Long.TYPE;

   Class c7 = Float.TYPE; 

   Class c8 = Double.TYPE;

   Class c9 = Void.TYPE;   

运用java基本数据类型的clss属性

   int.class;……

现在我们已经可以获得Class对象啦,如何利用反射构造一个这种类型的新的对象呢?首先要获得你要反射的对象的类的构造方法,是吧!再看这句话"一个类中的每个成员可以用相应的反射包中的一个类的实例对象来表示,通过Class类的方法可以得到这些实例对象;"

我要告诉你的是这个“成员”就包括:类的构造函数、成员变量、方法等一些信息。而他们所对应的反射包中的类分别是:Constructor类、Field类、Method类。

 

                一。Constructor类代表某个类中的一个构造方法

1.得到某个类所有的构造方法

例如:Constructor[]constructors=Clsaa.forName("java.lang.String").getConstructors();

2.得到一个具体的构造方法

Constructor constructor=Class.forName("java.lang.String").getConstructor(StringBuffer.class);//获得方法时要提供相应的类型参数

3.创建实例对象:

方法一:String str=(String)constructor.newInstance(new StringBuffer("abc"));//调用获得的构造方法是注意传入的参数类型一致。

方法二:Class.newInstance()方法  :该方法内部先得到默认构造方法的对象,然后用该构造方法的对象创建实例对象。

String obj = (String)Class.forName("java.lang.String").newInstance();

               二。 Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。Object  getobject obj返回指定对象上此 Field 表示的字段的值。如果该值是一个基本类型值,则自动将其包装在一个对象中。 

               基础字段的值是按以下方式获得的:

  User user=new User("wangfayin",20);

  Field name=user.getClass().getField("name");   //要注意现在我们获得的是一个User类中名称为  name  的字段对象,而不是一个值,也不是一个具体User对象的字段;

  String nameStr=(String)name.get(user);   //获得的是一个Object类型,要进行强制类型转换。
  System.out.println(nameStr);

如果基础字段是一个静态字段,则可以忽略get中 参数 将其设置为 null

                三。Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

invoke(Object obj, Object... args)
          对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null

用反射的方法调用某个main方法实例如下:

Class userClass=user.getClass();

Method say = userClass.getMethod("say");

User newUser=(User) userClass.getConstructor(String.class,int.class).newInstance("Li",30);

say.invoke(newUser); 

有不清楚得地方欢迎交流!

原创粉丝点击