编程开发人员最早反映了这一概念Smith于1982年提出,主要是指应用程序访问、测试和修改其状态和行为的能力。这一概念的提出立即引起了编程界的极大关注,随后开展了各种研究工作,导致了编程创新,并出现了各种支持反射机制的面向对象语言。许多优秀的开源框架都是通过反射完成的,比如许多最初的注释框架,这就是为什么它被称为框架设计的灵魂。Java的反射(reflection)机制是指在程序运行状态下,可以构建任何类别的对象,了解任何类别的类别,了解任何类别的成员变量和方法,调用任何对象的属性和方法。这种动态访问程序信息和动态调用对象的功能称为Java语言的反射机制。反射被认为是动态语言的关键。在Java编程语言中,反射是一种强大的工具,是一种实现抽象编程的方法,可以使代码句子更加灵活,大大提高代码运行时的装配能力。Java反射机制的存在主要是为了提供以下功能: 判断运行中任何对象的类别;构建运行中任何类别的对象;判断运行中任何类别的成员变量和方法;调用运行中任何对象的方法;生成动态代理。
有时我们说某种语言有很强的动态性,有时我们区分不同的动态和静态技术和实践。我们朗朗上口动态绑定(dynamic binding)、动态链接(dynamic linking)、动态加载(dynamic loading)等。然而“动态”事实上,这个词并没有绝对和普遍的严格定义,有时甚至就像导入编程领域一样,就像一千个人心中有一千个哈姆雷特一样。一般来说,当开发者社区谈到动态语言时,一个大致同意的定义是:“该语言称为动态语言,允许在程序运行时改变程序结构或变量类型”。从这个角度来看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
尽管在这样的定义和分类下Java不是动态语言,但它有一个非常突出的动态相关机制:Reflection。这个词的意思是“反射、图像、倒影”,Java中使用的是我们在操作过程中可以加载、探测和使用完全未知的clases。换句话说,Java程序可以在运行过程中加载一个class,了解其完整的结构(但不包括methods定义),并生成其对象实体,或设置其fields,或唤起其methods。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反思)。Reflection和introspection是常被提及的两个术语。
以下是通过反射过泛型检查的简单例子:
编译期使用泛型,编译后擦除泛型(消失)。因此,可以通过反射来检查泛型
测试类:
控制台输出:
aaa
bbb
100
当我们写完一个的时候Java项目结束后,每个Java文件都会被编译成一个.class文件,这些class对象承载了这一类的所有信息,包括父类、接口、结构函数、方法、属性等,这些class文件在程序运行时会被classloader加载到虚拟机中。Java虚拟机在内存中自动生成Class对象,当一个类被加载时。我们以new的形式创建对象实际上是通过这些class创建的,但这个过程对我们来说是不透明的。反射的工作原理是使用Class.java、Constructor.java、Method.java、Field.在程序运行过程中,java动态访问和修改任何类型的行为和状态。java是反射机制所需的主要类别.Class类和Java.lang.constructor类和Field类在reflect包中、Method类和Parameter类。Class类是一个特殊类,是反射机制的基础。Class类的对象表示,Java程序中的类或接口正在运行,即任何类被加载时即将到来.class文件(字节码文件)读入内存时,会自动创建java.lang.Class对象。Class类没有公共结构方法,其对象是JVM在加载类时通过调用类加载器中的defineClass()创建的,因此无法显式创建Class对象。只有通过这个Class对象,才能获得对象的其他信息。
我们必须承认java中的反射机制是一把双刃剑,它不仅大大提高了代码运行时的装配能力和代码灵活性,而且在性能上也带来了弱点。Java虚拟机无法优化这些动态代码,因为Java反射机制包含了一些动态类型。在安全方面,反射的使用通常要求程序的运行没有安全限制。如果一个程序对安全有一定的要求,反射就不能满足要求。反射允许代码执行一些通常不允许的操作,因此使用反射可能会导致意想不到的后果。反射代码破坏了Java程序结构的抽象性,因此当程序运行平台发生变化时,代码的效果会与以前不同,因为抽象的逻辑结构无法识别。然而,反射的基本语法仍然支持我们能够自己写出优秀的框架。同时,反射技术也是学习安卓插件技术和Hook技术必不可少的!