JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为反射
静态编译:在编译时确定类型,绑定对象
动态编译:在运行时确定类型,绑定对象
Class 和 java.lang.reflect 一起对反射提供了支持,java.lang.reflect 类库主要包含了以下三个类:
-
Field :可以使用 get() 和 set() 方法读取和修改 Field 对象关联的字段;
-
Method :可以使用 invoke() 方法调用与 Method 对象关联的方法;
-
Constructor :可以用 Constructor 的 newInstance() 创建新的对象。
优点:运行期类型的判断,动态加载类,灵活
-
可扩展性:应用程序可以利用全限定名创建可扩展对象的实例,来使用来自外部的用户自定义类。
-
类浏览器和可视化开发环境:一个类浏览器需要可以枚举类的成员。可视化开发环境(如 IDE)可以从利用反射中可用的类型信息中受益,以帮助程序员编写正确的代码。
-
调试器和测试工具:调试器需要能够检查一个类里的私有成员。测试工具可以利用反射来自动地调用类里定义的可被发现的 API 定义,以确保一组测试中有较高的代码覆盖率。
缺点:性能瓶颈,比起直接调用,绕了一个圈,相当于执行了一系列解释操作,再通知JVM操作
尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。在我们使用反射技术时,下面几条内容应该牢记于心。
-
性能开销:反射涉及了动态类型的解析,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。
-
安全限制:使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。
-
内部暴露:由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用,这可能导致代码功能失调并破坏可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。
应用场景
- jdbc连接数据库时使用Class.forName()通过反射加载数据库的驱动程序
- 动态代理
- spring框架
反射就是把java类中的各种成分映射成一个个的Java对象
-
getClass() 返回一个对象的运行时类
-
forName() Class类的静态方法 (常用)
-
.class 任何数据类型(包括基本数据类型)都有一个静态的
class
属性