dcLunatic's blog

java-reflect

字数统计: 1.1k阅读时长: 3 min
2018/08/28 Share

java反射

[TOC]
反射:能够分析类能力的程序叫做反射。

概述

Java反射机制在运行状态中,也就是说是动态的,对于任意一个类,都可以知道这个类的所有属性和方法;对于任意一个对象,都可以调用它任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为反射机制。

在Java中,在运行时识别对象和类的信息的方式主要有两种,一种是传统的RTTI(Run-Time Type Identification运行时类型识别),它假定我们在编译时已经知道了所有的类型信息,编译器在编译时打开和检查.class文件;另外一种就是反射机制了,它允许我们在运行时发现和使用类的信息,运行时会打开和检查.class文件。反射也是一种RTTI的方式。

瞎扯

Class对象

类型信息,在Java中,主要是通过Class对象来保存的,它包含了与类有关的信息。Java使用Class对象来执行RTTI。每一个类都会产生一个对应的Class对象,也就是保存在.class文件。所有的类都是在对其第一次使用时,动态加载到JVM的,当程序创建一个对类的静态成员的引用时,就会加载这个类。Class对象仅在需要的时候才会加载,static初始化就是在类加载时进行的。类加载器首先会检查这个类的Class对象是否已经备加载过,如果尚未加载,默认的类加载器就会根据类型查找对应的.class文件。

想要在运行时使用类型信息,必须获取对象的Class对象的引用(可以通过Class.forName方法获得,或者使用.class获得等,两者有所差别,前者会自动初始化Class对象,后者不会)

在使用类之前,需要

  • 加载:由类加载器找到对应的字节码,创建一个Class对象;
  • 链接:验证类中的字节码,为静态域分配空间;
  • 初始化:如果该类有超类,则对其初始化,执行静态初始化器和静态初始化块。

传统的RTTI

严格的说,反射也是一种形式的RTTI,不过,一般的文档资料中把RTTI和反射分开,因为一般的,大家认为RTTI指的是传统的RTTI,通过继承和多态来实现,在运行时通过调用超类的方法来实现具体的功能(超类会自动实例化为子类,或使用instance of)。

传统的RTTI有3种实现方式:

  • 向上转型或向下转型(upcasting and downcasting),在java中,向下转型(父类转成子类)需要强制类型转换
  • Class对象(用了Class对象,不代表就是反射,如果只是用Class对象cast成指定的类,那就还是传统的RTTI)
  • instanceof或isInstance()

传统的RTTI与反射最主要的区别,在于RTTI在编译期需要.class文件,而反射不需要。传统的RTTI使用转型或Instance形式实现,但都需要指定要转型的类型,比如

1
2
3
4
public void test(Object o){
Double d = (Double)o;
//这里在编译时,就需要知道被转成的类型Double,也就是需要Double的.class文件。
}

反射

反射有的时候页成为内省(Introspection),而事实上,反射就是内省的一种方式,Java不允许在运行时改变程序结构或者类型变量的结构,但允许在运行时去探知,加载调用编译时完全未知的class,可以在运行时加载该class,生成实例对象等等。实现主要是结合了Class类和reflect包。至于反射的api以及使用方法,直接查看API就好了。

反射的性能

反射机制给予Java开发很大的灵活性,但反射机制本身也有缺点,代表性的缺陷就是反射的性能,一般来说,通过反射调用方法的效率比直接调用的效率要至少慢一倍以上。

反射与设计模式

反射的一个很重要的作用,就是在设计模式中的应用,包括在工厂模式和代理模式中的应用。

原文作者:dcLunatic

原文链接:http://dclunatic.github.io/java-reflect.html

发表日期:August 28th 2018, 10:05:05 pm

更新日期:July 11th 2021, 9:13:50 pm

版权声明:转载的时候,记得注明来处

CATALOG
  1. 1. java反射
    1. 1.1. 概述
    2. 1.2. 瞎扯
      1. 1.2.1. Class对象
    3. 1.3. 传统的RTTI
    4. 1.4. 反射
    5. 1.5. 反射的性能
    6. 1.6. 反射与设计模式