在我的上篇文章模拟JDK动态代理实现中涉及到了反射机制,学无止境,在此系统的学习一下Java中的反射机制。首先给出Java反射机制的定义:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
从以上的描述中可以看出Java中的动态特性,那么Java属于动态语言吗?一般而言说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
尽管在这样的定义与分类下Java不是动态语言,但是它却有着一个非常突出的动态相关机制,即反射机制。通过Java反射机制可以在运行时才加载class,得到这个类的类类型的相关信息,生成实体对象、或对其成员变量设值、唤起方法。
总上,Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
类的类类型(com.lang.Class类的实例对象)
当Java虚拟机加载一个类时,会隐含的创建描述这个类的Class实例,通常把这个Class类的实例对象叫做这个类的类类型( class type),这样更易理解。下面为一个简单示例:
package com.reflact;
public class Test1 {
public static void main(String args[]){
Car car1 = new Car();
}
}
我们都知道 car1 是 Car类 的一个实例对象,那么 Car 这个类到底是什么呢? 这个 Car 类 本身也是一个对象 。在面向对象的世界里,万事万物皆对象,类也是对象,是Class类的实例对象。为了更易理解,我们把这个对象叫做该类的类类型(class type)。对比 car1 和 Car ,可以理解成car1 对象是按照Car这个类的类型来实例化的,同样Car类也有它自己的 类类型,可以通过以下三种方式获取Car类的类类型(class type):
package com.reflact;
public class Test1 {
public static void main(String args[]){
Car car1 = new Car();
Class c1 = Car.class;
Class c2 = car1.getClass();
try {
Class c3 = Class.forName("com.reflact.Car");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
c1、c2和c3都是Car类的类类型(class type),其中第一种方式和第三种方式通过类来获取类类型,第二种是通过类的实例化对象来获取类类型。那么c1、c2、c3是否相等呢?做以下测试:
package com.reflact;
public class Test1 {
public static void main(String args[]) throws ClassNotFoundException {
Car car1 = new Car();
Class c1 = Car.class;
Class c2 = car1.getClass();
Class c3 = Class.forName("com.reflact.Car");
System.out.println(c1 == c2);
System.out.println(c1 == c3);
}
}
测试结果:
按照类类型的角度很容易理解,c1、c2、c3都代表了Car类的类类型,所以它们是同一个东西,什么东西呢?上面提到类是java.lang.Class类的实例对象,也就是说c1、c2、c3都是Class类的实例对象,而一个类只能是Class类的一个实例化对象,所以c1、c2、c3是Class类的同一个实例对象,所以它们相等。
通过类的类类型创建类的实例对象
在初学Java创建对象的方式时知道有显式创建对象和隐式创建对象两类创建方式,其中显式创建对象有以下四种方式:
- 用new语句创建对象
- 运用反射手段
- 调用对象的clone()方法
- 运用反序列化手段
其中运用反射手段就是通过类的类类型来创建类的实例对象。示例如下:
Class c1 = Car.class;
try {
Car car2 = (Car)c1.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block