
com.hc360.rsf.common.utils.ReflectUtils Maven / Gradle / Ivy
/**
* ReflectUtils.java 2012-5-10
* Copyright(c) 2000-2012 HC360.COM, All Rights Reserved.
*/
package com.hc360.rsf.common.utils;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.NotFoundException;
/**
* ReflectUtils
*
*/
public final class ReflectUtils {
/**
* void(V).
*/
public static final char JVM_VOID = 'V';
/**
* boolean(Z).
*/
public static final char JVM_BOOLEAN = 'Z';
/**
* byte(B).
*/
public static final char JVM_BYTE = 'B';
/**
* char(C).
*/
public static final char JVM_CHAR = 'C';
/**
* double(D).
*/
public static final char JVM_DOUBLE = 'D';
/**
* float(F).
*/
public static final char JVM_FLOAT = 'F';
/**
* int(I).
*/
public static final char JVM_INT = 'I';
/**
* long(J).
*/
public static final char JVM_LONG = 'J';
/**
* short(S).
*/
public static final char JVM_SHORT = 'S';
public static final Class>[] EMPTY_CLASS_ARRAY = new Class>[0];
public static final String JAVA_IDENT_REGEX = "(?:[_$a-zA-Z][_$a-zA-Z0-9]*)";
public static final String JAVA_NAME_REGEX = "(?:" + JAVA_IDENT_REGEX + "(?:\\." + JAVA_IDENT_REGEX
+ ")*)";
public static final String CLASS_DESC = "(?:L" + JAVA_IDENT_REGEX + "(?:\\/" + JAVA_IDENT_REGEX + ")*;)";
public static final String ARRAY_DESC = "(?:\\[+(?:(?:[VZBCDFIJS])|" + CLASS_DESC + "))";
public static final String DESC_REGEX = "(?:(?:[VZBCDFIJS])|" + CLASS_DESC + "|" + ARRAY_DESC + ")";
public static final Pattern DESC_PATTERN = Pattern.compile(DESC_REGEX);
public static final String METHOD_DESC_REGEX = "(?:(" + JAVA_IDENT_REGEX + ")?\\((" + DESC_REGEX
+ "*)\\)(" + DESC_REGEX + ")?)";
public static final Pattern METHOD_DESC_PATTERN = Pattern.compile(METHOD_DESC_REGEX);
public static final Pattern GETTER_METHOD_DESC_PATTERN = Pattern.compile("get([A-Z][_a-zA-Z0-9]*)\\(\\)("
+ DESC_REGEX + ")");
public static final Pattern SETTER_METHOD_DESC_PATTERN = Pattern.compile("set([A-Z][_a-zA-Z0-9]*)\\(("
+ DESC_REGEX + ")\\)V");
public static final Pattern IS_HAS_CAN_METHOD_DESC_PATTERN = Pattern
.compile("(?:is|has|can)([A-Z][_a-zA-Z0-9]*)\\(\\)Z");
private static final ConcurrentMap> DESC_CLASS_CACHE = new ConcurrentHashMap>();
public static boolean isPrimitives(Class> cls) {
if (cls.isArray()) {
return isPrimitive(cls.getComponentType());
}
return isPrimitive(cls);
}
public static boolean isPrimitive(Class> cls) {
return cls.isPrimitive() || cls == String.class || cls == Boolean.class || cls == Character.class
|| Number.class.isAssignableFrom(cls) || Date.class.isAssignableFrom(cls);
}
/**
* is compatible.
*
* @param c
* class.
* @param o
* instance.
* @return compatible or not.
*/
public static boolean isCompatible(Class> c, Object o) {
boolean pt = c.isPrimitive();
if (o == null) {
return !pt;
}
if (pt) {
if (c == int.class) {
c = Integer.class;
} else if (c == boolean.class) {
c = Boolean.class;
} else if (c == long.class) {
c = Long.class;
} else if (c == float.class) {
c = Float.class;
} else if (c == double.class) {
c = Double.class;
} else if (c == char.class) {
c = Character.class;
} else if (c == byte.class) {
c = Byte.class;
} else if (c == short.class) {
c = Short.class;
}
}
if (c == o.getClass()) {
return true;
}
return c.isInstance(o);
}
/**
* is compatible.
*
* @param cs
* class array.
* @param os
* object array.
* @return compatible or not.
*/
public static boolean isCompatible(Class>[] cs, Object[] os) {
int len = cs.length;
if (len != os.length) {
return false;
}
if (len == 0) {
return true;
}
for (int i = 0; i < len; i++) {
if (!isCompatible(cs[i], os[i])) {
return false;
}
}
return true;
}
public static String getCodeBase(Class> cls) {
if (cls == null) {
return null;
}
ProtectionDomain domain = cls.getProtectionDomain();
if (domain == null) {
return null;
}
CodeSource source = domain.getCodeSource();
if (source == null) {
return null;
}
URL location = source.getLocation();
if (location == null) {
return null;
}
return location.getFile();
}
/**
* get name. java.lang.Object[][].class => "java.lang.Object[][]"
*
* @param c
* class.
* @return name.
*/
public static String getName(Class> c1) {
Class> c = c1;
if (c.isArray()) {
StringBuilder sb = new StringBuilder();
do {
sb.append("[]");
c = c.getComponentType();
} while (c.isArray());
return c.getName() + sb.toString();
}
return c.getName();
}
public static Class> getGenericClass(Class> cls) {
return getGenericClass(cls, 0);
}
public static Class> getGenericClass(Class> cls, int i) {
try {
ParameterizedType parameterizedType = ((ParameterizedType) cls.getGenericInterfaces()[0]);
Object genericClass = parameterizedType.getActualTypeArguments()[i];
if (genericClass instanceof ParameterizedType) { // 处理多级泛型
return (Class>) ((ParameterizedType) genericClass).getRawType();
} else if (genericClass instanceof GenericArrayType) { // 处理数组泛型
return (Class>) ((GenericArrayType) genericClass).getGenericComponentType();
} else {
return (Class>) genericClass;
}
} catch (Throwable e) {
throw new IllegalArgumentException(cls.getName() + " generic type undefined!", e);
}
}
/**
* get method name. "void do(int)", "void do()",
* "int do(java.lang.String,boolean)"
*
* @param m
* method.
* @return name.
*/
public static String getName(final Method m) {
StringBuilder ret = new StringBuilder();
ret.append(getName(m.getReturnType())).append(' ');
ret.append(m.getName()).append('(');
Class>[] parameterTypes = m.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
if (i > 0) {
ret.append(',');
}
ret.append(getName(parameterTypes[i]));
}
ret.append(')');
return ret.toString();
}
public static String getSignature(String methodName, Class>[] parameterTypes) {
StringBuilder sb = new StringBuilder(methodName);
sb.append("(");
if (parameterTypes != null && parameterTypes.length > 0) {
boolean first = true;
for (Class> type : parameterTypes) {
if (first) {
first = false;
} else {
sb.append(",");
}
sb.append(type.getName());
}
}
sb.append(")");
return sb.toString();
}
/**
* get constructor name. "()", "(java.lang.String,int)"
*
* @param c
* constructor.
* @return name.
*/
public static String getName(final Constructor> c) {
StringBuilder ret = new StringBuilder("(");
Class>[] parameterTypes = c.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
if (i > 0) {
ret.append(',');
}
ret.append(getName(parameterTypes[i]));
}
ret.append(')');
return ret.toString();
}
/**
* get class desc. boolean[].class => "[Z" Object.class =>
* "Ljava/lang/Object;"
*
* @param c
* class.
* @return desc.
* @throws NotFoundException
*/
public static String getDesc(Class> c) {
StringBuilder ret = new StringBuilder();
while (c.isArray()) {
ret.append('[');
c = c.getComponentType();
}
if (c.isPrimitive()) {
String t = c.getName();
if ("void".equals(t)) {
ret.append(JVM_VOID);
} else if ("boolean".equals(t)) {
ret.append(JVM_BOOLEAN);
} else if ("byte".equals(t)) {
ret.append(JVM_BYTE);
} else if ("char".equals(t)) {
ret.append(JVM_CHAR);
} else if ("double".equals(t)) {
ret.append(JVM_DOUBLE);
} else if ("float".equals(t)) {
ret.append(JVM_FLOAT);
} else if ("int".equals(t)) {
ret.append(JVM_INT);
} else if ("long".equals(t)) {
ret.append(JVM_LONG);
} else if ("short".equals(t)) {
ret.append(JVM_SHORT);
}
} else {
ret.append('L');
ret.append(c.getName().replace('.', '/'));
ret.append(';');
}
return ret.toString();
}
/**
* get class array desc. [int.class, boolean[].class, Object.class] =>
* "I[ZLjava/lang/Object;"
*
* @param cs
* class array.
* @return desc.
* @throws NotFoundException
*/
public static String getDesc(final Class>[] cs) {
if (cs.length == 0) {
return "";
}
StringBuilder sb = new StringBuilder(64);
for (Class> c : cs) {
sb.append(getDesc(c));
}
return sb.toString();
}
/**
* get method desc. int do(int arg1) => "do(I)I" void do(String arg1,boolean
* arg2) => "do(Ljava/lang/String;Z)V"
*
* @param m
* method.
* @return desc.
*/
public static String getDesc(final Method m) {
StringBuilder ret = new StringBuilder(m.getName()).append('(');
Class>[] parameterTypes = m.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
ret.append(getDesc(parameterTypes[i]));
}
ret.append(')').append(getDesc(m.getReturnType()));
return ret.toString();
}
/**
* get constructor desc. "()V", "(Ljava/lang/String;I)V"
*
* @param c
* constructor.
* @return desc
*/
public static String getDesc(final Constructor> c) {
StringBuilder ret = new StringBuilder("(");
Class>[] parameterTypes = c.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
ret.append(getDesc(parameterTypes[i]));
}
ret.append(')').append('V');
return ret.toString();
}
/**
* get method desc. "(I)I", "()V", "(Ljava/lang/String;Z)V"
*
* @param m
* method.
* @return desc.
*/
public static String getDescWithoutMethodName(Method m) {
StringBuilder ret = new StringBuilder();
ret.append('(');
Class>[] parameterTypes = m.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
ret.append(getDesc(parameterTypes[i]));
}
ret.append(')').append(getDesc(m.getReturnType()));
return ret.toString();
}
/**
* get class desc. Object.class => "Ljava/lang/Object;" boolean[].class =>
* "[Z"
*
* @param c
* class.
* @return desc.
* @throws NotFoundException
*/
public static String getDesc(final CtClass c) throws NotFoundException {
StringBuilder ret = new StringBuilder();
if (c.isArray()) {
ret.append('[');
ret.append(getDesc(c.getComponentType()));
} else if (c.isPrimitive()) {
String t = c.getName();
if ("void".equals(t)) {
ret.append(JVM_VOID);
} else if ("boolean".equals(t)) {
ret.append(JVM_BOOLEAN);
} else if ("byte".equals(t)) {
ret.append(JVM_BYTE);
} else if ("char".equals(t)) {
ret.append(JVM_CHAR);
} else if ("double".equals(t)) {
ret.append(JVM_DOUBLE);
} else if ("float".equals(t)) {
ret.append(JVM_FLOAT);
} else if ("int".equals(t)) {
ret.append(JVM_INT);
} else if ("long".equals(t)) {
ret.append(JVM_LONG);
} else if ("short".equals(t)) {
ret.append(JVM_SHORT);
}
} else {
ret.append('L');
ret.append(c.getName().replace('.', '/'));
ret.append(';');
}
return ret.toString();
}
/**
* get method desc. "do(I)I", "do()V", "do(Ljava/lang/String;Z)V"
*
* @param m
* method.
* @return desc.
*/
public static String getDesc(final CtMethod m) throws NotFoundException {
StringBuilder ret = new StringBuilder(m.getName()).append('(');
CtClass[] parameterTypes = m.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
ret.append(getDesc(parameterTypes[i]));
}
ret.append(')').append(getDesc(m.getReturnType()));
return ret.toString();
}
/**
* get constructor desc. "()V", "(Ljava/lang/String;I)V"
*
* @param c
* constructor.
* @return desc
*/
public static String getDesc(final CtConstructor c) throws NotFoundException {
StringBuilder ret = new StringBuilder("(");
CtClass[] parameterTypes = c.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
ret.append(getDesc(parameterTypes[i]));
}
ret.append(')').append('V');
return ret.toString();
}
/**
* get method desc. "(I)I", "()V", "(Ljava/lang/String;Z)V".
*
* @param m
* method.
* @return desc.
*/
public static String getDescWithoutMethodName(final CtMethod m) throws NotFoundException {
StringBuilder ret = new StringBuilder();
ret.append('(');
CtClass[] parameterTypes = m.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
ret.append(getDesc(parameterTypes[i]));
}
ret.append(')').append(getDesc(m.getReturnType()));
return ret.toString();
}
/**
* name to desc. java.util.Map[][] => "[[Ljava/util/Map;"
*
* @param name
* name.
* @return desc.
*/
public static String name2desc(String name) {
StringBuilder sb = new StringBuilder();
int c = 0, index = name.indexOf('[');
if (index > 0) {
c = (name.length() - index) / 2;
name = name.substring(0, index);
}
while (c-- > 0) {
sb.append("[");
}
if ("void".equals(name)) {
sb.append(JVM_VOID);
} else if ("boolean".equals(name)) {
sb.append(JVM_BOOLEAN);
} else if ("byte".equals(name)) {
sb.append(JVM_BYTE);
} else if ("char".equals(name)) {
sb.append(JVM_CHAR);
} else if ("double".equals(name)) {
sb.append(JVM_DOUBLE);
} else if ("float".equals(name)) {
sb.append(JVM_FLOAT);
} else if ("int".equals(name)) {
sb.append(JVM_INT);
} else if ("long".equals(name)) {
sb.append(JVM_LONG);
} else if ("short".equals(name)) {
sb.append(JVM_SHORT);
} else {
sb.append('L').append(name.replace('.', '/')).append(';');
}
return sb.toString();
}
/**
* desc to name. "[[I" => "int[][]"
*
* @param desc
* desc.
* @return name.
*/
public static String desc2name(String desc) {
StringBuilder sb = new StringBuilder();
int c = desc.lastIndexOf('[') + 1;
if (desc.length() == c + 1) {
switch (desc.charAt(c)) {
case JVM_VOID: {
sb.append("void");
break;
}
case JVM_BOOLEAN: {
sb.append("boolean");
break;
}
case JVM_BYTE: {
sb.append("byte");
break;
}
case JVM_CHAR: {
sb.append("char");
break;
}
case JVM_DOUBLE: {
sb.append("double");
break;
}
case JVM_FLOAT: {
sb.append("float");
break;
}
case JVM_INT: {
sb.append("int");
break;
}
case JVM_LONG: {
sb.append("long");
break;
}
case JVM_SHORT: {
sb.append("short");
break;
}
default: {
throw new RuntimeException();
}
}
} else {
sb.append(desc.substring(c + 1, desc.length() - 1).replace('/', '.'));
}
while (c-- > 0) {
sb.append("[]");
}
return sb.toString();
}
public static Class> forName(String name) {
try {
return name2class(name);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Not found class " + name + ", cause: " + e.getMessage(), e);
}
}
/**
* name to class. "boolean" => boolean.class "java.util.Map[][]" =>
* java.util.Map[][].class
*
* @param name
* name.
* @return Class instance.
*/
public static Class> name2class(String name) throws ClassNotFoundException {
return name2class(ClassHelper.getClassLoader(), name);
}
/**
* name to class. "boolean" => boolean.class "java.util.Map[][]" =>
* java.util.Map[][].class
*
* @param cl
* ClassLoader instance.
* @param name
* name.
* @return Class instance.
*/
private static Class> name2class(ClassLoader cl, String name) throws ClassNotFoundException {
int c = 0, index = name.indexOf('[');
if (index > 0) {
c = (name.length() - index) / 2;
name = name.substring(0, index);
}
if (c > 0) {
StringBuilder sb = new StringBuilder();
while (c-- > 0) {
sb.append("[");
}
if ("void".equals(name)) {
sb.append(JVM_VOID);
} else if ("boolean".equals(name)) {
sb.append(JVM_BOOLEAN);
} else if ("byte".equals(name)) {
sb.append(JVM_BYTE);
} else if ("char".equals(name)) {
sb.append(JVM_CHAR);
} else if ("double".equals(name)) {
sb.append(JVM_DOUBLE);
} else if ("float".equals(name)) {
sb.append(JVM_FLOAT);
} else if ("int".equals(name)) {
sb.append(JVM_INT);
} else if ("long".equals(name)) {
sb.append(JVM_LONG);
} else if ("short".equals(name)) {
sb.append(JVM_SHORT);
} else {
sb.append('L').append(name).append(';');
}// "java.lang.Object" ==> "Ljava.lang.Object;"
name = sb.toString();
} else {
if ("void".equals(name)) {
return void.class;
} else if ("boolean".equals(name)) {
return boolean.class;
} else if ("byte".equals(name)) {
return byte.class;
} else if ("char".equals(name)) {
return char.class;
} else if ("double".equals(name)) {
return double.class;
} else if ("float".equals(name)) {
return float.class;
} else if ("int".equals(name)) {
return int.class;
} else if ("long".equals(name)) {
return long.class;
} else if ("short".equals(name)) {
return short.class;
}
}
if (cl == null) {
cl = ClassHelper.getClassLoader();
}
/**
* 最多时候 ,走的还是Class.forName --赵磊
*/
return Class.forName(name, true, cl);
}
/**
* desc to class. "[Z" => boolean[].class "[[Ljava/util/Map;" =>
* java.util.Map[][].class
*
* @param desc
* desc.
* @return Class instance.
* @throws ClassNotFoundException
*/
public static Class> desc2class(String desc) throws ClassNotFoundException {
return desc2class(ClassHelper.getClassLoader(), desc);
}
/**
* desc to class. "[Z" => boolean[].class "[[Ljava/util/Map;" =>
* java.util.Map[][].class
*
* @param cl
* ClassLoader instance.
* @param desc
* desc.
* @return Class instance.
* @throws ClassNotFoundException
*/
private static Class> desc2class(ClassLoader cl, String desc) throws ClassNotFoundException {
switch (desc.charAt(0)) {
case JVM_VOID:
return void.class;
case JVM_BOOLEAN:
return boolean.class;
case JVM_BYTE:
return byte.class;
case JVM_CHAR:
return char.class;
case JVM_DOUBLE:
return double.class;
case JVM_FLOAT:
return float.class;
case JVM_INT:
return int.class;
case JVM_LONG:
return long.class;
case JVM_SHORT:
return short.class;
case 'L':
desc = desc.substring(1, desc.length() - 1).replace('/', '.'); // "Ljava/lang/Object;"
// ==>
// "java.lang.Object"
break;
case '[':
desc = desc.replace('/', '.'); // "[[Ljava/lang/Object;" ==>
// "[[Ljava.lang.Object;"
break;
default:
throw new ClassNotFoundException("Class not found: " + desc);
}
if (cl == null) {
cl = ClassHelper.getClassLoader();
}
Class> clazz = DESC_CLASS_CACHE.get(desc);
if (clazz == null) {
clazz = Class.forName(desc, true, cl);
DESC_CLASS_CACHE.put(desc, clazz);
}
return clazz;
}
/**
* get class array instance.
*
* @param desc
* desc.
* @return Class class array.
* @throws ClassNotFoundException
*/
public static Class>[] desc2classArray(String desc) throws ClassNotFoundException {
return desc2classArray(ClassHelper.getClassLoader(), desc);
}
/**
* get class array instance.
*
* @param cl
* ClassLoader instance.
* @param desc
* desc.
* @return Class[] class array.
* @throws ClassNotFoundException
*/
private static Class>[] desc2classArray(ClassLoader cl, String desc) throws ClassNotFoundException {
if (desc.length() == 0) {
return EMPTY_CLASS_ARRAY;
}
List> cs = new ArrayList>();
Matcher m = DESC_PATTERN.matcher(desc);
while (m.find()) {
cs.add(desc2class(cl, m.group()));
}
return cs.toArray(EMPTY_CLASS_ARRAY);
}
/**
* 根据方法签名从类中找出方法。
*
* @param clazz
* 查找的类。
* @param methodName
* 方法签名,形如method1(int, String)。也允许只给方法名不参数只有方法名,形如method2。
* @return 返回查找到的方法。
* @throws NoSuchMethodException
* @throws ClassNotFoundException
* @throws IllegalStateException
* 给定的方法签名找到多个方法(方法签名中没有指定参数,又有有重载的方法的情况)
*/
public static Method findMethodByMethodSignature(Class> clazz, String methodName,
String[] parameterTypes) throws NoSuchMethodException, ClassNotFoundException {
if (parameterTypes == null) {
List finded = new ArrayList();
for (Method m : clazz.getMethods()) {
if (m.getName().equals(methodName)) {
finded.add(m);
}
}
if (finded.isEmpty()) {
throw new NoSuchMethodException("No such method " + methodName + " in class " + clazz);
}
if (finded.size() > 1) {
String msg = String.format(
"Not unique method for method name(%s) in class(%s), find %d methods.", methodName,
clazz.getName(), finded.size());
throw new IllegalStateException(msg);
}
return finded.get(0);
} else {
Class>[] types = new Class>[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
types[i] = ReflectUtils.name2class(parameterTypes[i]);
}
return clazz.getMethod(methodName, types);
}
}
public static Method findMethodByMethodName(Class> clazz, String methodName)
throws NoSuchMethodException, ClassNotFoundException {
return findMethodByMethodSignature(clazz, methodName, null);
}
public static Constructor> findConstructor(Class> clazz, Class> paramType)
throws NoSuchMethodException {
Constructor> targetConstructor;
try {
targetConstructor = clazz.getConstructor(new Class>[] { paramType });
} catch (NoSuchMethodException e) {
targetConstructor = null;
Constructor>[] constructors = clazz.getConstructors();
for (Constructor> constructor : constructors) {
if (Modifier.isPublic(constructor.getModifiers())
&& constructor.getParameterTypes().length == 1
&& constructor.getParameterTypes()[0].isAssignableFrom(paramType)) {
targetConstructor = constructor;
break;
}
}
if (targetConstructor == null) {
throw e;
}
}
return targetConstructor;
}
/**
* 检查对象是否是指定接口的实现。
*
* 不会触发到指定接口的{@link Class},所以如果ClassLoader中没有指定接口类时,也不会出错。
*
* @param obj
* 要检查的对象
* @param interfaceClazzName
* 指定的接口名
* @return 返回{@code true},如果对象实现了指定接口;否则返回{@code false}。
*/
public static boolean isInstance(Object obj, String interfaceClazzName) {
for (Class> clazz = obj.getClass(); clazz != null && !clazz.equals(Object.class); clazz = clazz
.getSuperclass()) {
Class>[] interfaces = clazz.getInterfaces();
for (Class> itf : interfaces) {
if (itf.getName().equals(interfaceClazzName)) {
return true;
}
}
}
return false;
}
public static Object getEmptyObject(Class> returnType) {
return getEmptyObject(returnType, new HashMap, Object>(), 0);
}
private static Object getEmptyObject(Class> returnType, Map, Object> emptyInstances, int level) {
if (level > 2) {
return null;
}
if (returnType == null) {
return null;
} else if (returnType == boolean.class || returnType == Boolean.class) {
return false;
} else if (returnType == char.class || returnType == Character.class) {
return '\0';
} else if (returnType == byte.class || returnType == Byte.class) {
return (byte) 0;
} else if (returnType == short.class || returnType == Short.class) {
return (short) 0;
} else if (returnType == int.class || returnType == Integer.class) {
return 0;
} else if (returnType == long.class || returnType == Long.class) {
return 0L;
} else if (returnType == float.class || returnType == Float.class) {
return 0F;
} else if (returnType == double.class || returnType == Double.class) {
return 0D;
} else if (returnType.isArray()) {
return Array.newInstance(returnType.getComponentType(), 0);
} else if (returnType.isAssignableFrom(ArrayList.class)) {
return new ArrayList