首先看下JAVA创建对象的四种方式:
- 用new关键字创建;(最常用的)
- 调用对象的clone方法;
- 利用反射,调用Class类的或者是Constructor类的newInstance()方法;
- 用反序列化,调用ObjectInputStream类的readObject()方法;
在学习 Java 反射机制前,大家应该先了解两个概念,编译期和运行期。
编译期:
是指把源码交给编译器编译成计算机可以执行的文件的过程。在 Java 中也就是把 Java 代码编成 class 文件的过程。编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作,比如检查错误。
运行期:
是把编译后的文件交给计算机执行,直到程序运行结束。所谓运行期就把在磁盘中的代码放到内存中执行起来。
Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制。

new创建实例

反射创建实例
Java 反射机制主要提供了几大功能:
在运行时判断任意一个对象所属的类。在运行时构造任意一个类的对象。在运行时判断任意一个类所具有的成员变量和方法。在运行时调用任意一个对象的方法。 动态代理(这里划重点)。java反射的实现方式
(1)通过.class
Class class = Apple.class;
(2)通过创建实例对象来获取类对象
Apple apple =new Apple(); Class class = apple.getClass();
(3) 通过包名,调用class的forName方法
Class class = Class.forName("com.hq.Apple");
实现 Java 反射机制的类都位于 java.lang.reflect 包中,java.lang.Class 类是 Java 反射机制 API 中的核心类。
java.lang.Class 类是实现反射的关键所在,Class 类的一个实例表示 Java 的一种数据类型,包括类、接口、枚举、注解(Annotation)、数组、基本数据类型和 void。Class 没有公有的构造方法,Class 实例是由 JVM 在类加载时自动创建的。
java.lang.reflect 包提供了反射中用到类,主要的类说明如下:
- Constructor 类:提供类的构造方法信息。
- Field 类:提供类或接口中成员变量信息。
- Method 类:提供类或接口成员方法信息。
- Array 类:提供了动态创建和访问 Java 数组的方法。
- Modifier 类:提供类和成员访问修饰符信息。
示例代码:
public class ReflectionTest02 { public static void main(String[] args) { try { // 加载String类的运行时对象 Class c = Class.forName("java.lang.String"); // 获取方法集合 Method[] methods = c.getDeclaredMethods(); // 遍历方法集合 for (Method method : methods) { // 打印权限修饰符,如public、protected、private System.out.print(Modifier.toString(method.getModifiers())); System.out.print(" " + method.getReturnType().getName() + " ");// 打印返回值类型名称 System.out.println(method.getName());// 打印方法名称 } } catch (ClassNotFoundException e) { } }}
有的人会问怎么去访问方法,放心java作者都想好了,来看下Method 类的常用方法:
getName() :获取该方法的名称
getParameterType():按照声明顺序以 Class 数组的形式返回该方法各个参数的类型
getReturnType()以 Class 对象的形式获得该方法的返回值类型
getExceptionTypes()以 Class 数组的形式获得该方法可能抛出的异常类型
invoke(Object obj,Object...args)利用 args 参数执行指定对象 obj 中的该方法,返回值为 Object 类型
isVarArgs()查看该方法是否允许带有可变数量的参数,如果允许返回 true,否则返回
falsegetModifiers()获得可以解析出该方法所采用修饰符的整数
具体使用这里就不一一写示例代码了,上手跑下就会了。
反射带来的问题:
- 反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。。
- 使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如Applet,那么这就是个问题了。
- 由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用:代码有功能上的错误,降低可移植性。
- 反射破坏了代码的封装性。
提高反射效率:
- 尽量不要getMethods()后再遍历筛选调用方法,而直接用getMethod(methodName)。
- 缓存需要多次动态创建一个类的实例。
- 使用高性能的反射库。
- 使用高版本JDK也很重要,反射性能一直在提高。
总结
上面说到了反射机制的几大功能,重点--动态代理(极其广泛),后续文章会着重说明。