[align=center][size=xx-large][b]Class加载机制——反射机制[/b][/size][/align]
[size=medium]最近学习了动态加载Class.forName,知道了动态加载的应用流程,觉得这是一个很棒的功能,可以让Class动态加载,并且可以newInstance实例,invoke方法;在游戏中角色的加入、SSH框架的内部实现、Eclipse的自动补全功能等等都应用到了动态加载机制;Java动态加载太神奇了。但今天走进JVM内部一看才发现,哇,原来就是这样一回事!
以下是JVM加载Class的内存分布图:[/size]
[align=center]
[img]http://dl2.iteye.com/upload/attachment/0084/8480/8c54c247-48b0-3c0a-889b-a408dd5a2098.jpg[/img]
[/align]
[size=medium]看到这个图是不是能够联想到Java对象引用的内存分布图呢?[/size]
[align=center]
[img]http://dl2.iteye.com/upload/attachment/0084/8485/0211af6d-8660-39a9-8d3d-cd0f77e59561.jpg[/img]
[/align]
[size=medium] 这样对比就很容易理解到,JVM将Class文件也作为了一个个的对象存在于内存中,因此当我们通过反射去获取其中的元素时,就和我们平时使用一个普通Java对象一样方便。
[b]重点:Class文件在JVM中是以对象的形式存在!这就是反射的内部原理![/size][/b]
[size=medium]以下是反射的实例:[/size]
[size=medium]运行结果:[/size]
[quote]
通过反射拿到对象中的值为:正在吃饭!
//Student类
package com.sean.ioc
public class Student{
//类的属性
public String Sno;
private String Sname;
private String Ssex;
private int Sage;
private String Sclass;
private String Smajor;
//类的构造方法
public Student{}
//类的方法
public String doSomething() {}
public String getSno() {}
public void setSno() {}
public String getSname() {}
public void setSname() {}
public String getSsex() {}
public void setSsex() {}
public int getSage() {}
public void setSage() {}
public String getSclass() {}
public void setSclass() {}
public String getSmajor() {}
public void setSmajor() {}
}
[/quote]
[size=large][b]疑问:拿到方法后可以再拿里面的过程吗?
欢迎大家批指正!
[/b][/size]
[size=medium]最近学习了动态加载Class.forName,知道了动态加载的应用流程,觉得这是一个很棒的功能,可以让Class动态加载,并且可以newInstance实例,invoke方法;在游戏中角色的加入、SSH框架的内部实现、Eclipse的自动补全功能等等都应用到了动态加载机制;Java动态加载太神奇了。但今天走进JVM内部一看才发现,哇,原来就是这样一回事!
以下是JVM加载Class的内存分布图:[/size]
[align=center]
[img]http://dl2.iteye.com/upload/attachment/0084/8480/8c54c247-48b0-3c0a-889b-a408dd5a2098.jpg[/img]
[/align]
[size=medium]看到这个图是不是能够联想到Java对象引用的内存分布图呢?[/size]
[align=center]
[img]http://dl2.iteye.com/upload/attachment/0084/8485/0211af6d-8660-39a9-8d3d-cd0f77e59561.jpg[/img]
[/align]
[size=medium] 这样对比就很容易理解到,JVM将Class文件也作为了一个个的对象存在于内存中,因此当我们通过反射去获取其中的元素时,就和我们平时使用一个普通Java对象一样方便。
[b]重点:Class文件在JVM中是以对象的形式存在!这就是反射的内部原理![/size][/b]
[size=medium]以下是反射的实例:[/size]
package com.sean.ioc;
/**
* 学生类
*
* @author Sean 2013-5-21
*
*/
public class Student {
public String Sno;
private String Sname;
private String Ssex;
private int Sage;
private String Sclass;
private String Smajor;
public String getSno() {
return Sno;
}
public void setSno(String sno) {
Sno = sno;
}
public String getSname() {
return Sname;
}
public void setSname(String sname) {
Sname = sname;
}
public String getSsex() {
return Ssex;
}
public void setSsex(String ssex) {
Ssex = ssex;
}
public int getSage() {
return Sage;
}
public void setSage(int sage) {
Sage = sage;
}
public String getSclass() {
return Sclass;
}
public void setSclass(String sclass) {
Sclass = sclass;
}
public String getSmajor() {
return Smajor;
}
public void setSmajor(String smajor) {
Smajor = smajor;
}
public String doSomething() {
return "正在吃饭!";
}
}
package com.sean.ioc;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Java 反射机制
*
* @author Sean 2013-5-21
*
*/
public class Reflect {
/**
* 测试
*
* @param args
*/
public static void main(String[] args) {
Object stu = forReflect("com.sean.ioc.Student");
}
/**
* 反射机制
*
* @param string
* 对象
* @return
*/
private static Object forReflect(String className) {
Class thisClass = null;
try {
thisClass = Class.forName(className);
} catch (Exception e) {
e.printStackTrace();
}
getThisClassProperty(thisClass);
System.out.println("//Student类");
getThisClassName(thisClass);
System.out.println("//类的属性");
getThisClassFields(thisClass);
System.out.println("//类的构造方法");
getThisClassConstrName(thisClass);
System.out.println("//类的方法");
getThisClassMethods(thisClass);
System.out.println();
System.out.println("}");
return null;
}
/**
* 通过类反射出对象中的处理结果
*/
private static void getThisClassProperty(Class thisClass) {
try {
Object obj = thisClass.newInstance();
Method method = thisClass.getMethod("doSomething", null);
String sth = (String) method.invoke(obj, null);
System.out.println("\n\n通过类反射出对象中的处理结果:" + sth + "\n\n");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取这个类名
*
* @param thisClass
*/
private static void getThisClassName(Class thisClass) {
System.out.println(thisClass.getPackage());
System.out.println();
System.out.println("public class " + thisClass.getSimpleName() + "{");
}
/**
* 获取属性
*
* @param thisClass
*/
private static void getThisClassFields(Class thisClass) {
if (thisClass.getDeclaredFields().length > 0) {
Field[] field = thisClass.getDeclaredFields();
for (Field i : field) {
System.out
.println(i.toString().substring(0,
i.toString().indexOf(" "))
+ " "
+ i.getType()
.toString()
.substring(
i.getType().toString()
.lastIndexOf(".") + 1)
+ " " + i.getName() + ";");
// 只能拿到public 访问类型的属性吗?
}
}
}
/**
* 获取这个类的构造方法
*
* @param thisClass
*/
private static void getThisClassConstrName(Class thisClass) {
try {
Constructor[] con = thisClass.getConstructors();
for (Constructor i : con) {
System.out.println(i.toString().substring(0,
i.toString().indexOf(" "))
+ " "
+ i.getName().substring(
i.getName().lastIndexOf(".") + 1) + "{}");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取类中的方法
*
* @param thisClass
*/
private static void getThisClassMethods(Class thisClass) {
Method[] method = thisClass.getDeclaredMethods();
for (Method i : method) {
System.out.println(i.toString().substring(0,
i.toString().indexOf(" "))
+ " "
+ i.getReturnType()
.toString()
.substring(
i.getReturnType().toString()
.lastIndexOf(".") + 1)
+ " "
+ i.getName() + "() {}");
// 拿到方法后可以再拿里面的过程吗?
}
}
}
[size=medium]运行结果:[/size]
[quote]
通过反射拿到对象中的值为:正在吃饭!
//Student类
package com.sean.ioc
public class Student{
//类的属性
public String Sno;
private String Sname;
private String Ssex;
private int Sage;
private String Sclass;
private String Smajor;
//类的构造方法
public Student{}
//类的方法
public String doSomething() {}
public String getSno() {}
public void setSno() {}
public String getSname() {}
public void setSname() {}
public String getSsex() {}
public void setSsex() {}
public int getSage() {}
public void setSage() {}
public String getSclass() {}
public void setSclass() {}
public String getSmajor() {}
public void setSmajor() {}
}
[/quote]
[size=large][b]疑问:拿到方法后可以再拿里面的过程吗?
欢迎大家批指正!
[/b][/size]