zoukankan      html  css  js  c++  java
  • java中的反射机制详解

      在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息,以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。Java反射机制主要提供了以下功能:

           1.在运行时判断任意一个对象所属的类;
           2.在运行时构造任意一个类的对象;(在编译时通过new()方法就可以构造一个类的对象)
           3.在运行时判断任意一个类所具有的成员变量和方法;
       4.在运行时调用任意一个对象的方法;
           5.生成动态代理。

      Reflection 是 Java 被视为动态(或准动态)语言的关键,允许程序于执行期利用Reflection APIs 取得任何已知名称之 class 的內部信息,包括 package、type、parameters、superclass、implemented interfaces、inner classes、 outer class、fields、constructors、methods、modifiers(如public,static等),并可于运行期生成instances、改变 fields 內容或调用methods(包括私有的方法,即通过反射我们可以打破类的包装机制)。

      一般而言,开发者社区说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构和变量类型,这种语言就称为动态语言。”从这个观点看,perl,python,ruby,javascript等是动态语言,c,c++,c#,java等都不是动态语言。

      尽管在这样的定义与分类下,java并不是动态语言,但他却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映射、倒影”,用在java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或调用其methods。这种“看透 class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

      在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中。

    •   Class类:代表一个类。(位于java.lang)
    •   Field类:代表类的成员变量(成员变量也称为类的属性)。
    •   Method类:代表类的方法。
    •   Constructor类:代表类的构造方法。
    •   Array类:提供了动态创建数组,以及访问数组元素的静态方法。
    Field类:   提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。
    Constructor类: 提供关于类的单个构造方法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,而Constructor类则封装了反射类的构造方法。
    Method类: 提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 这个类不难理解,它是用来封装反射类方法的一个类。
    Class类: 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
    Object类: 每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

      在java中,无论生成某个类的多少个对象,这些对象都对应于同一个class对象。 


      要想使用反射,首先要获得对应类或对象的Class对象,获取某个类或对象的Class对象的三种方法:
      1. 使用Class类的静态方法:Class<?> classType = Class.forName("java.lang.String");
      2. 使用的.class语法:Class<?> classType = String.class;
      3. 适用对象的getClass()方法:String s = "aa"; Class<?> classType = s.getClass();

      若想通过反射来生成类的对象,有以下两种方式:
      1. 先生成欲生成对象对应的Class对象,然后通过Class对象的newInstance()方法直接生成新的实例对象:
          Class<?> classType = String.class;
          String str = classType.newInstance();
      2. 先生成欲生成对象对应的Class对象,然后通过Class对象的getConstructor()方法生成构造方法对象,再通过该构造方法对象来生成新的实例对象:
          Class<?> classType = String.class;
        Constructor<?> constructor = classType.getConstructor();
          String str = constructor.newInstance();  
      其中后者可以通过给getConstructor()方法传递参数而指定特定的构造方法(前者只能使用默认的即参数为空的构造方法):
        Class<?> classType = object.getClass();
        Constructor<?> constructor = classType.getConstructor(new Class[]{String.class, int.class});
        Object obj = constructor.newInstance(new Object[]{"tom", 23});

      

     1 import java.lang.reflect.Field;
     2 import java.lang.reflect.Method;
     3 
     4 
     5 public class ReflectTest {
     6     public Object copy (Object object) throws Exception{
     7         Class<?> classType = object.getClass();
     8         Object objectCopy = classType.getConstructor(new Class[]{})
     9             .newInstance(new Object[]{});
    10         Field[] fields = classType.getDeclaredFields();
    11         for(Field field: fields) {
    12             String name = field.getName();
    13             String firstLetter = name.substring(0, 1).toUpperCase();
    14             String setMethodName = "set" + firstLetter + name.substring(1);
    15             String getMethodName = "get" + firstLetter + name.substring(1);
    16             Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()});
    17             Method getMethod = classType.getMethod(getMethodName, new Class[]{});
    18             setMethod.invoke(objectCopy, new Object[]{getMethod.invoke(object, new Object[]{})});            
    19         }
    20         return objectCopy;
    21     }    
    22     
    23     public static void main(String[] args) throws Exception{
    24         Customer customer = new Customer("Tom", 23);
    25         customer.setId(1L);
    26         ReflectTest reflectTest = new ReflectTest();
    27         Customer customer2 = (Customer)reflectTest.copy(customer);
    28         System.out.println(customer2.getId() + "," + customer2.getName() + "," + customer2.getAge());
    29     }
    30 }
    31 
    32 class Customer {
    33     private Long id;
    34     private String name;
    35     private int age;
    36     
    37     public Customer() {
    38     }
    39     
    40     public Customer(String name, int age) {
    41         this.name = name;
    42         this.age = age;
    43     }
    44 
    45     public Long getId() {
    46         return id;
    47     }
    48 
    49     public void setId(Long id) {
    50         this.id = id;
    51     }
    52 
    53     public String getName() {
    54         return name;
    55     }
    56 
    57     public void setName(String name) {
    58         this.name = name;
    59     }
    60 
    61     public int getAge() {
    62         return age;
    63     }
    64 
    65     public void setAge(int age) {
    66         this.age = age;
    67     }
    68 }

      

      

  • 相关阅读:
    Eclipse 的单步调试
    CALayer快速入门
    UITableView快速入门
    iOS程序启动原理
    iOS触摸事件
    UITableViewCell重用和性能优化
    Autolayout
    iOS适配
    NSTimer
    UIScrollView
  • 原文地址:https://www.cnblogs.com/beanmoon/p/2778840.html
Copyright © 2011-2022 走看看