package com.hundsun.jresplus.common.util;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
/**
* 有关 <code>Class</code> 处理的工具类。
*
* <p>
* 这个类中的每个方法都可以“安全”地处理 <code>null</code> ,而不会抛出
* <code>NullPointerException</code>。
* </p>
*
*/
public class ClassUtil {
/*
* ==========================================================================
* ==
*/
/* 常量和singleton。 */
/*
* ==========================================================================
* ==
*/
/** 资源文件的分隔符: <code>'/'</code>。 */
public static final char RESOURCE_SEPARATOR_CHAR = '/';
/** Java类名的分隔符: <code>'.'</code>。 */
public static final char PACKAGE_SEPARATOR_CHAR = '.';
/** Java类名的分隔符: <code>"."</code>。 */
public static final String PACKAGE_SEPARATOR = String
.valueOf(PACKAGE_SEPARATOR_CHAR);
/** 内联类的分隔符: <code>'$'</code>。 */
public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
/** 内联类的分隔符: <code>"$"</code>。 */
public static final String INNER_CLASS_SEPARATOR = String
.valueOf(INNER_CLASS_SEPARATOR_CHAR);
/** 所有类的信息表,包括父类, 接口, 数组的维数等信息。 */
private static Map TYPE_MAP = Collections
.synchronizedMap(new WeakHashMap());
/*
* ==========================================================================
* ==
*/
/* 取得类名和package名的方法。 */
/*
* ==========================================================================
* ==
*/
/**
* 取得对象所属的类的直观类名。
*
* <p>
* 相当于 <code>object.getClass().getName()</code> ,但不同的是,该方法用更直观的方式显示数组类型。 例如:
*
* <pre>
* int[].class.getName() = "[I" ClassUtil.getClassName(int[].class) = "int[]"
*
* Integer[][].class.getName() = "[[Ljava.lang.Integer;" ClassUtil.getClassName(Integer[][].class) = "java.lang.Integer[][]"
* </pre>
*
* </p>
*
* <p>
* 对于非数组的类型,该方法等效于 <code>Class.getName()</code> 方法。
* </p>
*
* <p>
* 注意,该方法所返回的数组类名只能用于显示给人看,不能用于 <code>Class.forName</code> 操作。
* </p>
*
* @param object
* 要显示类名的对象
*
* @return 用于显示的直观类名,如果原类名为空或非法,则返回 <code>null</code>
*/
public static String getClassNameForObject(Object object) {
if (object == null) {
return null;
}
return getClassName(object.getClass().getName(), true);
}
/**
* 取得直观的类名。
*
* <p>
* 相当于 <code>clazz.getName()</code> ,但不同的是,该方法用更直观的方式显示数组类型。 例如:
*
* <pre>
* int[].class.getName() = "[I" ClassUtil.getClassName(int[].class) = "int[]"
*
* Integer[][].class.getName() = "[[Ljava.lang.Integer;" ClassUtil.getClassName(Integer[][].class) = "java.lang.Integer[][]"
* </pre>
*
* </p>
*
* <p>
* 对于非数组的类型,该方法等效于 <code>Class.getName()</code> 方法。
* </p>
*
* <p>
* 注意,该方法所返回的数组类名只能用于显示给人看,不能用于 <code>Class.forName</code> 操作。
* </p>
*
* @param clazz
* 要显示类名的类
*
* @return 用于显示的直观类名,如果原始类为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getClassName(Class clazz) {
if (clazz == null) {
return null;
}
return getClassName(clazz.getName(), true);
}
/**
* 取得直观的类名。
*
* <p>
* <code>className</code> 必须是从 <code>clazz.getName()</code>
* 所返回的合法类名。该方法用更直观的方式显示数组类型。 例如:
*
* <pre>
* int[].class.getName() = "[I" ClassUtil.getClassName(int[].class) = "int[]"
*
* Integer[][].class.getName() = "[[Ljava.lang.Integer;" ClassUtil.getClassName(Integer[][].class) = "java.lang.Integer[][]"
* </pre>
*
* </p>
*
* <p>
* 对于非数组的类型,该方法等效于 <code>Class.getName()</code> 方法。
* </p>
*
* <p>
* 注意,该方法所返回的数组类名只能用于显示给人看,不能用于 <code>Class.forName</code> 操作。
* </p>
*
* @param className
* 要显示的类名
*
* @return 用于显示的直观类名,如果原类名为 <code>null</code> ,则返回 <code>null</code>
* ,如果原类名是非法的,则返回原类名
*/
public static String getClassName(String className) {
return getClassName(className, true);
}
/**
* 取得直观的类名。
*
* @param className
* 类名
* @param processInnerClass
* 是否将内联类分隔符 <code>'$'</code> 转换成 <code>'.'</code>
*
* @return 直观的类名,或 <code>null</code>
*/
private static String getClassName(String className,
boolean processInnerClass) {
if (StringUtil.isEmpty(className)) {
return className;
}
if (processInnerClass) {
className = className.replace(INNER_CLASS_SEPARATOR_CHAR,
PACKAGE_SEPARATOR_CHAR);
}
int length = className.length();
int dimension = 0;
// 取得数组的维数,如果不是数组,维数为0
for (int i = 0; i < length; i++, dimension++) {
if (className.charAt(i) != '[') {
break;
}
}
// 如果不是数组,则直接返回
if (dimension == 0) {
return className;
}
// 确保类名合法
if (length <= dimension) {
return className; // 非法类名
}
// 处理数组
StringBuffer componentTypeName = new StringBuffer();
switch (className.charAt(dimension)) {
case 'Z':
componentTypeName.append("boolean");
break;
case 'B':
componentTypeName.append("byte");
break;
case 'C':
componentTypeName.append("char");
break;
case 'D':
componentTypeName.append("double");
break;
case 'F':
componentTypeName.append("float");
break;
case 'I':
componentTypeName.append("int");
break;
case 'J':
componentTypeName.append("long");
break;
case 'S':
componentTypeName.append("short");
break;
case 'L':
if ((className.charAt(length - 1) != ';')
|| (length <= (dimension + 2))) {
return className; // 非法类名
}
componentTypeName.append(className.substring(dimension + 1,
length - 1));
break;
default:
return className; // 非法类名
}
for (int i = 0; i < dimension; i++) {
componentTypeName.append("[]");
}
return componentTypeName.toString();
}
/**
* 取得指定对象所属的类的短类名,不包括package名。
*
* <p>
* 此方法可以正确显示数组和内联类的名称。
* </p>
*
* <p>
* 例如:
*
* <pre>
* ClassUtil.getShortClassNameForObject(Boolean.TRUE) = "Boolean" ClassUtil.getShortClassNameForObject(new Boolean[10]) = "Boolean[]" ClassUtil.getShortClassNameForObject(new int[1][2]) = "int[][]"
* </pre>
*
* </p>
*
* @param object
* 要查看的对象
*
* @return 短类名,如果对象为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getShortClassNameForObject(Object object) {
if (object == null) {
return null;
}
return getShortClassName(object.getClass().getName());
}
/**
* 取得短类名,不包括package名。
*
* <p>
* 此方法可以正确显示数组和内联类的名称。
* </p>
*
* <p>
* 例如:
*
* <pre>
* ClassUtil.getShortClassName(Boolean.class) = "Boolean" ClassUtil.getShortClassName(Boolean[].class) = "Boolean[]" ClassUtil.getShortClassName(int[][].class) = "int[][]" ClassUtil.getShortClassName(Map.Entry.class) = "Map.Entry"
* </pre>
*
* </p>
*
* @param clazz
* 要查看的类
*
* @return 短类名,如果类为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getShortClassName(Class clazz) {
if (clazz == null) {
return null;
}
return getShortClassName(clazz.getName());
}
/**
* 取得类名,不包括package名。
*
* <p>
* 此方法可以正确显示数组和内联类的名称。
* </p>
*
* <p>
* 例如:
*
* <pre>
* ClassUtil.getShortClassName(Boolean.class.getName()) = "Boolean" ClassUtil.getShortClassName(Boolean[].class.getName()) = "Boolean[]" ClassUtil.getShortClassName(int[][].class.getName()) = "int[][]" ClassUtil.getShortClassName(Map.Entry.class.getName()) = "Map.Entry"
* </pre>
*
* </p>
*
* @param className
* 要查看的类名
*
* @return 短类名,如果类名为空,则返回 <code>null</code>
*/
public static String getShortClassName(String className) {
if (StringUtil.isEmpty(className)) {
return className;
}
// 转换成直观的类名
className = getClassName(className, false);
char[] chars = className.toCharArray();
int lastDot = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] == PACKAGE_SEPARATOR_CHAR) {
lastDot = i + 1;
} else if (chars[i] == INNER_CLASS_SEPARATOR_CHAR) {
chars[i] = PACKAGE_SEPARATOR_CHAR;
}
}
return new String(chars, lastDot, chars.length - lastDot);
}
/**
* 取得指定对象所属的类的package名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param object
* 要查看的对象
*
* @return package名,如果对象为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getPackageNameForObject(Object object) {
if (object == null) {
return null;
}
return getPackageName(object.getClass().getName());
}
/**
* 取得指定类的package名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param clazz
* 要查看的类
*
* @return package名,如果类为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getPackageName(Class clazz) {
if (clazz == null) {
return null;
}
return getPackageName(clazz.getName());
}
/**
* 取得指定类名的package名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param className
* 要查看的类名
*
* @return package名,如果类名为空,则返回 <code>null</code>
*/
public static String getPackageName(String className) {
if (StringUtil.isEmpty(className)) {
return null;
}
// 转换成直观的类名
className = getClassName(className, false);
int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
if (i == -1) {
return "";
}
return className.substring(0, i);
}
/*
* ==========================================================================
* ==
*/
/* 取得类名和package名的resource名的方法。 */
/* */
/* 和类名、package名不同的是,resource名符合文件名命名规范,例如: */
/* java/lang/String.class */
/* com/alibaba/commons/lang */
/* etc. */
/*
* ==========================================================================
* ==
*/
/**
* 取得对象所属的类的资源名。
*
* <p>
* 例如:
*
* <pre>
* ClassUtil.getClassNameForObjectAsResource("This is a string") = "java/lang/String.class"
* </pre>
*
* </p>
*
* @param object
* 要显示类名的对象
*
* @return 指定对象所属类的资源名,如果对象为空,则返回<code>null</code>
*/
public static String getClassNameForObjectAsResource(Object object) {
if (object == null) {
return null;
}
return object.getClass().getName()
.replace(PACKAGE_SEPARATOR_CHAR, RESOURCE_SEPARATOR_CHAR)
+ ".class";
}
/**
* 取得指定类的资源名。
*
* <p>
* 例如:
*
* <pre>
* ClassUtil.getClassNameAsResource(String.class) = "java/lang/String.class"
* </pre>
*
* </p>
*
* @param clazz
* 要显示类名的类
*
* @return 指定类的资源名,如果指定类为空,则返回<code>null</code>
*/
public static String getClassNameAsResource(Class clazz) {
if (clazz == null) {
return null;
}
return clazz.getName().replace(PACKAGE_SEPARATOR_CHAR,
RESOURCE_SEPARATOR_CHAR)
+ ".class";
}
/**
* 取得指定类的资源名。
*
* <p>
* 例如:
*
* <pre>
* ClassUtil.getClassNameAsResource("java.lang.String") = "java/lang/String.class"
* </pre>
*
* </p>
*
* @param className
* 要显示的类名
*
* @return 指定类名对应的资源名,如果指定类名为空,则返回<code>null</code>
*/
public static String getClassNameAsResource(String className) {
if (className == null) {
return null;
}
return className.replace(PACKAGE_SEPARATOR_CHAR,
RESOURCE_SEPARATOR_CHAR) + ".class";
}
/**
* 取得指定对象所属的类的package名的资源名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param object
* 要查看的对象
*
* @return package名,如果对象为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getPackageNameForObjectAsResource(Object object) {
if (object == null) {
return null;
}
return getPackageNameForObject(object).replace(PACKAGE_SEPARATOR_CHAR,
RESOURCE_SEPARATOR_CHAR);
}
/**
* 取得指定类的package名的资源名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param clazz
* 要查看的类
*
* @return package名,如果类为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getPackageNameAsResource(Class clazz) {
if (clazz == null) {
return null;
}
return getPackageName(clazz).replace(PACKAGE_SEPARATOR_CHAR,
RESOURCE_SEPARATOR_CHAR);
}
/**
* 取得指定类名的package名的资源名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param className
* 要查看的类名
*
* @return package名,如果类名为空,则返回 <code>null</code>
*/
public static String getPackageNameAsResource(String className) {
if (className == null) {
return null;
}
return getPackageName(className).replace(PACKAGE_SEPARATOR_CHAR,
RESOURCE_SEPARATOR_CHAR);
}
/*
* ==========================================================================
* ==
*/
/* 取得类的信息,如父类, 接口, 数组的维数等。 */
/*
* ==========================================================================
* ==
*/
/**
* 取得指定维数的 <code>Array</code>类.
*
* @param componentType
* 数组的基类
* @param dimension
* 维数,如果小于 <code>0</code> 则看作 <code>0</code>
*
* @return 如果维数为0, 则返回基类本身, 否则返回数组类,如果数组的基类为 <code>null</code> ,则返回
* <code>null</code>
*/
public static Class getArrayClass(Class componentType, int dimension) {
if (dimension <= 0) {
return componentType;
}
if (componentType == null) {
return null;
}
return Array.newInstance(componentType, new int[dimension]).getClass();
}
/**
* 取得数组元素的类型。
*
* @param type
* 要查找的类
*
* @return 如果是数组, 则返回数组元素的类型, 否则返回 <code>null</code>
*/
public static Class getArrayComponentType(Class type) {
if (type == null) {
return null;
}
return getTypeInfo(type).getArrayComponentType();
}
/**
* 取得数组的维数。
*
* @param clazz
* 要查找的类
*
* @return 数组的维数. 如果不是数组, 则返回 <code>0</code> ,如果数组为 <code>null</code> ,是返回
* <code>-1</code>
*/
public static int getArrayDimension(Class clazz) {
if (clazz == null) {
return -1;
}
return getTypeInfo(clazz).getArrayDimension();
}
/**
* 取得指定类的所有父类。
*
* <p>
* 对于一个 <code>Class</code> 实例,如果它不是接口,也不是数组,此方法依次列出从该类的父类开始直到
* <code>Object</code> 的所有类。
* </p>
*
* <p>
* 例如 <code>ClassUtil.getSuperclasses(java.util.ArrayList.class)</code>
* 返回以下列表:
*
* <ol>
* <li>
* <code>java.util.AbstractList</code></li>
* <li>
* <code>java.util.AbstractCollection</code></li>
* <li>
* <code>java.lang.Object</code></li>
* </ol>
* </p>
*
* <p>
* 对于一个接口,此方法返回一个空列表。
* </p>
*
* <p>
* 例如<code>ClassUtil.getSuperclasses(java.util.List.class)</code>将返回一个空列表。
* </p>
*
* <p>
* 对于一个数组,此方法返回一个列表,列出所有component类型的父类的相同维数的数组类型。 例如:
* <code>ClassUtil.getSuperclasses(java.util.ArrayList[][].class)</code>
* 返回以下列表:
*
* <ol>
* <li>
* <code>java.util.AbstractList[][]</code></li>
* <li>
* <code>java.util.AbstractCollection[][]</code></li>
* <li>
* <code>java.lang.Object[][]</code></li>
* <li>
* <code>java.lang.Object[]</code></li>
* <li>
* <code>java.lang.Object</code></li>
* </ol>
*
* 注意,原子类型及其数组,将被转换成相应的包装类来处理。 例如:
* <code>ClassUtil.getSuperclasses(int[][].class)</code> 返回以下列表:
*
* <ol>
* <li>
* <code>java.lang.Number[][]</code></li>
* <li>
* <code>java.lang.Object[][]</code></li>
* <li>
* <code>java.lang.Object[]</code></li>
* <li>
* <code>java.lang.Object</code></li>
* </ol>
* </p>
*
* @param clazz
* 要查找的类
*
* @return 所有父类的列表,如果指定类为 <code>null</code> ,则返回 <code>null</code>
*/
public static List getSuperclasses(Class clazz) {
if (clazz == null) {
return null;
}
return getTypeInfo(clazz).getSuperclasses();
}
/**
* 取得指定类的所有接口。
*
* <p>
* 对于一个 <code>Class</code> 实例,如果它不是接口,也不是数组,此方法依次列出从该类的父类开始直到
* <code>Object</code> 的所有类。
* </p>
*
* <p>
* 例如 <code>ClassUtil.getInterfaces(java.util.ArrayList.class)</code>
* 返回以下列表:
*
* <ol>
* <li>
* <code>java.util.List</code></li>
* <li>
* <code>java.util.Collection</code></li>
* <li>
* <code>java.util.RandomAccess</code></li>
* <li>
* <code>java.lang.Cloneable</code></li>
* <li>
* <code>java.io.Serializable</code></li>
* </ol>
* </p>
*
* <p>
* 对于一个数组,此方法返回一个列表,列出所有component类型的接口的相同维数的数组类型。 例如:
* <code>ClassUtil.getInterfaces(java.util.ArrayList[][].class)</code>
* 返回以下列表:
*
* <ol>
* <li>
* <code>java.util.List[][]</code></li>
* <li>
* <code>java.util.Collection[][]</code></li>
* <li>
* <code>java.util.RandomAccess[][]</code></li>
* <li>
* <code>java.lang.Cloneable[][]</code></li>
* <li>
* <code>java.io.Serializable[][]</code></li>
* </ol>
* </p>
*
* <p>
* 注意,原子类型及其数组,将被转换成相应的包装类来处理。 例如:
* <code>ClassUtil.getInterfaces(int[][].class)</code> 返回以下列表:
*
* <ol>
* <li>
* <code>java.lang.Comparable[][]</code></li>
* <li>
* <code>java.io.Serializable[][]</code></li>
* </ol>
* </p>
*
* @param clazz
* 要查找的类
*
* @return 所有接口的列表,如果指定类为 <code>null</code> ,则返回 <code>null</code>
*/
public static List getInterfaces(Class clazz) {
if (clazz == null) {
return null;
}
return getTypeInfo(clazz).getInterfaces();
}
/**
* 判断指定类是否为内联类。
*
* @param clazz
* 要查找的类
*
* @return 如果是,则返回 <code>true</code>
*/
public static boolean isInnerClass(Class clazz) {
if (clazz == null) {
return false;
}
return StringUtil.contains(clazz.getName(), INNER_CLASS_SEPARATOR_CHAR);
}
/**
* 检查一组指定类型 <code>fromClasses</code> 的对象是否可以赋值给另一组类型 <code>classes</code>。
*
* <p>
* 此方法可以用来确定指定类型的参数 <code>object1, object2, ...</code> 是否可以用来调用确定参数类型为
* <code>class1, class2,
* ...</code> 的方法。
* </p>
*
* <p>
* 对于 <code>fromClasses</code> 的每个元素 <code>fromClass</code> 和
* <code>classes</code> 的每个元素 <code>clazz</code>, 按照如下规则:
*
* <ol>
* <li>
* 如果目标类 <code>clazz</code> 为 <code>null</code> ,总是返回 <code>false</code>。</li>
* <li>
* 如果参数类型 <code>fromClass</code> 为 <code>null</code> ,并且目标类型
* <code>clazz</code> 为非原子类型,则返回 <code>true</code>。 因为 <code>null</code>
* 可以被赋给任何引用类型。</li>
* <li>
* 调用 <code>Class.isAssignableFrom</code> 方法来确定目标类 <code>clazz</code> 是否和参数类
* <code>fromClass</code> 相同或是其父类、接口,如果是,则返回 <code>true</code>。</li>
* <li>
* 如果目标类型 <code>clazz</code> 为原子类型,那么根据 <a
* href="http://java.sun.com/docs/books/jls/">The Java Language
* Specification</a> ,sections 5.1.1, 5.1.2, 5.1.4定义的Widening Primitive
* Conversion规则,参数类型 <code>fromClass</code> 可以是任何能扩展成该目标类型的原子类型及其包装类。 例如,
* <code>clazz</code> 为 <code>long</code> ,那么参数类型可以是 <code>byte</code>、
* <code>short</code>、<code>int</code>、<code>long</code>、<code>char</code>
* 及其包装类 <code>java.lang.Byte</code>、<code>java.lang.Short</code>、
* <code>java.lang.Integer</code>、 <code>java.lang.Long</code> 和
* <code>java.lang.Character</code> 。如果满足这个条件,则返回 <code>true</code>。</li>
* <li>
* 不满足上述所有条件,则返回 <code>false</code>。</li>
* </ol>
* </p>
*
* @param classes
* 目标类型列表,如果是 <code>null</code> 总是返回 <code>false</code>
* @param fromClasses
* 参数类型列表, <code>null</code> 表示可赋值给任意非原子类型
*
* @return 如果可以被赋值,则返回 <code>true</code>
*/
public static boolean isAssignable(Class[] classes, Class[] fromClasses) {
if (!ArrayUtil.isSameLength(fromClasses, classes)) {
return false;
}
if (fromClasses == null) {
fromClasses = ArrayUtil.EMPTY_CLASS_ARRAY;
}
if (classes == null) {
classes = ArrayUtil.EMPTY_CLASS_ARRAY;
}
for (int i = 0; i < fromClasses.length; i++) {
if (isAssignable(classes[i], fromClasses[i]) == false) {
return false;
}
}
return true;
}
/**
* 检查指定类型 <code>fromClass</code> 的对象是否可以赋值给另一种类型 <code>clazz</code>。
*
* <p>
* 此方法可以用来确定指定类型的参数 <code>object1, object2, ...</code> 是否可以用来调用确定参数类型
* <code>class1, class2,
* ...</code> 的方法。
* </p>
*
* <p>
* 按照如下规则:
*
* <ol>
* <li>
* 如果目标类 <code>clazz</code> 为 <code>null</code> ,总是返回 <code>false</code>。</li>
* <li>
* 如果参数类型 <code>fromClass</code> 为 <code>null</code> ,并且目标类型
* <code>clazz</code> 为非原子类型,则返回 <code>true</code>。 因为 <code>null</code>
* 可以被赋给任何引用类型。</li>
* <li>
* 调用 <code>Class.isAssignableFrom</code> 方法来确定目标类 <code>clazz</code> 是否和参数类
* <code>fromClass</code> 相同或是其父类、接口,如果是,则返回 <code>true</code>。</li>
* <li>
* 如果目标类型 <code>clazz</code> 为原子类型,那么根据 <a
* href="http://java.sun.com/docs/books/jls/">The Java Language
* Specification</a> ,sections 5.1.1, 5.1.2, 5.1.4定义的Widening Primitive
* Conversion规则,参数类型 <code>fromClass</code> 可以是任何能扩展成该目标类型的原子类型及其包装类。 例如,
* <code>clazz</code> 为 <code>long</code> ,那么参数类型可以是 <code>byte</code>、
* <code>short</code>、<code>int</code>、<code>long</code>、<code>char</code>
* 及其包装类 <code>java.lang.Byte</code>、<code>java.lang.Short</code>、
* <code>java.lang.Integer</code>、 <code>java.lang.Long</code> 和
* <code>java.lang.Character</code> 。如果满足这个条件,则返回 <code>true</code>。</li>
* <li>
* 不满足上述所有条件,则返回 <code>false</code>。</li>
* </ol>
* </p>
*
* @param clazz
* 目标类型,如果是 <code>null</code> 总是返回 <code>false</code>
* @param fromClass
* 参数类型, <code>null</code> 表示可赋值给任意非原子类型
*
* @return 如果可以被赋值,则返回 <code>null</code>
*/
public static boolean isAssignable(Class clazz, Class fromClass) {
if (clazz == null) {
return false;
}
// 如果fromClass是null,只要clazz不是原子类型如int,就一定可以赋值
if (fromClass == null) {
return !clazz.isPrimitive();
}
// 如果类相同或有父子关系,当然可以赋值
if (clazz.isAssignableFrom(fromClass)) {
return true;
}
// 对于原子类型,根据JLS的规则进行扩展
// 目标class为原子类型时,fromClass可以为原子类型和原子类型的包装类型。
if (clazz.isPrimitive()) {
// boolean可以接受:boolean
if (Boolean.TYPE.equals(clazz)) {
return Boolean.class.equals(fromClass);
}
// byte可以接受:byte
if (Byte.TYPE.equals(clazz)) {
return Byte.class.equals(fromClass);
}
// char可以接受:char
if (Character.TYPE.equals(clazz)) {
return Character.class.equals(fromClass);
}
// short可以接受:short, byte
if (Short.TYPE.equals(clazz)) {
return Short.class.equals(fromClass)
|| Byte.TYPE.equals(fromClass)
|| Byte.class.equals(fromClass);
}
// int可以接受:int、byte、short、char
if (Integer.TYPE.equals(clazz)) {
return Integer.class.equals(fromClass)
|| Byte.TYPE.equals(fromClass)
|| Byte.class.equals(fromClass)
|| Short.TYPE.equals(fromClass)
|| Short.class.equals(fromClass)
|| Character.TYPE.equals(fromClass)
|| Character.class.equals((fromClass));
}
// long可以接受:long、int、byte、short、char
if (Long.TYPE.equals(clazz)) {
return Long.class.equals(fromClass)
|| Integer.TYPE.equals(fromClass)
|| Integer.class.equals(fromClass)
|| Byte.TYPE.equals(fromClass)
|| Byte.class.equals(fromClass)
|| Short.TYPE.equals(fromClass)
|| Short.class.equals(fromClass)
|| Character.TYPE.equals(fromClass)
|| Character.class.equals((fromClass));
}
// float可以接受:float, long, int, byte, short, char
if (Float.TYPE.equals(clazz)) {
return Float.class.equals(fromClass)
|| Long.TYPE.equals(fromClass)
|| Long.class.equals(fromClass)
|| Integer.TYPE.equals(fromClass)
|| Integer.class.equals(fromClass)
|| Byte.TYPE.equals(fromClass)
|| Byte.class.equals(fromClass)
|| Short.TYPE.equals(fromClass)
|| Short.class.equals(fromClass)
|| Character.TYPE.equals(fromClass)
|| Character.class.equals((fromClass));
}
// double可以接受:double, float, long, int, byte, short, char
if (Double.TYPE.equals(clazz)) {
return Double.class.equals(fromClass)
|| Float.TYPE.equals(fromClass)
|| Float.class.equals(fromClass)
|| Long.TYPE.equals(fromClass)
|| Long.class.equals(fromClass)
|| Integer.TYPE.equals(fromClass)
|| Integer.class.equals(fromClass)
|| Byte.TYPE.equals(fromClass)
|| Byte.class.equals(fromClass)
|| Short.TYPE.equals(fromClass)
|| Short.class.equals(fromClass)
|| Character.TYPE.equals(fromClass)
|| Character.class.equals((fromClass));
}
}
return false;
}
/**
* 取得指定类的 <code>TypeInfo</code>。
*
* @param type
* 指定类或接口
*
* @return <code>TypeInfo</code> 对象.
*/
protected static TypeInfo getTypeInfo(Class type) {
if (type == null) {
throw new IllegalArgumentException(
"Parameter clazz should not be null");
}
TypeInfo classInfo;
synchronized (TYPE_MAP) {
classInfo = (TypeInfo) TYPE_MAP.get(type);
if (classInfo == null) {
classInfo = new TypeInfo(type);
TYPE_MAP.put(type, classInfo);
}
}
return classInfo;
}
/**
* 代表一个类的信息, 包括父类, 接口, 数组的维数等.
*/
protected static class TypeInfo {
private Class type;
private Class componentType;
private int dimension = 0;
private List superclasses = new ArrayList(2);
private List interfaces = new ArrayList(2);
/**
* 创建 <code>TypeInfo</code>。
*
* @param type
* 创建指定类的 <code>TypeInfo</code>
*/
private TypeInfo(Class type) {
this.type = type;
// 如果是array, 设置componentType和dimension
Class componentType = null;
if (type.isArray()) {
componentType = type;
do {
componentType = componentType.getComponentType();
dimension++;
} while (componentType.isArray());
}
this.componentType = componentType;
// 取得所有superclass
if (dimension > 0) {
// 将primitive类型转换成对应的包装类
componentType = getNonPrimitiveType(componentType);
Class superComponentType = componentType.getSuperclass();
// 如果是primitive, interface, 则设置其基类为Object.
if ((superComponentType == null)
&& !Object.class.equals(componentType)) {
superComponentType = Object.class;
}
if (superComponentType != null) {
Class superclass = getArrayClass(superComponentType,
dimension);
superclasses.add(superclass);
superclasses.addAll(getTypeInfo(superclass).superclasses);
} else {
for (int i = dimension - 1; i >= 0; i--) {
superclasses.add(getArrayClass(Object.class, i));
}
}
} else {
// 将primitive类型转换成对应的包装类
type = getNonPrimitiveType(type);
Class superclass = type.getSuperclass();
if (superclass != null) {
superclasses.add(superclass);
superclasses.addAll(getTypeInfo(superclass).superclasses);
}
}
// 取得所有interface
if (dimension == 0) {
Class[] typeInterfaces = type.getInterfaces();
List set = new ArrayList();
for (int i = 0; i < typeInterfaces.length; i++) {
Class typeInterface = typeInterfaces[i];
set.add(typeInterface);
set.addAll(getTypeInfo(typeInterface).interfaces);
}
for (Iterator i = superclasses.iterator(); i.hasNext();) {
Class typeInterface = (Class) i.next();
set.addAll(getTypeInfo(typeInterface).interfaces);
}
for (Iterator i = set.iterator(); i.hasNext();) {
Class interfaceClass = (Class) i.next();
if (!interfaces.contains(interfaceClass)) {
interfaces.add(interfaceClass);
}
}
} else {
for (Iterator i = getTypeInfo(componentType).interfaces
.iterator(); i.hasNext();) {
Class componentInterface = (Class) i.next();
interfaces
.add(getArrayClass(componentInterface, dimension));
}
}
}
/**
* 将所有的原子类型转换成对应的包装类,其它类型不变。
*
* @param type
* 要转换的类型
*
* @return 非原子类型
*/
private Class getNonPrimitiveType(Class type) {
if (type.isPrimitive()) {
if (Integer.TYPE.equals(type)) {
type = Integer.class;
} else if (Long.TYPE.equals(type)) {
type = Long.class;
} else if (Short.TYPE.equals(type)) {
type = Short.class;
} else if (Byte.TYPE.equals(type)) {
type = Byte.class;
} else if (Float.TYPE.equals(type)) {
type = Float.class;
} else if (Double.TYPE.equals(type)) {
type = Double.class;
} else if (Boolean.TYPE.equals(type)) {
type = Boolean.class;
} else if (Character.TYPE.equals(type)) {
type = Character.class;
}
}
return type;
}
/**
* 取得 <code>TypeInfo</code> 所代表的java类。
*
* @return <code>TypeInfo</code> 所代表的java类
*/
public Class getType() {
return type;
}
/**
* 取得数组元素的类型。
*
* @return 如果是数组, 则返回数组元素的类型, 否则返回 <code>null</code>
*/
public Class getArrayComponentType() {
return componentType;
}
/**
* 取得数组的维数。
*
* @return 数组的维数. 如果不是数组, 则返回 <code>0</code>
*/
public int getArrayDimension() {
return dimension;
}
/**
* 取得所有的父类。
*
* @return 所有的父类
*/
public List getSuperclasses() {
return Collections.unmodifiableList(superclasses);
}
/**
* 取得所有的接口。
*
* @return 所有的接口
*/
public List getInterfaces() {
return Collections.unmodifiableList(interfaces);
}
}
/*
* ==========================================================================
* ==
*/
/* 有关primitive类型的方法。 */
/*
* ==========================================================================
* ==
*/
/**
* 返回指定类型所对应的primitive类型。
*
* @param clazz
* 要检查的类型
*
* @return 如果指定类型为<code>null</code>或不是primitive类型的包装类,则返回<code>null</code>
* ,否则返回相应的primitive类型。
*/
public static Class getPrimitiveType(Class clazz) {
if (clazz == null) {
return null;
}
if (clazz.isPrimitive()) {
return clazz;
}
if (clazz.equals(Long.class)) {
return long.class;
}
if (clazz.equals(Integer.class)) {
return int.class;
}
if (clazz.equals(Short.class)) {
return short.class;
}
if (clazz.equals(Byte.class)) {
return byte.class;
}
if (clazz.equals(Double.class)) {
return double.class;
}
if (clazz.equals(Float.class)) {
return float.class;
}
if (clazz.equals(Boolean.class)) {
return boolean.class;
}
if (clazz.equals(Character.class)) {
return char.class;
}
return null;
}
/**
* 返回指定类型所对应的非primitive类型。
*
* @param clazz
* 要检查的类型
*
* @return 如果指定类型为<code>null</code>,则返回<code>null</code>
* ,如果是primitive类型,则返回相应的包装类,否则返回原始的类型。
*/
public static Class getNonPrimitiveType(Class clazz) {
if (clazz == null) {
return null;
}
if (!clazz.isPrimitive()) {
return clazz;
}
if (clazz.equals(long.class)) {
return Long.class;
}
if (clazz.equals(int.class)) {
return Integer.class;
}
if (clazz.equals(short.class)) {
return Short.class;
}
if (clazz.equals(byte.class)) {
return Byte.class;
}
if (clazz.equals(double.class)) {
return Double.class;
}
if (clazz.equals(float.class)) {
return Float.class;
}
if (clazz.equals(boolean.class)) {
return Boolean.class;
}
if (clazz.equals(char.class)) {
return Character.class;
}
return null;
}
}