/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ package net.hasor.core.utils; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * <p>Operates on classes without using reflection.</p> * * <p>This class handles invalid <code>null</code> inputs as best it can. * Each method documents its behaviour in more detail.</p> * * <p>The notion of a <code>canonical name</code> includes the human * readable name for the type, for example <code>int[]</code>. The * non-canonical method variants work with the JVM names, such as * <code>[I</code>. </p> * * @author 赵永春 * @author Apache Software Foundation * @author Gary Gregory * @author Norm Deane * @author Alban Peignier * @author Tomasz Blachowicz * @since 2.0 * @version $Id: ClassUtils.java 1057072 2011-01-10 01:55:57Z niallp $ */ public class ClassUtils { /** <p>The package separator character: <code>'.' == {@value}</code>.</p> */ public static final char PACKAGE_SEPARATOR_CHAR = '.'; /** <p>The inner class separator character: <code>'$' == {@value}</code>.</p> */ public static final char INNER_CLASS_SEPARATOR_CHAR = '$'; /** Maps a primitive class name to its corresponding abbreviation used in array class names. */ private static final Map<String, String> abbreviationMap = new HashMap<String, String>(); /** Maps an abbreviation used in array class names to corresponding primitive class name. */ private static final Map<String, String> reverseAbbreviationMap = new HashMap<String, String>(); /** * Add primitive type abbreviation to maps of abbreviations. * @param primitive Canonical name of primitive type * @param abbreviation Corresponding abbreviation of primitive type */ private static void addAbbreviation(final String primitive, final String abbreviation) { ClassUtils.abbreviationMap.put(primitive, abbreviation); ClassUtils.reverseAbbreviationMap.put(abbreviation, primitive); } /** Feed abbreviation maps. */ static { ClassUtils.addAbbreviation("int", "I"); ClassUtils.addAbbreviation("boolean", "Z"); ClassUtils.addAbbreviation("float", "F"); ClassUtils.addAbbreviation("long", "J"); ClassUtils.addAbbreviation("short", "S"); ClassUtils.addAbbreviation("byte", "B"); ClassUtils.addAbbreviation("double", "D"); ClassUtils.addAbbreviation("char", "C"); } /** * <p>ClassUtils instances should NOT be constructed in standard programming. * Instead, the class should be used as * <code>ClassUtils.getShortClassName(cls)</code>.</p> * * <p>This constructor is public to permit tools that require a JavaBean * instance to operate.</p> */ public ClassUtils() { super(); } // Short class name // ---------------------------------------------------------------------- /** * <p>Gets the class name minus the package name from a String.</p> * <p>The string passed in is assumed to be a class name - it is not checked.</p> * * @param className the className to get the short name for * @return the class name of the class without the package name or an empty string */ public static String getShortClassName(String className) { if (className == null) { return StringUtils.EMPTY; } if (className.length() == 0) { return StringUtils.EMPTY; } StringBuilder arrayPrefix = new StringBuilder(); // Handle array encoding if (className.startsWith("[")) { while (className.charAt(0) == '[') { className = className.substring(1); arrayPrefix.append("[]"); } // Strip Object type encoding if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') { className = className.substring(1, className.length() - 1); } } if (ClassUtils.reverseAbbreviationMap.containsKey(className)) { className = ClassUtils.reverseAbbreviationMap.get(className); } int lastDotIdx = className.lastIndexOf(ClassUtils.PACKAGE_SEPARATOR_CHAR); int innerIdx = className.indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR, lastDotIdx == -1 ? 0 : lastDotIdx + 1); String out = className.substring(lastDotIdx + 1); if (innerIdx != -1) { out = out.replace(ClassUtils.INNER_CLASS_SEPARATOR_CHAR, ClassUtils.PACKAGE_SEPARATOR_CHAR); } return out + arrayPrefix; } // ---------------------------------------------------------------------- /** * <p>Gets the canonical name minus the package name from a <code>Class</code>.</p> * * @param cls the class to get the short name for. * @return the canonical name without the package name or an empty string * @since 2.4 */ public static String getShortCanonicalName(final Class<?> cls) { if (cls == null) { return StringUtils.EMPTY; } return ClassUtils.getShortCanonicalName(cls.getName()); } /** * <p>Gets the canonical name minus the package name from a String.</p> * <p>The string passed in is assumed to be a canonical name - it is not checked.</p> * * @param canonicalName the class name to get the short name for * @return the canonical name of the class without the package name or an empty string * @since 2.4 */ public static String getShortCanonicalName(final String canonicalName) { return ClassUtils.getShortClassName(ClassUtils.getCanonicalName(canonicalName)); } // Package name // ---------------------------------------------------------------------- /** * <p>Converts a given name of class into canonical format. * If name of class is not a name of array class it returns unchanged name.</p> * <p>Example: * <ul> * <li><code>getCanonicalName("[I") = "int[]"</code></li> * <li><code>getCanonicalName("[Ljava.lang.String;") = "java.lang.String[]"</code></li> * <li><code>getCanonicalName("java.lang.String") = "java.lang.String"</code></li> * </ul> * </p> * * @param className the name of class * @return canonical form of class name * @since 2.4 */ private static String getCanonicalName(String className) { // if (!StringUtils.isEmpty(className)) { int sz = className.length(); char[] chs = new char[sz]; int count = 0; for (int i = 0; i < sz; i++) { if (!Character.isWhitespace(className.charAt(i))) { chs[count++] = className.charAt(i); } } if (count != sz) { className = new String(chs, 0, count); } } // if (className == null) { return null; } else { int dim = 0; while (className.startsWith("[")) { dim++; className = className.substring(1); } if (dim < 1) { return className; } else { if (className.startsWith("L")) { className = className.substring(1, className.endsWith(";") ? className.length() - 1 : className.length()); } else { if (className.length() > 0) { className = ClassUtils.reverseAbbreviationMap.get(className.substring(0, 1)); } } StringBuilder canonicalClassNameBuffer = new StringBuilder(className); for (int i = 0; i < dim; i++) { canonicalClassNameBuffer.append("[]"); } return canonicalClassNameBuffer.toString(); } } } /**获取方法的标识代码,在不考虑其所属类的情况下。*/ public static String getDescName(final Class<?> type) { if (type == Void.class) { return "void "; } else if (type.isPrimitive()) { return ClassUtils.getShortCanonicalName(type); } else if (type.isArray()) { return type.getComponentType().getName() + "[]"; } else { return type.getName(); } } /**获取方法的标识代码,在不考虑其所属类的情况下。 * 格式为:<code><修饰符> <返回值> <类名>.<方法名>(<参数签名列表>)</code>*/ public static String getDescNameWithOutModifiers(final Method method) { //public void addChild(org.noe.safety.services.SYS_TB_MenuTree) StringBuffer str = new StringBuffer(""); //2.返回值 Class<?> returnType = method.getReturnType(); str.append(ClassUtils.getDescName(returnType) + " "); //3.方法名 Class<?> decType = method.getDeclaringClass(); str.append(decType.getName()); str.append("."); str.append(method.getName()); //4.方法签名 Class<?>[] paramTypes = method.getParameterTypes(); str.append("("); if (paramTypes != null) { for (int j = 0; j < paramTypes.length; j++) { str.append(ClassUtils.getDescName(paramTypes[j])); if (j < paramTypes.length - 1) { str.append(","); } } } str.append(")"); // return str.toString(); } }