java的反射机制

来源:互联网 发布:欧文场均数据 编辑:程序博客网 时间:2024/04/28 00:41
据我的理解,反射机制不过是java提供类信息等的功能。很多框架都使用了这种技术,但平时我们自己用的很少。不过这个功能在运行时不知道class类型时很有作用,还能获取类中的公用方法,等等。
本想自己总结一下有那些用法,后来发现一篇文章,来自:lxblg的BLOG,我自己写估计没那么详细,还是转载过来吧。
==========================================================================

Lesson: 检测类examing class

1.Retrieving Class Objects
获取一个Class对象(metadata)

a,从对象的实例获取。
Class c = mystery.getClass();//(return Class)
b,从子类的实例获取
TextField t = new TextField();
Class c = t.getClass();
Class s = c.getSuperclass();
c,知道类名,则可以把.class加入到名字之后来获取。
Class c = java.awt.Button.class;
d,如果类名在编译时是未知的,则可以使用Class.forName()方法来获取.
Class c = Class.forName(classString);

2.Getting the Class Name
获取类名称
 c.getName();

例如:
import java.lang.reflect.*;
import java.awt.*;

class SampleName {

   public static void main(String[] args) {
      Button b = new Button();
      printName(b);
   }

   static void printName(Object o) {
       Class c = o.getClass();
       String s = c.getName();
       System.out.println(s);
   }
}


3.Discovering Class Modifiers
检索修改符
a.通过getModifiers()方法获取一个整型标识值。
b.通过java.reflect.Modifier对象的isPublic, isAbstract, 和 isFinal方法判断此值.

例如:
import java.lang.reflect.*;
import java.awt.*;

class SampleModifier {

   public static void main(String[] args) {
      String s = new String();
      printModifiers(s);
   }

   public static void printModifiers(Object o) {
      Class c = o.getClass();
      int m = c.getModifiers();
      if (Modifier.isPublic(m))
         System.out.println("public");
      if (Modifier.isAbstract(m))
         System.out.println("abstract");
      if (Modifier.isFinal(m))
         System.out.println("final");
   }
}


4.Finding Superclasses
检索父类
例如:
import java.lang.reflect.*;
import java.awt.*;

class SampleSuper {

   public static void main(String[] args) {
      Button b = new Button();
      printSuperclasses(b);
   }

   static void printSuperclasses(Object o) {
      Class subclass = o.getClass();
      Class superclass = subclass.getSuperclass();
      while (superclass != null) {
         String className = superclass.getName();
         System.out.println(className);
         subclass = superclass;
         superclass = subclass.getSuperclass();
      }
   }
}


5.Identifying the Interfaces Implemented by a Class
检索指定类实现的接口
例如:
import java.lang.reflect.*;
import java.io.*;

class SampleInterface {

   public static void main(String[] args) {
      try {
          RandomAccessFile r = new RandomAccessFile("myfile", "r");
          printInterfaceNames(r);
      } catch (IOException e) {
          System.out.println(e);
      }
   }

   static void printInterfaceNames(Object o) {
      Class c = o.getClass();
      Class[] theInterfaces = c.getInterfaces();
      for (int i = 0; i < theInterfaces.length; i++) {
         String interfaceName = theInterfaces[i].getName();
         System.out.println(interfaceName);
      }
   }
}
6.Examining Interfaces
判定一个类是不是接口

import java.lang.reflect.*;
import java.util.*;

class SampleCheckInterface {

   public static void main(String[] args) {
      Class thread = Thread.class;
      Class runnable = Runnable.class;
      verifyInterface(thread);
      verifyInterface(runnable);
   }

   static void verifyInterface(Class c) {
      String name = c.getName();
      if (c.isInterface()) {
         System.out.println(name + " is an interface.");
      } else {
         System.out.println(name + " is a class.");
      }
   }
}

 

如:c.isInterface()

7.Identifying Class Fields
找出指定类所有的域成员
每个数据成员可以用java.reflect.Field来封闭其名称,类型,修改符的集合。
也可以通过相应的方法获取或设置到该成员的值。
 
如:
import java.lang.reflect.*;
import java.awt.*;

class SampleField {

   public static void main(String[] args) {
      GridBagConstraints g = new GridBagConstraints();
      printFieldNames(g);
   }

