反射

Wu Jun 2020-01-04 08:43:49
Categories: > > Tags:

反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。

反射允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。

反射的核心是 JVM 在运行时才动态加载类或调用方法/访问属性,它不需要事先知道运行对象是谁。

1 反射的作用

反射机制可以用来:

2 反射的优缺点

2.1 反射的优点

2.2 反射的缺点

反射机制对于编写系统程序来说极其实用,但是通常不适于编写应用程序。

反射是很脆弱的,即编译器很难帮助人们发现程序中的错误。任何错误只能在运行时才被发现,并导致异常。

3 基本运用

反射相关的类一般都在 java.lang.relfect 包里,java.lang.reflect 类库主要包含了以下三个类:

3.1 获得 Class 对象

获得类对象的方式有三种:

  1. 类型.class
    例如:Class<?> class = String.class
  2. 调用对象getClass()
    例如:Class<?> class = “hello”.getClass()
  3. Class.forName()
    例如:Class<?> class = Class.forName(“java.lang.String”)

虚拟机为每个类管理一个 Class 对象。因此,可以利用 == 运算符实现两个类对象比较的操作。

3.2 判断是否为某个类的实例

  1. 一般用 instanceof 关键字来判断是否为某个类的实例。
  2. 同时也可用反射中 Class 对象的 isInstance() 方法来判断:class.isInstance(obj);

3.3 创建实例

  1. 调用 Class 类的 newInstance()
Class<?> c = String.class;
Object str = c.newInstance();
  1. 调用 Constructor 类的 newInstance()
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
System.out.println(obj);

3.4 获取方法

获取某个 Class 对象的方法集合

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

3.5 获取构造器信息

获取某个 Class 对象的构造器集合,与获取方法用法相似

3.6 获取类的域

3.7 调用方法

利用 Method 类中的 invoke 方法,调用任意方法。

public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException

3.8 获取修饰符

Modifier 类的静态方法分析 getModifiers 返回的整型数值,isPublish、isPrivate 或 isFinal 判断方法或构造器是否是 public、private 或 final。

3.9 利用反射创建数组

java.lang.reflect 包中的 Array 类允许动态地创建数组。

public static void testArray() throws ClassNotFoundException {
    Class<?> cls = Class.forName("java.lang.String");
    Object array = Array.newInstance(cls,25);
    //往数组里添加内容
    Array.set(array,0,"hello");
    Array.set(array,1,"Java");
    //获取某一项的内容
    System.out.println(Array.get(array,0));
}