Java反射-1(理论)
Java反射-2(技巧)
JAVA反射-3(性能)
1. 官网解读:
1.1 什么叫做反射
反射通常是被程序使用,这些程序需要能够检查或修改运行在JVM的应用程序的运行时行为。
1.1.1 反射的优点
可扩展功能
应用程序可使用 完全限定的名称 创建 可扩展对象的实例 来使用外部或用户定义的类。
1.1.2 反射的缺点
性能开销
由于反射设计到动态解析的类型,因此无法执行某些JVM的优化。因此,反射操作性能低于非反射操作,应该避免在性能敏感的程序中频繁调用。
内部暴露
由于反射允许代码执行非法的操作在非反射代码中,例如,访问私有字段或方法,因此使用反射可能导致意外的副作用,可能导致代码功能失常并可能失去可移植性,反射代码打破了抽象,因此使用反射的代码可能会在系统升级后表现异常。
安全限制
反射需要运行时的权限,因此无法在安全管理器下运行,必须受限于安全的上下文中运行,例如Applet,只是一个重要的考虑因素。
1.2 Class对象的学习
每一种对象都是引用类型或者基本数据类型。
对于每一种对象的类型,JVM提供了一个不可变对象,java.lang.Class
不可变对象提供了检查运行时对象 成员和类型信息的方法。还提供了创建类和对象的功能。最重要的,他是反射API的入口点。
1.2.1 getClass()语法
对象是可用的情况:得到它的class
对象最简单的方法就是object.getClass()
,当然,这仅仅适用于继承与object
下的类。
public static void main(String[] args) {
Heap heap = new Heap();
System.out.println("普通对象的返回类型:" + heap.getClass());
//注意,声明类型 xx=new 实际类型();返回的是实际类型
Set set = new HashSet();
System.out.println("实际类型的返回类型:" + set.getClass());
//注意数据的返回类型
byte[] bytes = new byte[1024];
System.out.println("数组的返回类型:" + bytes.getClass());
System.out.println("枚举的返回类型:"+enums.RED.getClass());
}
执行结果:
1.2.2 .class语法
If the type is available but there is no instance then it is possible to obtain a Class
by appending ".class"
to the name of the type.
如果类型可用但没有对象:可以通过Class
附带的".class"
名称获取Class
对象。
1.2.3 Class.forName()语法
If the fully-qualified name of a class is available, it is possible to get the corresponding Class
using the static method Class.forName()
. This cannot be used for primitive types.
一个类的完全限定名可用:可以使用静态方法Class.forName()
去创建Class
对象,不能用于基本数据类型。
1.2.4 Type用法
对于基本数据类型,.class
方式是一种便捷的、首选的方式来获取Class
对象。然而有另一种方法去创建Class
对象。每一种基本数据类型和void
都有一个包装类java.lang
。用于将基本数据类型装箱。每一个包装类包含一个TYPE
的域,该字段等于Class
被包装的基本类型。
对于非基本数据类型,返回的是编译错误。
测试代码:
public static void main(String[] args) {
Class dobClass = Double.TYPE;
//Void也有封装类型!
Class voidClass=Void.TYPE;
System.out.println(dobClass);
System.out.println(voidClass);
}
输出结果:
1.2.5 返回Class的方法
有几个Reflection API
可以返回classes
对象,但只有Class
对象直接或者间接获取的情况下。
下面getclasses()
知识点需要用到成员内部类,可以先了解下。
public static void main(String[] args) {
//返回作为类成员的所有公共类,接口和枚举,包括继承的成员。
Class<?>[] dobClass = HashMap.class.getClasses();
for (Class c : dobClass) {
System.out.println("类或其父类所有成员public内部类:" + c);
}
Class<?>[] declaredClasses = HashMap.class.getDeclaredClasses();
for (Class c1 : declaredClasses) {
System.out.println("本类所有成员内部类:"+c1);
}
}
执行结果:
下面这个类实现了:获取类的声明组件,包括修饰符,泛型类型参数,实现的接口和继承路径。由于 Class
实现了java.lang.reflect.AnnotatedElement
接口,因此还可以查询运行时注释。
public class Reflect {
public static void main(String[] args) {
try {
Class<?> c = Class.forName("Algorithm.Outer");
out.println("Class:" + c.getCanonicalName());
out.println("访问修饰符:" + Modifier.toString(c.getModifiers()));
TypeVariable<? extends Class<?>>[] tv = c.getTypeParameters();
if (tv.length != 0) {
for (TypeVariable t : tv) {
out.println("泛型类型:" + t.getName());
}
out.println();
} else {
out.println("--无泛型的参数类型--");
}
//获取接口类型
Type[] intfs = c.getGenericInterfaces();
if (intfs.length != 0) {
for (Type intf : intfs)
out.println("接口类型:" + intf.toString());
} else {
out.format("--无接口类型--");
}
//将父类保存到List集合里面
List<Class> l = new ArrayList<Class>();
printAncestor(c, l);
if (l.size() != 0) {
for (Class<?> cl : l)
//打印父类名称
out.println("父类名称:" + cl.getCanonicalName());
} else {
out.format("--没有父类名称--");
}
Annotation[] ann = c.getAnnotations();
if (ann.length != 0) {
for (Annotation a : ann)
out.println("注释信息:" + a.toString());
} else {
out.format(" --没有注释信息--");
}
// production code should handle this exception more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
//递归方法,返回所以的父类类型,直至Object类
private static void printAncestor(Class<?> c, List<Class> l) {
Class<?> ancestor = c.getSuperclass();
if (ancestor != null) {
l.add(ancestor);
printAncestor(ancestor, l);
}
}
}
由于数组是运行时对象,因此所有的类型信息都由JVM定义的。特别是,数组实现Clonable
和java.io.Serializable
,他的直接超类总是Object
;
2. 源码实现
/**
* XML转化为Object
*
* @throws IllegalAccessException
* @throws InstantiationException
*/
public final static void objectFromXml(Object obj, String xml) throws InstantiationException,
IllegalAccessException {
Element root = parseXml(xml);
Class clazz = obj.getClass();
do
objectFromXml(obj, clazz, root);
while ((clazz = clazz.getSuperclass()) != null);
}
public final static void objectFromXml(Object obj, Class clazz, Element root)
throws InstantiationException, IllegalAccessException {
if (root == null || (root.elements()).size() == 0) {
return;
}
// 获取私有变量
Field[] fields = clazz.getDeclaredFields();
// 暴力解除
Field.setAccessible(fields, true);
for (Field field : fields) {
// field.getModififers()获取
String name = field.getName();
Class type = field.getType();
// 内省机制,证明该字段在此对象里面是可编辑的
if ((!Modifier.isStatic(field.getModifiers())) && PropertyUtils.isWriteable(obj, name)) {
// 获取属性的类型
// 判断类型来自哪里(可指定的)
if (type.isAssignableFrom(List.class)) {
// 获取属性的Type类型
Type genericType = field.getGenericType();
List<Element> elements = root.elements(name);
// 根本没有这个节点的话,那么不予赋值
if ((elements == null) && elements.size() == 0) {
continue;
}
// 判断该Type类型是不是参数化的文件
if (genericType instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) genericType;
Class parameterizedClass = (Class) pt.getActualTypeArguments()[0];
// 想当与new了一个对象
List lists = new ArrayList();
for (Element ele : elements) {
Object object = parameterizedClass.newInstance();
// 判断泛型是否是基本数据对象
if (isPrimitiveType(parameterizedClass)) {
// 将element里面的对象赋值到反射出的对象里面
object = setObjectValue(object, ele.getText());
} else {
// 迭代,无论执行都少次,最后一次,将正确的值返回
objectFromXml(object, parameterizedClass, ele);
}
lists.add(object);
}
// 将obj对象的List集合赋值
field.set(obj, lists);
}
} else {
// 若不包含改节点
String text = root.elementText(name);
if (null != text) {
try {
if (isPrimitiveType(field.getType())) {
setObjectValue(obj, field, text);
} else {
// 创建改属性的object、class、节点
Object fieldObject = type.newInstance();
Element fieldRoot = root.element(name);
objectFromXml(fieldObject, type, fieldRoot);
// 为obj对象里面的field属性赋予fieldObject对象的值
field.set(obj, fieldObject);
}
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
Object转化为XML:
public static void ObjectToXML(Object obj, Element root) throws IllegalArgumentException,
IllegalAccessException, SecurityException, NoSuchMethodException,
InvocationTargetException, ParseException {
// 创建Class对象
Class clazz = obj.getClass();
do
ObjectToXML(obj, clazz, root);
while ((clazz = clazz.getSuperclass()) != null);
}
public static void ObjectToXML(Object obj, Class clazz, Element root)
throws IllegalArgumentException, IllegalAccessException, SecurityException,
NoSuchMethodException, InvocationTargetException, ParseException {
Field[] fields = clazz.getDeclaredFields();
Field.setAccessible(fields, true);
for (Field field : fields) {
// 判断是否是List
Class fieldClass = field.getType();
String name = field.getName();
Object descObj = field.get(obj);
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (descObj == null) {
if (isPrimitiveType(fieldClass)) {
descObj = "";
} else {
continue;
}
}
if (fieldClass.isAssignableFrom(List.class)) {
Type genType = field.getGenericType();
if (genType instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) genType;
Class paramClass = (Class) pt.getActualTypeArguments()[0];
System.out.println("List的泛型对象:" + paramClass);
String paramText = null;
// 判断参数的类型
List paramList = (ArrayList) descObj;
// foreach循环前需要加判断
if (paramList == null || paramList.size() == 0 || paramClass == null) {
continue;
}
Method m = fieldClass.getDeclaredMethod("size", new Class[0]);
Integer size = (Integer) m.invoke(descObj, new Object[0]);
root.addElement(name + "_NUM").setText(size + "");
Element childEle = null;
// 获取list集合里面的对象
for (Object object : paramList) {
if (isPrimitiveType(paramClass)) {
childEle = root.addElement(name);
root.addText(String.valueOf(getObjectValue(object, paramClass)));
} else {
childEle = new DOMElement(name);
ObjectToXML(object, childEle);
root.add(childEle);
}
}
}
} else if (fieldClass.isAssignableFrom(Map.class)) {
Map map = (Map) descObj;
Type mapGentype = field.getGenericType();
// 若是泛型类型
if (mapGentype instanceof ParameterizedType) {
ParameterizedType mapPt = (ParameterizedType) mapGentype;
Class keyClass = (Class) mapPt.getActualTypeArguments()[0];
Type valueType = mapPt.getActualTypeArguments()[1];
Class valueClass = (Class) valueType;
Iterator<Map.Entry> it = map.entrySet().iterator();
// 默认Key是基本类型
while (it.hasNext()) {
Entry entry = it.next();
Object keyObject = entry.getKey();
System.out.println("map的key:" + keyObject);
Object valueObject = entry.getValue();
System.out.println("map的value:" + valueObject.getClass());
Element mapEle = null;
// 设置到XML里面
String keyName = null;
if (isPrimitiveType(keyClass)) {
keyName = (String) getObjectValue(keyObject, keyClass);
} else {
continue;
}
if (isPrimitiveType(valueClass)) {
mapEle = root.addElement(keyName); // 创建节点
mapEle.setText((String) getObjectValue(valueObject, valueClass));
} else {
// 若是对象
mapEle = new DOMElement(keyName);
Element childEle = null;
if (valueObject instanceof List) {
// 若是list集合,直接继续赋值
List mapList = (ArrayList) valueObject;
if (mapList == null || map.size() == 0) {
continue;
}
Class cls = mapList.get(0).getClass(); // 获取List对象的泛型的对象类型
for (Object object : mapList) {
if (isPrimitiveType(cls)) {
childEle = root.addElement(name);
mapEle.addText(String.valueOf(getObjectValue(object, cls)));
} else {
childEle = new DOMElement(name);
ObjectToXML(object, childEle);
mapEle.add(childEle);
}
}
} else {
ObjectToXML(valueObject, mapEle);
}
root.add(mapEle);
}
}
}
} else {
// 属性字段是否是普通对象普通对象
Element childEle = new DOMElement(name);
if (isPrimitiveType(fieldClass)) {
childEle.setText(String.valueOf(getObjectValue(descObj, fieldClass)));
} else {
ObjectToXML(descObj, childEle);
}
root.add(childEle);
}
}
}
工具类:
/**
* 解析Element节点
*
* @param xml
* @return
*/
private static Element parseXml(String xml) {
Element root = null;
try {
Document doc = DocumentHelper.parseText(xml);
root = doc.getRootElement();
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return root;
}
/**
*
* @param object
* 目标对象
* @param field
* 目标对象的反射字段
* @param text
* 需要反射字段赋予的值
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws NumberFormatException
* @throws ParseException
*/
private static void setObjectValue(Object object, Field field, String text)
throws NumberFormatException, IllegalArgumentException, IllegalAccessException,
ParseException {
if (object == null || field == null) {
return;
}
// 获取反射字段的Class对象。getClass()返回的是Field对象
Class fieldClass = field.getType();
if (fieldClass.isAssignableFrom(long.class) || fieldClass.isAssignableFrom(Long.class)) {
field.set(object, Long.valueOf(text));
} else if (fieldClass.isAssignableFrom(int.class)
|| fieldClass.isAssignableFrom(Integer.class)) {
field.set(object, Integer.valueOf(text));
} else if (fieldClass.isAssignableFrom(double.class)
|| fieldClass.isAssignableFrom(Double.class)) {
field.set(object, Double.valueOf(text));
} else if (fieldClass.isAssignableFrom(float.class)
|| fieldClass.isAssignableFrom(Float.class)) {
field.set(object, Float.valueOf(text));
} else if (fieldClass.isAssignableFrom(boolean.class)
|| fieldClass.isAssignableFrom(Boolean.class)) {
field.set(object, Boolean.valueOf(text));
} else if (fieldClass.isAssignableFrom(Date.class)) {
DateFormat df = new SimpleDateFormat("yyyyMMddhhmmss");
field.set(object, df.parse(text));
} else if (fieldClass.isAssignableFrom(String.class)) {
field.set(object, text);
} else if (fieldClass.isArray()) {
field.set(object, text.toCharArray());
} else {
field.set(object, text);
}
}
private static Object getObjectValue(Object object, Class paramsClass)
throws IllegalArgumentException, IllegalAccessException, ParseException {
if (object == null) {
return null;
}
if (paramsClass.isAssignableFrom(Date.class)) {
DateFormat dt = new SimpleDateFormat("yyyyMMddhhmmss");
object = dt.format(object);
} else if (paramsClass.isAssignableFrom(Double.class)
|| paramsClass.isAssignableFrom(double.class)) {
// double类型格式化
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(8);
object = nf.format((Double) object);
} else {
object = String.valueOf(object);
}
return object;
}
// 返回泛型(反射的new)对象的值 。
private static Object setObjectValue(Object object, String text) {
if (object == null)
return null;
Class clazz = object.getClass();
if (clazz.isAssignableFrom(long.class) || clazz.isAssignableFrom(Long.class)) {
object = Long.valueOf(text);
} else if (clazz.isAssignableFrom(int.class) || clazz.isAssignableFrom(Integer.class)) {
object = Integer.valueOf(text);
} else if (clazz.isAssignableFrom(double.class) || clazz.isAssignableFrom(Double.class)) {
object = Double.valueOf(text);
} else if (clazz.isAssignableFrom(float.class) || clazz.isAssignableFrom(Float.class)) {
object = Float.valueOf(text);
} else if (clazz.isAssignableFrom(boolean.class) || clazz.isAssignableFrom(Boolean.class)) {
object = Boolean.valueOf(text);
} else if (clazz.isAssignableFrom(Date.class)) {
DateFormat df = new SimpleDateFormat("yyyymmddhhmiss");
try {
object = df.parse(text);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
object = text;
}
return object;
}
// 将其超类删除
private static boolean isPrimitiveType(Class<?> clazz) {
boolean isPrimitiveOrPrimitiveClass = Boolean.valueOf(false);
if ((!clazz.isAssignableFrom(Object.class))
&& ((clazz.isPrimitive() || clazz.isAssignableFrom(Double.class)
|| clazz.isAssignableFrom(Float.class)
|| clazz.isAssignableFrom(Long.class)
|| clazz.isAssignableFrom(Integer.class)
|| clazz.isAssignableFrom(Boolean.class)
|| clazz.isAssignableFrom(Byte.class)
|| clazz.isAssignableFrom(Character.class)
|| clazz.isAssignableFrom(Short.class)
|| clazz.isAssignableFrom(String.class) || clazz
.isAssignableFrom(Date.class)))) {
isPrimitiveOrPrimitiveClass = Boolean.valueOf(true);
}
return isPrimitiveOrPrimitiveClass;
}