   static void printFieldNames(Object o) {
      Class c = o.getClass();
      Field[] publicFields = c.getFields();
      for (int i = 0; i < publicFields.length; i++) {
         String fieldName = publicFields[i].getName();
         Class typeClass = publicFields[i].getType();
         String fieldType = typeClass.getName();
         System.out.println("Name: " + fieldName +
           ", Type: " + fieldType);
         }
      }
}

 

8.Discovering Class Constructors
检索指定类的构造函数

当创建一个类的实例时,是通过检造方法来作的,这种方法可以被重载。
每一个构造方法可以用类Constructor来描述,,包括名称,修饰符,参数类型(Class[]),和异常列表。
可以通过一个Class的getConstructors方法获取到该类的Constructor数组。
例程:
import java.lang.reflect.*;
import java.awt.*;

class SampleConstructor {

   public static void main(String[] args) {
      Rectangle r = new Rectangle();
      showConstructors(r);
   }

   static void showConstructors(Object o) {
      Class c = o.getClass();
      Constructor[] theConstructors = c.getConstructors();
      for (int i = 0; i < theConstructors.length; i++) {
         System.out.print("( ");
         Class[] parameterTypes =
            theConstructors[i].getParameterTypes();
         for (int k = 0; k < parameterTypes.length; k ++) {
            String parameterString = parameterTypes[k].getName();
            System.out.print(parameterString + " ");
            }
         System.out.println(")");
         }
   }
}

 

 

9.Obtaining Method Information
检索方法
可以找到隶属于一个类的所有方法,通过getMethods包含Method数组,进而得到该方法的返回类型,修饰符,方法名称,参数列表
步骤:
a.指定类的Class Object
b.getMethods()获取Method[]对象
c,遍历该数组对象

例程:

import java.lang.reflect.*;
import java.awt.*;

class SampleMethod {

   public static void main(String[] args) {
      Polygon p = new Polygon();
      showMethods(p);
   }

   static void showMethods(Object o) {
      Class c = o.getClass();
      Method[] theMethods = c.getMethods();
      for (int i = 0; i < theMethods.length; i++) {
         String methodString = theMethods[i].getName();
         System.out.println("Name: " + methodString);
         String returnString =
           theMethods[i].getReturnType().getName();
         System.out.println("   Return Type: " + returnString);
         Class[] parameterTypes = theMethods[i].getParameterTypes();
         System.out.print("   Parameter Types:");
         for (int k = 0; k < parameterTypes.length; k ++) {
            String parameterString = parameterTypes[k].getName();
            System.out.print(" " + parameterString);
         }
         System.out.println();
      }
   }
}
======================================================================

Lesson:2 处理对象
1.Creating Objects
一般情况下,创建一个对象用以下方法
Rectangle r = new Rectangle();
但如果你正在开发一个development tools,在运行之前或许不知道要生成对象的类。
所以要像下面这样来创建对象:
String className;

// . . . load className from the user interface

Object o = new (className); // WRONG!


但以上是错误的。
正确的方法是使用类的反射特性:


1)Using No-Argument Constructors
例如:
    Class classDefinition = Class.forName(className);//指定类的运行期实例
    object = classDefinition.newInstance();//调用无参构造函数来生成指定类的实例。

2)Using Constructors that Have Arguments
这个技术要用到如下步骤:
a,创建一个Class对象
b,创建一个Constructor对象,getConstructor(Class[] params)方法,参数是一个与构造方法相适合的Class 数组.
c,在Constructor对象上调用newInstance方法来生成一个对象,参数 是一个object数组与这个构造方法相配备。

例如:
import java.lang.reflect.*;
import java.awt.*;

class SampleInstance {

   public static void main(String[] args) {

      Rectangle rectangle;
      Class rectangleDefinition;
     

Class[] intArgsClass = new Class[] {int.class, int.class};
      Integer height = new Integer(12);
      Integer width = new Integer(34);
      Object[] intArgs = new Object[] {height, width};

      Constructor intArgsConstructor;

      try {
//1.
        rectangleDefinition = Class.forName("java.awt.Rectangle");
  //2.
      intArgsConstructor =
            rectangleDefinition.getConstructor(intArgsClass);//找到指定的构造方法
//3.     
  rectangle =
            (Rectangle) createObject(intArgsConstructor, intArgs);//构造方法描述对象,object[]
      } catch (ClassNotFoundException e) {
          System.out.println(e);
      } catch (NoSuchMethodException e) {
          System.out.println(e);
      }
   }

