zoukankan      html  css  js  c++  java
  • java 反射机制

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

    注意:反射是在运行的时候进行的,不是在编译的时候运行的。

    反射的功能

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

    • 在运行时判断任意一个对象所属的类;
    • 在运行时构造任意一个类的对象;
    • 在运行时判断任意一个类所具有的成员变量和方法;
    • 在运行时调用任意一个对象的方法;生成动态代理。

    API简介

    在这里先看一下sun为我们提供了那些反射机制中的类:

      — java.lang.Class;        代表一个类

      — java.lang.reflect.Constructor; 代表类的构造方法 

      — java.lang.reflect.Field;        代表类的成员变量(成员变量也称为类的属性)

      — java.lang.reflect.Method;  代表类的方法

      — java.lang.reflect.Array;  提供了动态创建数组,以及访问数组的元素的静态方法

    注意:java中无论生成某个类的多少对象, 这些对象都会对应于同一个Class对象。

    方法介绍

    方法关键字

    含义

    getDeclaredMethods()

    获取所有的方法

    getReturnType()

    获得方法的放回类型

    getParameterTypes()

    获得方法的传入参数类型

    getDeclaredMethod("方法名",参数类型.class,……)

    获得特定的方法

    构造方法关键字

    含义

    getDeclaredConstructors()

    获取所有的构造方法

    getDeclaredConstructor(参数类型.class,……)

    获取特定的构造方法

    父类和父接口

    含义

    getSuperclass()

    获取某类的父类

    getInterfaces()

    获取某类实现的接口

    获取Class的三种方式

    1)、使用Class类的forName(String className)静态方法。改方法需要传入字符串参数,改字符串参数的值是某个类的全限定类名(必须添加完整的包名)。

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

    2)、调用某个的class属性来获取该类对应的class对象,如

    String.class

    3)、调用某个对象的getClass方法。

    String s = "aa";
    Class<?> clazz = s.getClass();

    生成对象

    1)、通过不带参数的构造方法生成对象有两种方法

      a)、先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可:

      newInstance()方法可以返回一个实例,但是构造方法要是没有参数列表的,它相当于调用某个类的不带参数的构造方法,但是如果在初始化对象的时候要传参数,就要使用Constructor

    Class<?> classType = String.class;
    Object obj = classType.newInstance();

      b)、先获得Class对象,然后通过该对象获得相应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:

    Class<?> classType = object.getClass();
    Constructor cons = classType.getConstructor(new Class[]{});
    Object obj = cons.newInstance(new Object[]{});

    2)、若想通过类的带参数的构造方法生成对象,只能使用下面一种方式:

       Class<?> classType = object.getClass();
       Constructor cons = classType.getConstructor(new Class[]{String.class,int.class});
       Object obj = cons.newInstance(new Object[]{"hello",3});

      例子

    public class ReflectTester
    {
     
     //方法实现对Customer对象的拷贝操作
     public Object copy(Object object) throws Exception
     {
      Class<?> classType = object.getClass();
      /*Constructor cons = classType.getConstructor(new Class[]{});
     
      Object obj = cons.newInstance(new Object[]{});
      System.out.println(obj);
      System.out.println("-----------");*/
     
      //以上的两行代码等价于下面一行
      //Object obj2 = classType.newInstance();
      Constructor cons2 = classType.getConstructor(new Class[]{String.class, int.class});
      Object obj2 = cons2.newInstance(new Object[]{"hello",3});
      System.out.println(obj2);
     
      return null;
     }
     
     public static void main(String[] args) throws Exception {
      ReflectTester test = new ReflectTester();
      test.copy(new Customer());
     }
     
    }
    class Customer
    {
     private Long id;
     
     private int age;
     
     private String name;
     
     public Customer()
     {
     
     }
     
     public Customer(String name,int age)
     {
      this.name = name;
      this.age= age;
     }
     public Long getId() {
      return id;
     }
     public void setId(Long id) {
      this.id = id;
     }
     public int getAge() {
      return age;
     }
     public void setAge(int age) {
      this.age = age;
     }
     public String getName() {
      return name;
     }
     public void setName(String name) {
      this.name = name;
     }
     
    }

      相对复杂的例子

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    public class ReflectTester
    {
     
     //方法实现对Customer对象的拷贝操作
     public Object copy(Object object) throws Exception
     {
      Class<?> classType = object.getClass();
    
      Object ObjectCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
     
      //获得成员变量
     
      Field[] fields = classType.getDeclaredFields();
      for(Field field : fields)
      {
       String name = field.getName();
       
       String firstLetter = name.substring(0,1).toUpperCase(); //将属性的首字母转换为大写
       
       String getMethodName = "get" + firstLetter + name.substring(1);
       
       String setMethodName = "set" + firstLetter + name.substring(1);
       
       Method getMethod = classType.getMethod(getMethodName, new Class[]{});
       
       Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()});
       
       Object value = getMethod.invoke(object, new Object[]{});
       
       setMethod.invoke(ObjectCopy, new Object[]{value});
       
      }
     
     
      return ObjectCopy;
     }
     
     public static void main(String[] args) throws Exception {
      Customer customer = new Customer("tom",20);
     
      customer.setId(1L);
     
      ReflectTester test = new ReflectTester();
     
      Customer cus = (Customer)test.copy(customer);
     
      System.out.println(cus.getAge()+","+cus.getName()+","+cus.getId());
     }
     
    }
    class Customer
    {
     private Long id;
     
     private int age;
     
     private String name;
     
     public Customer()
     {
     
     }
     
     public Customer(String name,int age)
     {
      this.name = name;
      this.age= age;
     }
     public Long getId() {
      return id;
     }
     public void setId(Long id) {
      this.id = id;
     }
     public int getAge() {
      return age;
     }
     public void setAge(int age) {
      this.age = age;
     }
     public String getName() {
      return name;
     }
     public void setName(String name) {
      this.name = name;
     }
     
    }

      注意:Integer.TYPE返回的是int,而Integer.class返回的是Integer类所对应的Class对象。

    反射生成多维数组

    import java.lang.reflect.Array;
    /**
     *
     * 用反射构造一个多维数组
     *
     */
    public class ArrayTester2 {
     public static void main(String[] args) {
      int[] dims = new int[]{5,10,15};
     
      //newInstance()方法的第二个参数是代表生成数组的维度,所以生成的数组维度为5,10,15,长宽高
      Object array = Array.newInstance(Integer.TYPE,dims);
     
      //arrayObj是一个二维的数组
      Object arrayObj = Array.get(array,3);
     
      Class<?> classType = arrayObj.getClass().getComponentType();
     
      //arrayObj是一个一维的数组
      arrayObj = Array.get(arrayObj, 5);
     
      Array.setInt(arrayObj, 10, 37);
     
      int[][][] arrayCast = (int[][][])array;
     
      System.out.println(arrayCast[3][5][10]);
     }
    }

    反射访问私有(private)的方法

      private 限制的方法没有办法在另外的类中使用,但可以使用反射进行使用。而getMethod()方法只能获取public的方法。如果要使用private的方法就要使用 getDeclaredMethod()方法。

    例子1、获取privete方法、

    public class PrivateTest {
     private String sayHello(String name)
     {
        return "hello" + name;
     }
    }
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    public class TestPrivate {
     public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
      PrivateTest p = new PrivateTest();
     
      Class<?> classType = p.getClass();
     
      Method method = classType.getDeclaredMethod("sayHello", new Class[]{String.class});
     
      method.setAccessible(true); //压制java的访问控制检查
     
      String str = (String)method.invoke(p, new Object[]{"aaa"});
     
      System.out.println(str);
     
     }
     
    }

    例子2、改变private的属性

    public class Private2 {
     private String name = "zhangsan";
     
     public String getName()
     {
      return name;
     }
    }
    /**
     *
     * 将Private2中的private属性name的值变为李四
     *
     */
    public class TestPrivate2{
     
     public static void main(String[] args) throws Exception
     {
      Private2 p = new Private2();
     
      Class<?> classType = p.getClass();
     
      Field field = classType.getDeclaredField("name");
     
      field.setAccessible(true);
     
      field.set(p, "lisi");
     
      System.out.println(p.getName());
     }
     
    }

      致谢:感谢您的阅读!

  • 相关阅读:
    至少有K个重复字符的最长字串 分治法+递归
    旋转数组
    旋转链表 指针移动
    通过删除字母匹配到字典里最长的单词
    How to fix yum after CentOS 6 went EOL
    Centos6 yum源配置(CentOS 6停止更新)
    ORACLE 12C R2 RAC 安装配置指南
    Background Processes Specific to Oracle RAC
    如何缩小 Oracle 数据库中的临时表空间
    Script To Get Tablespace Utilization In Oracle Database 12c
  • 原文地址:https://www.cnblogs.com/0201zcr/p/4858607.html
Copyright © 2011-2022 走看看