/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import static com.alibaba.citrus.util.Assert.*; import static com.alibaba.citrus.util.CollectionUtil.*; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import com.alibaba.citrus.util.internal.ArrayUtil; import com.alibaba.citrus.util.internal.StringUtil; /** * 有关类型的工具类。 * * @author Michael Zhou */ public class ClassUtil { private static final Map<String, PrimitiveInfo<?>> PRIMITIVES = createHashMap(); static { PRIMITIVES.put("boolean", new PrimitiveInfo<Boolean>(boolean.class, "Z", Boolean.class, "booleanValue")); PRIMITIVES.put("short", new PrimitiveInfo<Short>(short.class, "S", Short.class, "shortValue")); PRIMITIVES.put("int", new PrimitiveInfo<Integer>(int.class, "I", Integer.class, "intValue")); PRIMITIVES.put("long", new PrimitiveInfo<Long>(long.class, "J", Long.class, "longValue")); PRIMITIVES.put("float", new PrimitiveInfo<Float>(float.class, "F", Float.class, "floatValue")); PRIMITIVES.put("double", new PrimitiveInfo<Double>(double.class, "D", Double.class, "doubleValue")); PRIMITIVES.put("char", new PrimitiveInfo<Character>(char.class, "C", Character.class, "charValue")); PRIMITIVES.put("byte", new PrimitiveInfo<Byte>(byte.class, "B", Byte.class, "byteValue")); PRIMITIVES.put("void", new PrimitiveInfo<Void>(void.class, "V", Void.class, null)); } /** 代表一个primitive类型的信息。 */ private static class PrimitiveInfo<T> { final Class<T> type; final String typeCode; final Class<T> wrapperType; final String unwrapMethod; public PrimitiveInfo(Class<T> type, String typeCode, Class<T> wrapperType, String unwrapMethod) { this.type = type; this.typeCode = typeCode; this.wrapperType = wrapperType; this.unwrapMethod = unwrapMethod; } } /** * 取得primitive类。 * <p> * 例如: * <p/> * <pre> * ClassUtil.getPrimitiveType("int") = int.class; * ClassUtil.getPrimitiveType("long") = long.class; * </pre> * <p/> * </p> */ public static Class<?> getPrimitiveType(String name) { PrimitiveInfo<?> info = PRIMITIVES.get(name); if (info != null) { return info.type; } return null; } /** * 取得primitive类型的wrapper。如果不是primitive,则原样返回。 * <p> * 例如: * <p/> * <pre> * ClassUtil.getPrimitiveWrapperType(int.class) = Integer.class; * ClassUtil.getPrimitiveWrapperType(int[].class) = int[].class; * ClassUtil.getPrimitiveWrapperType(int[][].class) = int[][].class; * ClassUtil.getPrimitiveWrapperType(String[][].class) = String[][].class; * </pre> * <p/> * </p> */ @SuppressWarnings("unchecked") public static <T> Class<T> getPrimitiveWrapperType(Class<T> type) { if (type.isPrimitive()) { return ((PrimitiveInfo<T>) PRIMITIVES.get(type.getName())).wrapperType; } return type; } /** 代表Array的信息。 */ public static final class ArrayInfo { public final Class<?> componentType; public final int dimension; private ArrayInfo(Class<?> componentType, int dimension) { this.componentType = componentType; this.dimension = dimension; } } /** 取得数组的维度,非数组则返回<code>0</code>。 */ public static ArrayInfo getArrayInfo(Class<?> arrayType) { assertNotNull(arrayType, "arrayType"); int dimension = 0; while (arrayType.isArray()) { arrayType = arrayType.getComponentType(); dimension++; } return new ArrayInfo(arrayType, dimension); } /** 取得指定component类型和维度的数组类。 */ public static Class<?> getArrayType(Class<?> componentType, int dimension) { assertTrue(dimension >= 0, "dimension"); if (dimension == 0) { return componentType; } return Array.newInstance(componentType, new int[dimension]).getClass(); } /** * 取得JVM内部的类名。 * <p> * 例如: * <p/> * <pre> * ClassUtil.getJVMClassName("int[]") = "[I" * ClassUtil.getJVMClassName("java.lang.Integer[][]") = "[[Ljava.lang.Integer;" * </pre> * <p/> * </p> * <p> * 该方法所返回的类名可用于 <code>Class.forName</code> 操作。 * </p> */ public static String getJVMClassName(String name) { return getJVMClassName(name, 0); } /** * 取得JVM内部的数组类名。 * <p> * 例如: * <p/> * <pre> * ClassUtil.getJVMClassName("int", 1) = "[I" // int[] * ClassUtil.getJVMClassName("java.lang.Integer", 2) = "[[Ljava.lang.Integer;" // Integer[][] * * ClassUtil.getJVMClassName("int[]", 1) = "[[I" // int[][] * ClassUtil.getJVMClassName("java.lang.Integer[]", 1) = "[[Ljava.lang.Integer;" // Integer[][] * </pre> * <p/> * </p> * <p> * 该方法所返回的类名可用于 <code>Class.forName</code> 操作。 * </p> */ public static String getJVMClassName(String name, int dimension) { assertTrue(dimension >= 0, "dimension"); if (StringUtil.isEmpty(name)) { return name; } if (!name.endsWith("[]") && dimension == 0) { return name; } StringBuilder buffer = new StringBuilder(); while (name.endsWith("[]")) { buffer.append("["); name = name.substring(0, name.length() - 2); } for (int i = 0; i < dimension; i++) { buffer.append("["); } PrimitiveInfo<?> pi = PRIMITIVES.get(name); if (pi != null) { buffer.append(pi.typeCode); } else { buffer.append("L"); buffer.append(name); buffer.append(";"); } return buffer.toString(); } /** * 取得完整的类名。 * <p> * 对于数组,将返回以“<code>[]</code>”结尾的名字。 * </p> * <p> * 本方法和<code>Class.getCanonicalName()</code>的区别在于,本方法会保留inner类的 * <code>$</code>符号。 * </p> */ public static String getJavaClassName(Class<?> clazz) { if (clazz.isArray()) { return getJavaClassName(clazz.getComponentType()) + "[]"; } return clazz.getName(); } /** * 取得完整的类名。 * <p> * 对于数组,将返回以“<code>[]</code>”结尾的名字。 * </p> * <p> * 本方法和<code>Class.getSimpleName()</code>的区别在于,本方法会保留inner类的<code>$</code> * 符号。 * </p> */ public static String getSimpleJavaClassName(Class<?> clazz) { String className = getJavaClassName(clazz); return className.substring(className.lastIndexOf(".") + 1); } /** 判断方法是不是<code>String toString()</code>方法。 */ public static boolean isToString(Method method) { return isToString(new MethodSignature(method)); } /** 判断方法是不是<code>String toString()</code>方法。 */ public static boolean isToString(MethodSignature method) { if (!"toString".equals(method.getName())) { return false; } if (method.getParameterTypes().length > 0) { return false; } return String.class == method.getReturnType(); } /** * 取得指定类的所有父类和接口。 * <p> * 对于一个<code>Class</code>对象,如果它即不是接口,也不是数组,则按如下次序列出该类的父类及接口。 * </p> * <p> * 例如<code>ClassUtil.getSupertypes(java.util.ArrayList.class)</code>返回以下列表: * (顺序为:本类、父类、父接口、Object类) * <ol> * <li>本类 - <code>java.util.ArrayList</code></li> * <li>父类 - <code>java.util.AbstractList</code></li> * <li>父类 - <code>java.util.AbstractCollection</code></li> * <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> * <li>父接口 - <code>java.io.Iterable</code></li> * <li>Object类 - <code>java.lang.Object</code></li> * </ol> * </p> * <p> * 对于一个<code>Class</code>对象,如果它是接口,则按如下次序列出该类的父接口。 * </p> * <p> * 例如<code>ClassUtil.getSupertypes(java.util.List.class)</code>将返回如下列表: * (顺序为:本接口、父接口、Object类) * </p> * <ol> * <li>本接口 - <code>java.util.List</code></li> * <li>父接口 - <code>java.util.Collection</code></li> * <li>父接口 - <code>java.util.Iterable</code></li> * <li>Object类 - <code>java.lang.Object</code></li> * </ol> * <p> * 对于一个数组,此方法返回一个列表,列出所有component类型的父类和接口的维数相同的数组类型。 例如: * <code>ClassUtil.getSupertypes(java.util.ArrayList[][].class)</code> * 返回以下列表:(顺序为:本数组、父类数组、父接口数组、Object类数组、数组父类、数组父接口、Object类) * <ol> * <li>本数组 - <code>java.util.ArrayList[][]</code></li> * <li>父类数组 - <code>java.util.AbstractList[][]</code></li> * <li>父类数组 - <code>java.util.AbstractCollection[][]</code></li> * <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> * <li>父接口数组 - <code>java.io.Iterable[][]</code></li> * <li>Object类数组 - <code>java.lang.Object[][]</code></li> * <li>数组父类 - <code>java.lang.Object[]</code></li> * <li>数组父接口 - <code>java.lang.Cloneable</code></li> * <li>数组父接口 - <code>java.io.Serializable</code></li> * <li>Object类 - <code>java.lang.Object</code></li> * </ol> * 特殊类型<code>void</code>、<code>Void</code>没有任何父类。 * <ol> * <li><code>java.lang.Void</code></li> * </ol> * 最后,原子类型将会被转换成包装类。 例如:<code>ClassUtil.getSupertypes(int.class)</code> * 返回以下列表: * <ol> * <li><code>java.lang.Integer</code></li> * <li><code>java.lang.Number</code></li> * <li><code>java.lang.Comparable</code></li> * <li><code>java.io.Serializable</code></li> * <li><code>java.lang.Object</code></li> * </ol> * 但是原子类型的数组并不会被转成包装类。例如:<code>ClassUtil.getSupertypes(int[][].class)</code> * 返回以下列表: * <ol> * <li><code>int[][]</code></li> * <li><code>Object[]</code></li> * <li><code>java.lang.Comparable</code></li> * <li><code>java.io.Serializable</code></li> * <li><code>java.lang.Object</code></li> * </ol> * </p> */ public static Iterable<Class<?>> getSupertypes(Class<?> clazz) { return new Supertypes(clazz); } /** 遍历所有父类和接口。 */ private static class Supertypes implements Iterable<Class<?>> { private Class<?> clazz; public Supertypes(Class<?> clazz) { this.clazz = clazz; } public Iterator<Class<?>> iterator() { return new SupertypeIterator(clazz); } } /** 遍历所有父类和接口的遍历器。 */ private static class SupertypeIterator implements Iterator<Class<?>> { private static enum State { CLASSES, INTERFACES, ARRAYS, END } private final Set<Class<?>> processedInterfaces = createHashSet(); private final LinkedList<Class<?>> interfaceQueue = createLinkedList(); private Class<?> clazz; private int dimension; private Iterator<Class<?>> componentTypes; private State state; public SupertypeIterator(Class<?> clazz) { this(clazz, true); } public SupertypeIterator(Class<?> clazz, boolean convertPrimitive) { assertNotNull(clazz, "clazz"); clazz = convertPrimitive ? getPrimitiveWrapperType(clazz) : clazz; queueInterfaces(clazz); // 是否为数组? ArrayInfo ai = getArrayInfo(clazz); this.clazz = clazz = ai.componentType; this.dimension = ai.dimension; // 设置初始状态 if (dimension > 0) { componentTypes = new SupertypeIterator(clazz, false); state = State.ARRAYS; } else if (clazz.isInterface() || clazz == Object.class) { state = State.INTERFACES; } else { state = State.CLASSES; } } public boolean hasNext() { return state != State.END; } public Class<?> next() { Class<?> result; switch (state) { case ARRAYS: result = getArrayType(componentTypes.next(), dimension); if (!componentTypes.hasNext()) { if (--dimension > 0) { state = State.CLASSES; clazz = Object.class; } else { state = State.INTERFACES; } } break; case CLASSES: if (dimension > 0) { result = getArrayType(clazz, dimension); if (--dimension == 0) { state = State.INTERFACES; } } else { result = clazz; if (clazz == Void.class) { clazz = null; } else { clazz = clazz.getSuperclass(); } if (clazz == null) { if (interfaceQueue.isEmpty()) { state = State.END; } } else { queueInterfaces(clazz); if (clazz == Object.class) { state = State.INTERFACES; } } } break; case INTERFACES: if (interfaceQueue.isEmpty()) { state = State.END; result = Object.class; } else { result = interfaceQueue.removeFirst(); queueInterfaces(result); } break; default: throw new NoSuchElementException(); } return result; } public void remove() { throw new UnsupportedOperationException(); } private void queueInterfaces(Class<?> clazz) { if (clazz.isInterface() && !processedInterfaces.contains(clazz)) { interfaceQueue.addLast(clazz); processedInterfaces.add(clazz); } for (Class<?> interfaceClass : clazz.getInterfaces()) { if (!processedInterfaces.contains(interfaceClass)) { interfaceQueue.addLast(interfaceClass); processedInterfaces.add(interfaceClass); } } } } /** 取得类名对应的资源名。 */ public static String getResourceNameOfClass(Class<?> clazz) { String className = clazz == null ? null : clazz.getName(); return getResourceNameOfClass(className); } /** 取得类名对应的资源名。 */ public static String getResourceNameOfClass(String className) { if (className == null) { return null; } return className.trim().replace('.', '/'); } /** * 取得指定类或接口的所有<code>public</code>方法签名。 * <p> * 该方法返回的签名是被排序的。 * </p> */ public static Map<MethodSignature, Class<?>> getMethodSignatures(Class<?>... classes) throws IncompatibleMethodSignatureException { class Tuple implements Comparable<Tuple> { public final MethodSignature signature; public final Class<?> declaringClass; public Tuple(MethodSignature signature, Class<?> declaringClass) { this.signature = signature; this.declaringClass = declaringClass; } public int compareTo(Tuple other) { return signature.compareTo(other.signature); } } Map<MethodSignature, Tuple> set = createHashMap(); for (Class<?> clazz : classes) { for (Method method : clazz.getMethods()) { MethodSignature signature = new MethodSignature(method); Tuple existing = set.get(signature); if (existing == null) { set.put(signature, new Tuple(signature, method.getDeclaringClass())); } else { if (existing.signature.isOverridingSignatureOf(signature)) { set.put(signature, new Tuple(signature, method.getDeclaringClass())); } else if (!signature.isOverridingSignatureOf(existing.signature)) { throw new IncompatibleMethodSignatureException(incompatibleMethodSignaturesDetected( existing.signature, signature)); } } } } List<Tuple> tuples = createArrayList(set.size()); tuples.addAll(set.values()); Collections.sort(tuples); Map<MethodSignature, Class<?>> signatures = createLinkedHashMap(); for (Tuple tuple : tuples) { signatures.put(tuple.signature, tuple.declaringClass); } return signatures; } /** 调用构造函数创建对象。 */ public static <T> T newInstance(Class<T> clazz) { return newInstance(clazz, null, null); } /** 调用构造函数创建对象。 */ public static <T> T newInstance(Class<T> clazz, Class<?>[] paramTypes, Object[] paramValues) { try { if (ArrayUtil.isEmpty(paramTypes)) { return clazz.newInstance(); } Constructor<T> constructor = clazz.getDeclaredConstructor(paramTypes); return constructor.newInstance(paramValues); } catch (InvocationTargetException e) { if (e.getCause() instanceof RuntimeException) { throw (RuntimeException) e.getCause(); } else { unexpectedException(e.getCause()); return null; } } catch (Exception e) { unexpectedException(e); return null; } } }