   public static Object createObject(Constructor constructor,
                                     Object[] arguments) {

      System.out.println ("Constructor: " + constructor.toString());
      Object object = null;

      try {
        object = constructor.newInstance(arguments);
        System.out.println ("Object: " + object.toString());
        return object;
      } catch (InstantiationException e) {
          System.out.println(e);
      } catch (IllegalAccessException e) {
          System.out.println(e);
      } catch (IllegalArgumentException e) {
          System.out.println(e);
      } catch (InvocationTargetException e) {
          System.out.println(e);
      }
      return object;
   }
}

 

2。Getting Field Values
If you are writing a development tool such as a debugger, you must be able to obtain field values. This is a three-step process:
如果要作一个开发工具像debugger之类的,你必须能发现filed values,以下是三个步骤:
a.创建一个Class对象
b.通过getField 创建一个Field对象
c.调用Field.getXXX(Object)方法(XXX是Int,Float等,如果是对象就省略;Object是指实
例).

例如:
import java.lang.reflect.*;
import java.awt.*;

class SampleGet {

   public static void main(String[] args) {
      Rectangle r = new Rectangle(100, 325);
      printHeight(r);

   }

   static void printHeight(Rectangle r) {
      Field heightField;
      Integer heightValue;
      Class c = r.getClass();
      try {
        heightField = c.getField("height");
        heightValue = (Integer) heightField.get(r);
        System.out.println("Height: " + heightValue.toString());
      } catch (NoSuchFieldException e) {
          System.out.println(e);
      } catch (SecurityException e) {
          System.out.println(e);
      } catch (IllegalAccessException e) {
          System.out.println(e);
      }
   }
}

3。Setting Field Values
a.创建一个Class对象
b.通过getField 创建一个Field对象
c.调用Field.set(Object,withparam)方法(XXX是Int,Float等,如果是对象就省略;Object是指实例,withparam指和这个字段相区配的字段。

import java.lang.reflect.*;
import java.awt.*;

class SampleSet {

   public static void main(String[] args) {
      Rectangle r = new Rectangle(100, 20);
      System.out.println("original: " + r.toString());
      modifyWidth(r, new Integer(300));
      System.out.println("modified: " + r.toString());
   }

   static void modifyWidth(Rectangle r, Integer widthParam ) {
      Field widthField;
      Integer widthValue;
      Class c = r.getClass();
      try {
        widthField = c.getField("width");
        widthField.set(r, widthParam);
      } catch (NoSuchFieldException e) {
          System.out.println(e);
      } catch (IllegalAccessException e) {
          System.out.println(e);
      }
   }
}

4。调用指定的方法
a.创建一个Class对象
b.创建一个方法对象method,getMethod(String methodName,Class[])方法
c.调方法对象,method.invoke(object,Object[]),两个参数,第一个是指调用方法所属于的对象,第二个是传递的值对象列表。

The sample program that follows shows you how to invoke a method dynamically. The program retrieves the Method object for the String.concat method and then uses invoke to concatenate two String objects.
//


import java.lang.reflect.*;

class SampleInvoke {

   public static void main(String[] args) {
      String firstWord = "Hello "; //指定类的实例

      String secondWord = "everybody.";//变元


      String bothWords = append(firstWord, secondWord);
      System.out.println(bothWords);
   }

   public static String append(String firstWord, String secondWord) {
      String result = null;
      Class c = String.class;
      Class[] parameterTypes = new Class[] {String.class};
      Method concatMethod;
      Object[] arguments = new Object[] {secondWord};
      try {
        concatMethod = c.getMethod("concat", parameterTypes);//获取到方法对象
        result = (String) concatMethod.invoke(firstWord, arguments);//调用
      } catch (NoSuchMethodException e) {
          System.out.println(e);
      } catch (IllegalAccessException e) {
          System.out.println(e);
      } catch (InvocationTargetException e) {
          System.out.println(e);
      }
      return result;
   }
}

原创粉丝点击