反射reflect

来源:互联网 发布:思科查看端口流量命令 编辑:程序博客网 时间:2024/06/07 02:06

Java的反射机制常被用于检查或者修改在JVM中运行的程序的实时行为,是非常高级的Java特性,如果不是对Java掌握的非常透彻,建议不要随便使用!除此之外,反射是一个非常强大的技术,它可以让你的应用拥有前所未有的能力:

可扩展性特性:使应用可以通过类的名称来创建用户自建的类对象。

类浏览器以及可视化开发环境:类浏览器可以查看类里包含的所有成员。可视化开发环境利用反射提供的类型信息帮助开发人员写出正确的代码

调试器以及测试工具:调试器需要检查类的私有成员。测试工具可利用反射机制系统的调用类中的一系列API,以单元测试保证代码质量(TestNG, JUnit)


反射的缺点:反射会造成性能上的障碍、会带来安全问题、会暴露出代码的内部结构。如果可以用其他方法达到相同的目的,就不应使用反射!


每个对象要么是一个引用类型要么是一个基本类型,

所有引用类型都继承自java.lang.Object,类、枚举、数组已经接口都是引用类型,比如java.lang.String,而基本类型是固定的几个:boolean, byte, short, int, long, char, float以及double。

JVM会为每个类型的对象实例化一个不可变的java.lang.Class对象(就是说对每个类,JVM中都有一个类型为Class的对象对应这个类),这个对象提供一些方法检测这个对象运行时的属性,比如成员和类型信息。Class类也提供创建新类和对象的功能。最重要的是,Class类(对每个其他类来说是Class对象)是所有反射API的入口。


1 获取Class对象

所有反射操作都通过java.lang.Class进行,这个类及其实例化的对象是反射机制的入口。java.lang.reflect包中没有一个类有公共的构建器。要取得这些类,我们需要调用Class类中的某些适当的方法。下面介绍一些获取Class的方法,当然能不能获取还要看代码有没有访问这个对象、类名或者已经存在的Class的权限。


1.1 Object.getClass()

如果已经有了对象,最简单的获取其对应Class的方法是调用Object.getClass()方法。当然这个方法只能用于继承自Object的引用类型。

Class h = "foo".getClass(); //返回String对应的Class对象

Class h = System.console().getClass(); //System.console()返回一个Console对象,它调用getClass()方法返回一个java.io.Console对象的Class对象。

enum E { A, B }

Class h = A.getClass(); //返回枚举类型E对应的Class对象


1.2 通过.class语法获取

如果没有已经实例化的对象,那么也可以通过将'.class'加到这个类型名的尾部来获取对应的Class对象。这是获取基本类型Class对象的最简方法。


  1. boolean b;  
  2. //Class h = b.getClass(); //无法编译  
  3. Class h = boolean.class//获得boolean对应的Class对象h  

Class h = java.io.PrintStream.class; //获取到java.io.PrintStream对应的Class对象

Class h = int[][][].class; //.class 也可用于获取指定类型多维数组的Class对象



1.3 Class.forName()

如果我们知道某个类的全名,也可以调用Class类的静态方法Class.forName()来获取该类对应的Class对象。forName()方法不能用于基本类型,但是可以用于使用基本类型的数组。数组类型名字的语法可参考Class.getName()

Class h = Class.forName("com.hehe.MyClass"); //获取MyClass对应的Class对象

Class hDoubleArray = Class.forName("[D"); //获取类型为基本类型double的数组对应的Class对象(与double[].class等同)

Class hStringArray = Class.forName("[[Ljava.lang.String;"); //类型为String的二维数组对应的Class对象,等同于String[][].class


1.4 基本类型包装类的类型域

除了.class方法获取主类型的Class对象外,还可以通过基本类型的包装类来获取。每个基本类型以及void类型在java.lang包里都有一个对应的包装类,这些包装类都有一个名叫TYPE的域,这个域对应了被包装的基本类型的Class对象。所以我们可以通过基本类型的包装类的TYPE域来获取其Class对象。

Class h = Double.TYPE; //获取基本类型double对应的Class对象

Class h = Void.TYPE; //获取void类型对应的Class对象


Field域包含一个类型和一个值,java.lang.reflect.Field类提供了访问给定对象的域的类型信息以及设置/获取域值信息的方法



3 Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。
一个完整方法包含的属性有:
方法上使用的注解、方法的修饰符、方法上定义的泛型参数、方法的返回值、方法名称、方法参数(泛型、注解)、方法抛出的异常。


4  Constructor 如果指定的类中没有空参数的构造函数,或者要创建的类对象需要通过指定的构造函数进行初始化。这时怎么办呢?这时就不能使用Class类中的newInstance方法了。既然要通过指定的构造函数进行对象的初始化。就必须先获取这个构造函数——Constructor。Constructor代表某个类的构造方法。

原创粉丝点击