【反射】JAVA反射机制

来源:互联网 发布:mac和投影仪无线连接 编辑:程序博客网 时间:2024/03/29 08:57

1. 什么是反射

反射机制是在运行状态中,对类信息的获取,以及对对象方法的调用机制。

在Java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息:
- 访问修饰符
- 继承的父类
- 实现的接口
- 属性和方法

反射机制还可以操作对象实例:
- 创建对象
- 修改对象属性
- 调用对象方法

2. 反射机制的用途

静态编译:在编译时确定类型,绑定对象。
动态编译:在运行时确定类型,绑定对象。

Driver driver=new Driver(); //静态创建Class.forName("com.mysql.jdbc.Driver.class").newInstance(); //动态创建

动态编译最大限度的发挥了Java的灵活性,体现了多态的应用,用以降低类之间的耦合性。

反射机制就是用来动态创建对象和编译。反射机制对性能有影响,这类操作总是慢于直接执行的相同操作。

3. Class对象

要想动态操作类中的属性和方法,都必须从获取Class对象开始。

当我们编写一个新的Java类时,JVM会先编译出一个Class对象,从放在同名的.class字节码文件中,在需要生成这个类的对象的时候,JVM就会检测此类是否装载到内存当中,若没有装载,先把.class字节码文件装载到内存中;若已经装载,则根据.class文件生成一个实例对象

3.1 获取Class对象

Class类没有公共的构造方法,Class对象是加载类的时候由JVM通过调用类加载器中的方法自动构造的,因此不能显式声明一个Class对象。

要获取Class对象,有以下几种方式:

  • ==Class.forName(完整类名)== 用Class的静态方法,根据传入的类名获取
Class c1=Class.forName("java.lang.String");
  • Class.class语法 直接获取一个类的Class对象
Class listClass=ArrayList.class;
  • object.getClass() 获取指定实例的Class
String str="abc";Class c1=str.getClass;
  • class.getSuperclass() 获取当前class的父类的class
List list=new ArrayList();Class listClass=list.getClass();Class superClass=listClass.getSuperclass();
  • Primitive.TYPE 基本数据类型的包装类获取
Class longClass=long.TYPE;Class integerClass=Integer.TYPE;Class longClass=int.class;

3.2 class方法摘要

Class方法摘要:

  • toString():将对象转换为字符串。字符串的表示形式为字符串 “class” 或 “interface” 后面紧跟一个空格,然后是该类的完全限定名。
  • forName(String className):返回与带有给定字符串名的类或接口相关联的 Class 对象。
  • newInstance():创建此 Class 对象所表示的类的一个新实例。
  • getName:以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
  • Class

4 Class类实现反射机制

4.1 通过反射实例化对象

  • 实例化无参构造函数的对象
    • Class.newInstance();
    • class.getConstructor(new Class[]{}).newInstance(new Object[]{})
  • 参数的类型对应的class对象
    • class.getConstructor(Class

4.2 通过反射获取并调用属性

  • Field[] getFields:获得当前类以及超类的public Field
  • Field[] getDeclaredFields:获得当前类声明的Field
  • Field getField(String name):获取当前类以及超类的指定public Field
  • Field getDeclaredFields(String name):多去当前类生命的指定Field

通过反射动态指定Field的值:
- 属于Field类的方法:Field Field.set(Object obj,Object value): obj是要设定Field所属的对象,Object value是Field对应的值。
通过反射动态获取Filed的值:
- 属于Field类的方法:Object Filed.get(Object obj)

4.3 通过反射获取并调用方法

  • Method[] getMethods():获得当前类以及超类的public Method。
  • Method[] getDeclaredMethods():获得当前类声明的Method。
  • Method[] getMethod(String name, Class

5. Java.lang.reflect库

提供类和接口,以获得关于类和对象的反射信息。

类摘要:
Field:代表类的成员变量
Method:代表类的方法
Constructor:代表类的构造方法
Array:提供了动态创建数组,以及访问数组的元素的静态方法

在第4节已经涉及到几个reflect库中的类方法完成的反射机制:

  • 通过反射动态指定Field的值:
    • 属于Field类的方法:Field Field.set(Object obj,Object value): obj是要设定Field所属的对象,Object value是Field对应的值。
  • 通过反射动态获取Filed的值:

    • 属于Field类的方法:Object Filed.get(Object obj)
  • 通过反射动态运行指定Method:

    • 属于method类的方法:Object method.invoke(Object obj,Object…args): obj是方法所属的对象,Object…args是方法所需要的参数。
  • 实例化无参构造函数的对象

    • class.getConstructor(new Class[]{}).newInstance(new Object[]{})
  • 参数的类型对应的class对象
    • class.getConstructor(Class

6.反射总结

  • 只要用到反射,必先获得Class对象
  • 没有方法能获得当前类的超配的private方法和属性,你必须通过getSuperClass()找到超类以后再用getMethod方法。
  • 通常情况下,即使是当前类,pricate属性或方法也是不能访问的,需要设置压制权限setAccessible(true)来取得private的访问权。但是最好不要这么做。

Code Demo

使用Java反射机制动态创建数组

package com.reflection;import java.lang.reflect.Array;public class ReflectionArrayDemo {    public static void main(String[] args) throws Exception{        //动态地创建一个一维数组(String)        Class<?> classType=Class.forName("java.lang.String");        Object array=Array.newInstance(classType, 5);//创建一个String类型的长度为5的数组        Array.set(array, 3, "abc");        System.out.println(Array.get(array,3));        //动态地创建一个二维整形数组(3行3列)        int[] dimens={3,3};        Class<?> classType1=int.class;        Object array1=Array.newInstance(classType1, dimens);        Object arrayObj=Array.get(array1, 2);//先定位到第三行        Array.setInt(arrayObj, 2, 200);//再对第三行的第三个元素赋值        int[][] array2=(int [][])array1;//二维数组的数据类型从Object类型装换为int类型        System.out.println(array2[2][2]);        System.out.println(Array.get(arrayObj,2));    }}
0 0