Java反射-1(理论)
【Java反射-1(理论)】Java反射-1(理论)
Java反射-2(技巧)
JAVA反射-3(性能)
什么叫做反射?反射有什么用?这篇文章会娓娓道来。1. 官网解读: 1.1 什么叫做反射
咱们就先从反射官网入手,开始解读下吧。
Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine.反射通常是被程序使用,这些程序需要能够检查或修改运行在JVM的应用程序的运行时行为。
1.1.1 反射的优点
Extensibility Features可扩展功能
An application may make use of external, user-defined classes by creating instances of extensibility objects using their fully-qualified names.
应用程序可使用 完全限定的名称 创建 可扩展对象的实例 来使用外部或用户定义的类。
1.1.2 反射的缺点
Performance Overhead性能开销
Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
由于反射设计到动态解析的类型,因此无法执行某些JVM的优化。因此,反射操作性能低于非反射操作,应该避免在性能敏感的程序中频繁调用。
Exposure of Internals内部暴露
Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.
由于反射允许代码执行非法的操作在非反射代码中,例如,访问私有字段或方法,因此使用反射可能导致意外的副作用,可能导致代码功能失常并可能失去可移植性,反射代码打破了抽象,因此使用反射的代码可能会在系统升级后表现异常。
Security Restrictions安全限制
Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet.
反射需要运行时的权限,因此无法在安全管理器下运行,必须受限于安全的上下文中运行,例如Applet,只是一个重要的考虑因素。
1.2 Class对象的学习
Every type is either a reference or a primitive.每一种对象都是引用类型或者基本数据类型。
For every type of object, the Java virtual machine instantiates an immutable instance of对于每一种对象的类型,JVM提供了一个不可变对象,java.lang.Class
which provides methods to examine the runtime properties of the object including its members and type information.Class
also provides the ability to create new classes and objects. Most importantly, it is the entry point for all of the Reflection APIs.
java.lang.Class
不可变对象提供了检查运行时对象 成员和类型信息的方法。还提供了创建类和对象的功能。最重要的,他是反射API的入口点。1.2.1 getClass()语法
If an instance of an object is available, then the simplest way to get its对象是可用的情况:得到它的Class
is to invokeObject.getClass()
. Of course, this only works for reference types which all inherit fromObject
.
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());
}
执行结果:
文章图片
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
对象。文章图片
.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用法
The对于基本数据类型,.class
syntax is a more convenient and the preferred way to obtain theClass
for a primitive type; however there is another way to acquire theClass
. Each of the primitive types andvoid
has a wrapper class injava.lang
that is used for boxing of primitive types to reference types. Each wrapper class contains a field namedTYPE
which is equal to theClass
for the primitive type being wrapped.
.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);
}
输出结果:
文章图片
TYPE字段
1.2.5 返回Class的方法
There are several Reflection APIs which return classes but these may only be accessed if a有几个Class
has already been obtained either directly or indirectly.
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);
}
}
执行结果:
文章图片
getClasses()和getDeclaredClasses()代码 下面这个类实现了:获取类的声明组件,包括修饰符,泛型类型参数,实现的接口和继承路径。由于
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 l = new ArrayList();
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 l) {
Class> ancestor = c.getSuperclass();
if (ancestor != null) {
l.add(ancestor);
printAncestor(ancestor, l);
}
}
}
Since arrays are runtime objects, all of the type information is defined by the Java virtual machine. In particular, arrays implement由于数组是运行时对象,因此所有的类型信息都由JVM定义的。特别是,数组实现Cloneable
andjava.io.Serializable
and their direct superclass is alwaysObject
.
Clonable
和java.io.Serializable
,他的直接超类总是Object
;2. 源码实现
将XML数据转化为Object对象,将Object对象转化为XML文件。
/**
* 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 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 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;
}
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 事件代理
- Java|Java OpenCV图像处理之SIFT角点检测详解
- java中如何实现重建二叉树
- 数组常用方法一
- 【Hadoop踩雷】Mac下安装Hadoop3以及Java版本问题
- Java|Java基础——数组
- RxJava|RxJava 在Android项目中的使用(一)
- java之static、static|java之static、static final、final的区别与应用
- Java基础-高级特性-枚举实现状态机