目录:
前言: 这里只讲简单的语法, 不讲应用, 帮助理解JDBC的加载驱动, 以及明白框架原理, 如果想设计框架还要进一步学习.
正文:
1. 反射 Reflectoin
反射机制是Java的一个非常重要的机制。一些著名的应用框架都使用了此机制。
例如,
struts, spring, hibernate
android app的界面设计器 …
在设计应用框架时一般都要使用反射,它是Java的一个非常优越的特性。
2. 从Class说起
java.lang.Class
它是Java语法的一个基础类,用于描述一个class对象。
在文件系统中,class以文件的形式存在 Student.class
在运行时的JVM中,该*.class文件被加载到内存中成为一个对象,对象的类型就是java.lang.Class
例如,
Class cls = Student.class;
System.out.println("Name: " + cls.getName());
其中,cls这个对象就是这个Class的描述。
再例如,
Student obj = new Student();
Class cls = obj.getClass();
其中,obj是一个对象,obj.getClass()则是获取它的Class描述。
3. Class有什么用
用于判断一个运行时对象的类型
public static void test1(Object obj)
{
Class cls = Student.class;
if(cls.isInstance(obj))
{
}
}
其中,cls.Instance(obj)意思是判断obj是否为my.Student的一个实例。
另一种写法,也可以判断一个运行时对象的类型
public static void test2(Object obj)
{
String clsName = obj.getClass().getName();
if(clsName.equals("my.Student"))
{
}
}
其中,obj.getClass()可以得到对象obj的具体类型
小结:
应用展示
让一个对Student对象可以与String和Integer进行比较。
public boolean equals(Object obj)
{
// 与一个String对象比较
if(String.class.isInstance(obj))
{
String other = (String)obj;
return other.equals(this.name);
}
// 与一个Integer对象比较
if(Integer.class.isInstance(obj))
{
Integer other = (Integer)obj;
return this.id == other;
}
return false;
}
4. Reflection
给定一个*.class文件中,我们可以得到以下信息:
类名 (含package路径)
函数 (名称,参数类型,返回值)
域 (名称,类型)
实现的接口 (interfaces)
… …
使用java.lang.reflect.*下的类来实现。。。
注意:不需要源文件,只需要*.class文件
动态加载一个*.class文件到内存:
// 加载my/Student.class
Class cls = Class.forName("my.Student");
// 获取函数列表
Method[] methods = cls.getMethods();
// 获取成员变量列表
Field[] fields = cls.getFields();
也就是说,虽然我们不知道Student类的代码,但是这个class文件本身可以反映(reflect)出这些信息。。。
结论:通过Reflection机制,我们可以直接从class文件反推出它有哪个成员变量、有哪些函数。
例1 遍历Method
已经函数名,找到对象的 Method(如何获取函数名? 看使用文档, 遍历函数列表, 打电话问设计者)
Class cls = Class.forname("my.Student");
String methodName = "setId";
// 获取所有Method列表,顺序比对
Method[] methods = cls.getMethods();
for(Method m : methods)
{
if(m.getName().equals(methodName))
{
break;
}
}
例2 查找Method
已经函数名,参数列表,寻找Method
Class cls = Class.forname("my.Student");
String methodName = "setId";
Class[] parameterTypes = { int.class };
Method m = cls.getMethod(methodName,parameterTypes);
例3 Reflection的运用
// 创建一个实例, 要求有一个不带参数的构造函数
Object obj = cls.newInstance();
// 找到method
Class[] parameterTypes = { int.class };
Method m1 = cls.getMethod("setId",parameterTypes);
// 调用method
Object[] paramters = { 123 };
m1.invoke(obj, paramters);
更多细节 Class Loader
Class.forName(…) 可以加载一个class文件。(所以创建Class类有三种方法了)
(1)由谁负责加载?
由Class Loader负责加载,具体地讲,JVM提供了一个内置的 bootstrap class loader。
(2)从哪里加载?
从classpath下寻找class,以及该class里面import的class
小结
1.Reflection: 从*.class文件中,可以reflect得到它的描述信息:类名,函数名等
2.通过Class,可以newInstance()创建一个实例instance
3.通过Class,可以找到它的某个Method,进而就可以调用这个函数。(有函数名, 有实例了不就可以调用了??)
4.需要知道Class Loader的存在及其作用
如果不是为了设计框架, 学这么多应该也就够了, 毕竟普通的开发一般不会使用到反射, 现在主流的框架也是使用反射机制, 学习框架的时候可以思考一下, 自己如何通过反射设计一个这样的框架来.