Java反射理解

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sinat_41917109/article/details/88818669

反射:程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已加载类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法和属性。

Java 反射主要涉及两个类(接口) Class, Member

Class详解

Class与 class 关键字不是同一种东西。class 关键字是在声明 java 类时使用的;而 Class 是 java JDK 提供的一个类,完整路径为 java.lang.Class。每当我们编写并且编译一个新创建的类就会产生一个对应 Class 对象,并且这个 Class 对象会被保存在同名 .class 文件里。当我们 new 一个新对象或者引用静态成员变量时,Java 虚拟机(JVM)中的类加载器系统会将对应 Class 对象加载到 JVM 中,然后 JVM 再根据Class 对象创建我们需要的实例对象或者提供静态变量的引用值。

几种能够获取 Class 对象的方法:

1. Object.getClass()
通过对象实例获取对应 Class 对象,如

Class c = "foo".getClass();

enum E { A, B }
Class c = A.getClass();

byte[] bytes = new byte[1024];
Class c = bytes.getClass();

Set<String> s = new HashSet<String>();
Class c = s.getClass();

基本类型无法使用这种方法

boolean b;
Class c = b.getClass();//编译错误

2. 通过类的类型获取Class对象,

Class c = boolean.class;  

Class c = String.class;

基本类型同样可以使用这种方法

3. Class.forName()
通过类的全限定名获取Class对象, 基本类型无法使用此方法

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

 Member详解
类成员主要包括构造函数,变量和方法,Java 中的操作基本都和这三者相关,而 Member 的这三个实现类就分别对应他们。

java.lang.reflect.Field ://对应类变量
java.lang.reflect.Method ://对应类方法
java.lang.reflect.Constructor ://对应类构造函数

反射就是通过这三个类才能在运行时改变对象状态

Field

Class 提供了4种方法获得给定类的 Field

  • Method 

    • getDeclaredField(String name)     

      获取指定的变量(只要是声明的变量都能获得,包括 private)

    • getField(String name)      

      获取指定的变量(只能获得 public 的)

    • getDeclaredFields()              

      获取所有声明的变量(包括 private)

    • getFields() 

      获取所有的 public 变量

    Class 依然提供了4种方法获取 Method:

    Constructor 

      • getDeclaredMethod(String name, Class<?>... parameterTypes)

        根据方法名获得指定的方法, 参数 name 为方法名,参数 parameterTypes 为方法的参数类型,如 getDeclaredMethod(“eat”, String.class)

      • getMethod(String name, Class<?>... parameterTypes)

        根据方法名获取指定的 public 方法,其它同上

      • getDeclaredMethods()

        获取所有声明的方法

      • getMethods()

        获取所有的 public 方法

    和 Method 一样,Class 也为 Constructor 提供了4种方法获取

    总结: 

      • getDeclaredConstructor(Class<?>... parameterTypes)

        获取指定构造函数,参数 parameterTypes 为构造方法的参数类型

      • getConstructor(Class<?>... parameterTypes)

        获取指定 public 构造函数,参数 parameterTypes 为构造方法的参数类型

      • getDeclaredConstructors()

        获取所有声明的构造方法

      • getConstructors()

        获取所有的 public 构造方法

    • 性能开销

      反射涉及类型动态解析,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。

    • 安全限制

      使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。

    • 内部曝光

      由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。

展开阅读全文

没有更多推荐了,返回首页