反射:字面意思就是反向映射。通常我们都是通过类来获取对象,而反射则正好相反,它是通过对象来获取到对象所属的类。并且可以获取到类的完整结构(包括private修饰的信息)。

反射的重要性:反射使我们不需要在编译时知道类型,而可以延迟到运行时获得对象的属性、调用对象的方法。使得 Java 语言具有了动态性。 Hibernate、Spring 等框架都是基于反射实现的,可以说没有反射就没有 JavaEE

1、是什么(What)?

编译时不知道哪个类被加载,在运行时可以动态获取对类的属性以及调用对象的方法的机制就叫反射

2、为什么(Why)?

简单的说,反射使得 Java 这种静态编译型语言具有了动态性

Java 反射机制主要提供了以下功能:

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时获取泛型信息
  • 在运行时调用任意一个对象的成员变量和方法
  • 在运行时处理注解
  • 生成动态代理

就是说,反射有能够看透 class 的能力,类的信息都是透明的(包括 private 修饰的属性或方法也可以访问)。也就是能够获取到 Class 中所有的信息

3、怎么用(How)?

反射相关的核心类

java.lang.Class:代表一个类
java.lang.reflect.Constructor:代表类的构造器
java.lang.reflect.Method:代表一个方法
java.lang.reflect.Field:代表类的成员变量

(1)Class 类:整个反射的核心类(源头)

       Class 是描述类的类的类型。例如:Person 类是每一个具体 person 对象实例的类的类型。ArrayList类是每一个ArrayList对象实例的类的类型。在 Java 中“万物皆对象”,所以 Person 类和 ArrayList 类也可以看做是一个对象,Class 就是他们类的类型(也是 Class 类本身类的类型,Class 类也可以看成是一个具体的对象)。

为什么java反射性能差 java为什么使用反射_Java反射

 

获得Class类的实例(四种方式)

(1)通过类的属性获取:类名.class
  Class clazz = String.class;
(2)通过调用类实例的 getClass() 方法:对象.getClass()
  String str = "hello";
  Class clazz = str.getClass();
(3)通过Class类的静态方法 forName() 获取:Class.forName("类名路径") (常用方式)
  Class clazz = Class.forName("java.lang.String");
(4)通过类加载器加载(不常用)
  ClassLoader cl = this.getClass().getClassLoader();
  Class clazz = cl.loadClass("类的全类名");

 

有了Classs实例就通过API可以获取到运行时类的完整结构。

(2)Constructor 类:

Constructor<T> getConstructor(Class<?>... parameterTypes)

 获取指定参数的public构造函数

Constructor<?>[]  getConstructors()

 获取所有public的构造函数

Constructor<T>   getDeclaredConstructor(<?>... parameterTypes)

 获取指定参数的所有构造函数

Constructor<?>[]  getDeclaredConstructors()

 获取所有构造函数

(3)Method类:

Method[]  getMethods()

返回当前类和父类所有的public的方法

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

返回 当前类和父类指定的public的方法

Method[] getDeclaredMethods()

返回当前类所有的方法包含private

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

返回当前类指定的方法(包含private)

(3)Field类:

Field getField(String name)

 获取当前类及父类指定名字public属性

Field[] getFields()

//获取当前类及父类所有public属性

Field getDeclaredField(String name)

 获取当前类指定名字的属性

Field[] getDeclaredFields()

//获取当前类所有的属性

几种方法的区别:

不加“s”返回的是指定参数的单个对象,加“s”的返回的是数组类型

不加“Declared”的返回的是当前类和父类中所有public修饰的对象,加“Declared”的返回的是当前类中所有的对象(包括private修饰的)

(4)其他的注解(Annotation)、泛型(Generic)等类似。这里不再赘述。

(5)使用反射的一般开发步骤:

       获取Class实例(四种方式)→ 通过Class实例获取Constructor( Field、Method等) → 通过Constructor( Field、Method等)调用相应的方法

总结:Java 中反射的重要性不言而喻,想要理解 Java 框架(如Spring)的源码,就必须学好反射,反射其实就是在运行时可以动态地获取任意一个类的所有属性、方法、注解等所有信息的完整结构Java 所有框架都可以简单理解成是由 注解+反射+设计模式的一种结合。学习反射还需要了解类的加载机制。