zoukankan      html  css  js  c++  java
  • java笔记十:java中的反射

      Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。

      Java的类反射所需要的类并不多,它们分别是:Field、Constructor、Method、Class、Object,下面我将对这些类做一个简单的说明。
    Field类:提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。
    Constructor类:提供关于类的单个构造方法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,而Constructor类则封装了反射类的构造方法。
    Method类:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 这个类不难理解,它是用来封装反射类方法的一个类。
    Class类:类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
    Object类:每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

      下面举几个例子:

    ①、反射类中的属性

     1 package com.reflect;
     2 
     3 import java.awt.event.ActionEvent;
     4 import java.awt.event.ActionListener;
     5 import java.lang.reflect.Field;
     6 
     7 class A extends Object implements ActionListener{
     8     public String s = "aaa";
     9     private int a = 3;
    10     private Integer b = new Integer(4);
    11     public A(){}
    12     public A(int id,String name){}    
    13     private int abc(int id,String name){
    14         return 0;
    15     }
    16     public void actionPerformed(ActionEvent e) {
    17         System.out.println("actionPerformed()");
    18     }
    19     public void f1(int a){System.out.println(a);}
    20     private void f2(int a){
    21         System.out.println(a);
    22     }
    23 }
    24 
    25 public class TestReflect {
    26     public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    27         A a = new A();
    28         Class c = a.getClass();
    29         //反射属性
    30         Field[] fields = c.getFields();//得到公有属性
    31         //Field[] fields = c.getDeclaredFields(); //得到所有属性
    32         for (int i = 0; i < fields.length; i++) {
    33             Class c1 = fields[i].getType(); //得到属性类型
    34             System.out.println(c1);
    35         }
    36         System.out.println("反射类中的私有属性");
    37         Field f = c.getDeclaredField("a");
    38         f.setAccessible(true);  //如果是私有成员,则要加这句,否则无法访问
    39         System.out.println(f.get(a));//f.get(o)返回o对象的f属性
    40     }
    41 
    42 }

      反射类中的属性主要有两个方法:getFields()和getDeclaredFielda(),这两个方法返回的都是一个Field数组。getFields()得到的是public修饰的属性,而getDeclaredFielda()得到的是所有的属性。当然也可以得到某一个属性,如Field f = c.getDeclaredField("a"),如果该属性是私有的话,必须加上f.setAccessible(true),否则用到的时候会报java.lang.IllegalAccessException异常。

    ②、反射类中的构造方法

     1 package com.reflect;
     2 
     3 import java.lang.reflect.Constructor;
     4 
     5 public class RefectConstructors {
     6     public static void main(String[] args) throws NoSuchMethodException, SecurityException {
     7         Class c = A.class;
     8         String className = c.getName();//得到类名
     9         Constructor[] cons = c.getConstructors();  //得到所有构造方法
    10         for (int i = 0; i < cons.length; i++) {
    11             Class[] parameterTypes = cons[i].getParameterTypes();
    12             System.out.print(className+"(");
    13             for (int j = 0; j < parameterTypes.length; j++) {
    14                 System.out.print(parameterTypes[j].getName()+" ");
    15             }
    16             System.out.print(")");
    17             System.out.println();
    18         }
    19         Constructor con = c.getConstructor(int.class,String.class);  //得到某个具体的构造方法
    20         System.out.println(con.getName());
    21     }
    22 
    23 }

      通过反射得到某个类的构造方法可以通过c.getConstructors()来获得,返回的是Constructor数组,也可以用c.getConstructor(Class ...)方法来获得某个具体构造方法这个方法的参数是构造方法的参数类class对象。

    ③、反射接口和父类

     1 package com.reflect;
     2 
     3 public class ReflectInterface {
     4 
     5     public static void main(String[] args) {
     6         Class c = A.class;
     7         //反射得到所有的接口
     8         Class[] interfaces = c.getInterfaces();
     9         for (int i = 0; i < interfaces.length; i++) {
    10             System.out.println(interfaces[i].getName());
    11         }
    12         //反射得到所有的父类
    13         Class superClass = c.getSuperclass();
    14         System.out.println(superClass.getName());
    15     }
    16 }

    ④、反射得到方法

     1 package com.reflect;
     2 
     3 import java.lang.reflect.InvocationTargetException;
     4 import java.lang.reflect.Method;
     5 
     6 public class ReflectMethod {
     7     public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
     8         Class c = A.class;
     9         A a = new A();
    10         //Method[] methods = c.getDeclaredMethods();  //返回该类定义的所有方法。父类的方法若没有被重写则不会返回
    11         Method[] methods = c.getMethods();  //得到public方法,包括从父类继承的方法
    12         for (int i = 0; i < methods.length; i++) {
    13             //输出方法的返回类型
    14             System.out.print(methods[i].getReturnType());
    15             //输出方法名
    16             System.out.print(" "+methods[i].getName()+"(");
    17             //获取方法的参数
    18             Class[] paramTypes = methods[i].getParameterTypes();
    19             for (int j = 0; j < paramTypes.length; j++) {
    20                 System.out.print(paramTypes[j].getName());
    21                 if(paramTypes.length>j+1){
    22                     System.out.print(",");
    23                 }
    24             }
    25             System.out.print(")");
    26             System.out.println();
    27         }
    28         //得到指定私有方法名
    29         Method m = c.getDeclaredMethod("f2",int.class); //方法名、方法中的参数
    30         //私有方法需要让其能够被访问
    31         m.setAccessible(true);
    32         m.invoke(a, 5);
    33     }
    34 
    35 }

      c.getDeclaredMethods():返回该类定义的所有方法。父类的方法若没有被重写则不会返回。

      c.getMethods(): 得到所有public方法,包括从父类继承的方法

      c.getDeclaredMethod(String methodName,Class param) :得到某个具体的方法,要传入方法名和方法的参数。

  • 相关阅读:
    字符转int 的几种方法
    递归在类中的写法
    修改多维才智的名字
    max中用 .net 判断输入的邮箱地址是否合格。
    找处场景中同名称的结点
    Android Button [ 学习笔记 一 ] 原创
    Android中Listview注意事项
    Android 移动开发一本就够学习笔记一
    ListActivity 学习[原创]
    在 Eclipse 中导入 Android 示例程序
  • 原文地址:https://www.cnblogs.com/liuling/p/reflect.html
Copyright © 2011-2022 走看看