现在的位置: 首页 > 综合 > 正文

黑马程序员_反射

2014年02月18日 ⁄ 综合 ⁄ 共 5680字 ⁄ 字号 评论关闭

----------------------android培训java培训、期待与您交流!
-------------------------------------

反射:
 具有动态获取类的信息,以及动态调用类的方法的功能。
 一个类中的每个成员都可以用相应的反射API类中的一个实例对象来表示,通过调用Class类中的方法,可以得到这些实例对象。

反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。 
Class中方法: 静态  Class<?> forName(String className)className - 所需类的完全限定名。
   返回与带有给定字符串名的类或接口相关联的 Class 对象。
           
  例如,以下代码片段返回命名为 java.lang.Thread 的类的运行时 Class 描述符。

     Class t = Class.forName("java.lang.Thread")
   调用 forName("X") 将导致命名为 X 的类被初始化。

 Java 的反射机制是使其具有动态特性(所谓动态是指在程序运行期间可以改变程序结构和变量类型。)的非常关键的一种机制,也是在JavaBean 中

广泛应用的一种特性。它可以让程序在运行期间加载编译期间不得而知的Class。并可以生成其实例、调用其方法、为其属性赋值。
 JAVA的Reflection(反射)机制同样可以在程序运行期间得到 Class 的名称,构造并生成其实例。利用 Reflection 我们可以为 fields(属性)

赋值,调用其 method。

Java 反射相关的API简介:
位于java.lang.reflect包中
--Class类:代表一个类
--Filed类:代表类的成员变量
--Method类:代表类的方法
--Constructor类:代表类的构造方法
--Array类:提供了动态创建数组,以及访问数组的元素的静态方法。该类中的所有方法都是静态方法

反射功能:
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法)
 强制访问:method.setaccessible(true)
4.在运行时调用任意一个对象的方法(*****注意:前提都是在运行时,而不是在编译时)

反射作用:
----运行时生成instance

想生成对象的实体,在反射动态机制中有两种方法,一个针对无变量的构造方法,一个针对带参数的构造方法,,如果想调用带参数的构造方法,就比较的麻

烦,不 能直接调用Class类中的newInstance(),而是调用Constructor类中newInstance()方法,首先准备一个Class[]作为Constructor的参数类型。然

后调用该Class对象的getConstructor()方法获得一个专属的Constructor的对象,最后再准备一个
Object[]作为Constructor对象昂的newInstance(()方法的实参。
在这里需要说明的是 只有两个类拥有newInstance()方法,分别是Class类和Constructor类
Class类中的newInstance()方法是不带参数的,而Constructro类中的newInstance()方法是带参数的
需要提供必要的参数。

1. 一个简单的例子

import java.lang.reflect.*;
public class DumpMethods {
   public static void main(String args[]) {
      try {
           Class c = Class.forName("java.util.Stack");
           Method m[] = c.getDeclaredMethods();
           
           for (int i = 0; i < m.length; i++)
               System.out.println(m[i].toString());
      }
      catch (Throwable e){
            System.err.println(e);
      }
   }
}
它的结果输出为:

public synchronized java.lang.Object java.util.Stack.pop()
public java.lang.Object java.util.Stack.push(java.lang.Object)
public boolean java.util.Stack.empty()
public synchronized java.lang.Object java.util.Stack.peek()
public synchronized int java.util.Stack.search(java.lang.Object)
列出了java.util.Stack 类的各方法名以及它们的限制符和返回类型。
这个程序使用 Class.forName 载入指定的类,然后调用 getDeclaredMethods 来获取这个类中定义了的方法列表。java.lang.reflect.Methods 是用来描

述某个类中单个方法的一个类。

--------
找出类的方法:找出一个类中定义了些什么方法

import java.lang.reflect.*; 
public class Method1 {
   private int f1(Object p, int x) throws NullPointerException {
   if (p == null)
      throw new NullPointerException();
   return x;

   public static void main(String args[]) {
       try {
           Class cls = Class.forName("Method1"); //取得 method1 类的描述
           Method methlist[] = cls.getDeclaredMethods();  //调用 getDeclaredMethods 来获取一系列的 Method 对象,它们分别描述了

定义在类中的每一个方法,包括 public 方法、protected 方法、package 方法和 private 方法等。
           for (int i = 0; i < methlist.length; i++)
   {
               Method m = methlist[i]; //取得 Method 对象列表
               System.out.println("name = " + m.getName());
               System.out.println("decl class = " + m.getDeclaringClass());
               Class pvec[] = m.getParameterTypes();
               for (int j = 0; j < pvec.length; j++)
                   System.out.println("param #" + j + " " + pvec[j]);
               Class evec[] = m.getExceptionTypes();
               for (int j = 0; j < evec.length; j++)
                   System.out.println("exc #" + j + " " + evec[j]);
               System.out.println("return type = " + m.getReturnType());
               System.out.println("-----");
           }
       }
       catch (Throwable e) {
           System.err.println(e);
       }
   }

输出的结果如下:

name = f1
decl class = class method1
param #0 class java.lang.Object
param #1 int
exc #0 class java.lang.NullPointerException
return type = int
-----
name = main
decl class = class method1
param #0 class [Ljava.lang.String;
return type = void

获取构造器、字段信息的用法与上述获取方法的用法类似
------------------
根据方法的名称来执行方法

reflection 也可以来做一些其它的事情,比如执行一个指定了名称的方法:

import java.lang.reflect.*;
public class Method2 {
   public int add(int a, int b) {
      return a + b;
   }
   public static void main(String args[]) {
      try {
           Class cls = Class.forName("Method2");
           Class partypes[] = new Class[2];
           partypes[0] = Integer.TYPE;
           partypes[1] = Integer.TYPE;
      
           Method meth = cls.getMethod("add", partypes); //方法的名称是在程序的运行过程中指定的
           Method2 methobj = new Method2();
           Object arglist[] = new Object[2];
           arglist[0] = new Integer(37);
           arglist[1] = new Integer(47);
           Object retobj = meth.invoke(methobj, arglist);
           Integer retval = (Integer) retobj;
           System.out.println(retval.intValue());
      }
      catch (Throwable e) {
           System.err.println(e);
      }
   }
}

上例中,getMethod用于查找一个具有两个整型参数且名为 add 的方法。找到该方法并创建了相应的Method 对象之后,在正确的对象实例中执行它。执行该

方法的时候,需要提供一个参数列表,这在上例中是分别用了基本类型包装类 37 和 47 的两个 Integer 对象。执行方法的返回的同样是一个 Integer 对象

84。
--------------
改变字段(域)的值:
reflection 的还有一个用处就是改变对象数据字段的值。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"); //搜索到成员变量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);
      }
   }
}
字段 d 的值被变为了 12.34。

--------------------
使用数组,最后一种用法是反射创建的操作数组。数组在 Java 语言中是一种特殊的类类型,一个数组的引用可以赋给 Object 引用:

import java.lang.reflect.*; 
public class Array1 {
   public static void main(String args[]) {
      try {
           Class cls = Class.forName("java.lang.String");
           Object arr = Array.newInstance(cls, 10); //创建了 10 个单位长度的 String 数组
           Array.set(arr, 5, "this is a test"); //为第 5 个位置的字符串赋值
           String s = (String) Array.get(arr, 5);
           System.out.println(s); //将这个字符串从数组中取得并打印了出来。
      }
      catch (Throwable e) {
           System.err.println(e);
      }
   }
}

----------------------android培训java培训、期待与您交流!
----------------------详细请查看:
http://edu.csdn.net/heima(日记必用代码)

抱歉!评论已关闭.