zoukankan      html  css  js  c++  java
  • 反射

    反射机制

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

    反射技术

    类字节码文件是在硬盘上存储的,是一个个的.class文件。我们在new一个对象时,JVM会先把字节码文件的信息读出来放到内存中,第二次用时,就不用在加载了,而是直接使用之前缓存的这个字节码信息。字节码的信息包括:类名、声明的方法、声明的字段等信息。在Java中“万物皆对象”,这些信息当然也需要封装一个对象,这就是Class类、Method类、Field类。通过Class类、Method类、Field类等等类可以得到这个类型的一些信息,甚至可以不用new关键字就创建一个实例,可以执行一个对象中的方法,设置或获取字段的值,这就是反射技术。

    反射技术中涉及到的类的用法

    1、Class类

    Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(booleanbytecharshortintlongfloatdouble)和关键字 void 也表示为 Class 对象。Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

    获取Class对象的三种方式:

    1、static Class<?> forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象。

    2、类名.class;

    3、对象.getClass();

    代码示例:

    1     public void test() throws Exception {
    2         // 方式一
    3         Class clazz1 = Class.forName("com.nick.reflect.Person");
    4         // 方式二
    5         Class clazz2 = Person.class;
    6         // 方式三
    7         Person p1 = new Person();
    8         Class clazz3 = p1.getClass();
    9     }

    通过Class类获取类型的信息

    String getName()String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。

    String getSimpleName() 返回源代码中给出的底层类的简称。

    int getModifiers() 返回此类或接口以整数编码的 Java 语言修饰符。

    创建对象

    T newInstance() 创建此 Class 对象所表示的类的一个新实例。

    代码示例:

     1     private static void test2() throws Exception {
     2 
     3         Class clazz1 = Class.forName("com.nick.reflect.Person");
     4         // 获取类的名称
     5         String name = clazz1.getName();
     6         System.out.println(name); // com.nick.reflect.Person
     7         // 获取类的简单名称
     8         System.out.println(clazz1.getSimpleName()); // Person
     9         // 获取类的修饰符
    10         int modifiers = clazz1.getModifiers();
    11         System.out.println(modifiers);
    12         // 构建对象(默认调用无参数构造.)
    13         Object ins = clazz1.newInstance();
    14         Person p = (Person) ins;
    15         System.out.println(p); // com.nick.reflect.Person@c17164
    16         }

    获取构造方法

    Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。

    Constructor<?>[] getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。

    Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。

    Constructor<?>[] getDeclaredConstructor(Class<?>... parameterTypes)  返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。

    示例代码

     1 public static void main(String[] args) throws Exception {
     2         //获取到对应的Class对象
     3         Class clazz = Class.forName("com.nick.reflect.Person");
     4         
     5         //通过Class对象获取对应的构造方法
     6         /*Constructor[] constructors = clazz.getConstructors();  // getConstructors()获取一个类的所有公共的构造方法
     7         for(Constructor constructor : constructors){
     8             System.out.println(constructor);
     9         }
    10         
    11         Constructor[] constructors =  clazz.getDeclaredConstructors(); //获取到一个类的所有构造方法,包括私有的在内 。
    12         for(Constructor constructor : constructors){
    13             System.out.println(constructor);
    14         }
    15         */
    16         
    17         /*Constructor constructor = clazz.getConstructor(int.class,String.class);  // getConstructor 获取单个指定的构造方法。
    18         Person p  = (Person) constructor.newInstance(999,"小城"); // newInstance()创建一个对象
    19         System.out.println(p);*/
    20         
    21         
    22         
    23         //获取私有的构造函数
    24         Constructor constructor =  clazz.getDeclaredConstructor(null);
    25         //暴力反射
    26         constructor.setAccessible(true);
    27         Person p  =(Person) constructor.newInstance(null);
    28         System.out.println(p);
    29         
    30         
    31     }

    获取方法

    Method getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。

    Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。

    Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。

    Method[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

    调用方法

    Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。

    代码示例

    public static void main(String[] args) throws Exception {
            //获取到对应的Class对象
            Class clazz = Class.forName("com.nick.reflect.Person");
            
            //获取到所有公共的方法
            /*Method[] methods = clazz.getMethods(); // getMethods() 获取所有 的公共方法而已。
            Method[] methods = clazz.getDeclaredMethods(); //获取到所有的方法,但是不包含父类的方法。
            for(Method method  : methods){
                System.out.println(method);
            }*/
            
            Person p = new Person(110,"狗娃");
            /*    
            Method m = clazz.getMethod("eat", int.class);
            m.invoke(p, 3); //invoke 执行一个方法。 第一个参数:方法的调用对象。 第二参数: 方法所需要的参数。
            
            
            //执行私有的方法
            Method m =clazz.getDeclaredMethod("sleep",int.class);
            //设置访问权限允许访问
            m.setAccessible(true);
            m.invoke(null, 6);*/
            
            Method m = clazz.getMethod("sum", int[].class);
            m.invoke(p,new int[]{12,5,9});
    
        }

    获取属性

    Field getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。

    Field[] getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。

    Objec get(Object obj) 返回指定对象上此 Field 表示的字段的值。

    void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

    代码示例:

     1 public static void main(String[] args) throws Exception {
     2         //获取到对应的Class对象
     3         Class clazz = Class.forName("com.nick.reflect.Person");
     4         
     5         //获取 到所有的成员变量
     6         /*Field[] fields = clazz.getDeclaredFields();
     7         for(Field field  : fields){
     8             System.out.println(field);
     9         }*/
    10         Person p = new Person();
    11         Field field = clazz.getDeclaredField("id");
    12         //设置访问权限可以访问
    13         field.setAccessible(true);
    14         field.set(p, 110); //第一个参数: 设置该数据 的成员变量, 第二个参数:属性值。
    15         System.out.println(p);
    16 
    17     }

    具体详细内容可以参照:http://www.cnblogs.com/lzq198754/p/5780331.html。

  • 相关阅读:
    UNIX网络编程——非阻塞connect
    UNIX网络编程——非阻塞式I/O(套接字)
    UNIX网络编程——使用select 实现套接字I/O超时
    UNIX网络编程——设置套接字超时
    UNIX网络编程——名字与地址转换(gethostbyname,gethostbyaddr,getservbyname,getservbyport,getaddrinfo,getnameinfo函数)
    [Java] Java API文档下载方法
    [Selenium] 在Grid模式下打印出当前Case是在哪台Node上运行
    [Selenium] 针对下拉菜单出现之后又立马消失的问题,通过Javascript改变元素的可见属性
    [Java] 通过XPath获取XML中某个节点的属性
    [Java] 获取当前Project所在的路径
  • 原文地址:https://www.cnblogs.com/nicker/p/6274864.html
Copyright © 2011-2022 走看看