|
Java example source code file (ClassUtils.java)
This example Java source code file (ClassUtils.java) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
Learn more about this Java project at its project page.
The ClassUtils.java Java example source code
/*
* 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 org.apache.commons.lang3;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.mutable.MutableObject;
/**
* <p>Operates on classes without using reflection.
*
* <p>This class handles invalid {@code null} inputs as best it can.
* Each method documents its behaviour in more detail.</p>
*
* <p>The notion of a {@code canonical name} includes the human
* readable name for the type, for example {@code int[]}. The
* non-canonical method variants work with the JVM names, such as
* {@code [I}. </p>
*
* @since 2.0
*/
public class ClassUtils {
/**
* Inclusivity literals for {@link #hierarchy(Class, Interfaces)}.
* @since 3.2
*/
public enum Interfaces {
INCLUDE, EXCLUDE
}
/**
* The package separator character: <code>'.' == {@value}.
*/
public static final char PACKAGE_SEPARATOR_CHAR = '.';
/**
* The package separator String: <code>".".
*/
public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
/**
* The inner class separator character: <code>'$' == {@value}.
*/
public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
/**
* The inner class separator String: {@code "$"}.
*/
public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
/**
* Maps primitive {@code Class}es to their corresponding wrapper {@code Class}.
*/
private static final Map<Class>, Class>> primitiveWrapperMap = new HashMap, Class>>();
static {
primitiveWrapperMap.put(Boolean.TYPE, Boolean.class);
primitiveWrapperMap.put(Byte.TYPE, Byte.class);
primitiveWrapperMap.put(Character.TYPE, Character.class);
primitiveWrapperMap.put(Short.TYPE, Short.class);
primitiveWrapperMap.put(Integer.TYPE, Integer.class);
primitiveWrapperMap.put(Long.TYPE, Long.class);
primitiveWrapperMap.put(Double.TYPE, Double.class);
primitiveWrapperMap.put(Float.TYPE, Float.class);
primitiveWrapperMap.put(Void.TYPE, Void.TYPE);
}
/**
* Maps wrapper {@code Class}es to their corresponding primitive types.
*/
private static final Map<Class>, Class>> wrapperPrimitiveMap = new HashMap, Class>>();
static {
for (final Map.Entry<Class>, Class>> entry : primitiveWrapperMap.entrySet()) {
final Class<?> primitiveClass = entry.getKey();
final Class<?> wrapperClass = entry.getValue();
if (!primitiveClass.equals(wrapperClass)) {
wrapperPrimitiveMap.put(wrapperClass, primitiveClass);
}
}
}
/**
* Maps a primitive class name to its corresponding abbreviation used in array class names.
*/
private static final Map<String, String> abbreviationMap;
/**
* Maps an abbreviation used in array class names to corresponding primitive class name.
*/
private static final Map<String, String> reverseAbbreviationMap;
/**
* Feed abbreviation maps
*/
static {
final Map<String, String> m = new HashMap();
m.put("int", "I");
m.put("boolean", "Z");
m.put("float", "F");
m.put("long", "J");
m.put("short", "S");
m.put("byte", "B");
m.put("double", "D");
m.put("char", "C");
m.put("void", "V");
final Map<String, String> r = new HashMap();
for (final Map.Entry<String, String> e : m.entrySet()) {
r.put(e.getValue(), e.getKey());
}
abbreviationMap = Collections.unmodifiableMap(m);
reverseAbbreviationMap = Collections.unmodifiableMap(r);
}
/**
* <p>ClassUtils instances should NOT be constructed in standard programming.
* Instead, the class should be used as
* {@code ClassUtils.getShortClassName(cls)}.</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 for an {@code Object}.
*
* @param object the class to get the short name for, may be null
* @param valueIfNull the value to return if null
* @return the class name of the object without the package name, or the null value
*/
public static String getShortClassName(final Object object, final String valueIfNull) {
if (object == null) {
return valueIfNull;
}
return getShortClassName(object.getClass());
}
/**
* <p>Gets the class name minus the package name from a {@code Class}.
*
* <p>Consider using the Java 5 API {@link Class#getSimpleName()} instead.
* The one known difference is that this code will return {@code "Map.Entry"} while
* the {@code java.lang.Class} variant will simply return {@code "Entry"}. </p>
*
* @param cls the class to get the short name for.
* @return the class name without the package name or an empty string
*/
public static String getShortClassName(final Class<?> cls) {
if (cls == null) {
return StringUtils.EMPTY;
}
return getShortClassName(cls.getName());
}
/**
* <p>Gets the class name minus the package name from a String.
*
* <p>The string passed in is assumed to be a class name - it is not checked.
* <p>Note that this method differs from Class.getSimpleName() in that this will
* return {@code "Map.Entry"} whilst the {@code java.lang.Class} variant will simply
* return {@code "Entry"}. </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 (StringUtils.isEmpty(className)) {
return StringUtils.EMPTY;
}
final 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 (reverseAbbreviationMap.containsKey(className)) {
className = reverseAbbreviationMap.get(className);
}
}
final int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
final int innerIdx = className.indexOf(
INNER_CLASS_SEPARATOR_CHAR, lastDotIdx == -1 ? 0 : lastDotIdx + 1);
String out = className.substring(lastDotIdx + 1);
if (innerIdx != -1) {
out = out.replace(INNER_CLASS_SEPARATOR_CHAR, PACKAGE_SEPARATOR_CHAR);
}
return out + arrayPrefix;
}
/**
* <p>Null-safe version of aClass.getSimpleName()
*
* @param cls the class for which to get the simple name.
* @return the simple class name.
* @since 3.0
* @see Class#getSimpleName()
*/
public static String getSimpleName(final Class<?> cls) {
if (cls == null) {
return StringUtils.EMPTY;
}
return cls.getSimpleName();
}
/**
* <p>Null-safe version of aClass.getSimpleName()
*
* @param object the object for which to get the simple class name.
* @param valueIfNull the value to return if <code>object is null
* @return the simple class name.
* @since 3.0
* @see Class#getSimpleName()
*/
public static String getSimpleName(final Object object, final String valueIfNull) {
if (object == null) {
return valueIfNull;
}
return getSimpleName(object.getClass());
}
// Package name
// ----------------------------------------------------------------------
/**
* <p>Gets the package name of an {@code Object}.
*
* @param object the class to get the package name for, may be null
* @param valueIfNull the value to return if null
* @return the package name of the object, or the null value
*/
public static String getPackageName(final Object object, final String valueIfNull) {
if (object == null) {
return valueIfNull;
}
return getPackageName(object.getClass());
}
/**
* <p>Gets the package name of a {@code Class}.
*
* @param cls the class to get the package name for, may be {@code null}.
* @return the package name or an empty string
*/
public static String getPackageName(final Class<?> cls) {
if (cls == null) {
return StringUtils.EMPTY;
}
return getPackageName(cls.getName());
}
/**
* <p>Gets the package name from a {@code String}.
*
* <p>The string passed in is assumed to be a class name - it is not checked.
* <p>If the class is unpackaged, return an empty string.
*
* @param className the className to get the package name for, may be {@code null}
* @return the package name or an empty string
*/
public static String getPackageName(String className) {
if (StringUtils.isEmpty(className)) {
return StringUtils.EMPTY;
}
// Strip array encoding
while (className.charAt(0) == '[') {
className = className.substring(1);
}
// Strip Object type encoding
if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
className = className.substring(1);
}
final int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
if (i == -1) {
return StringUtils.EMPTY;
}
return className.substring(0, i);
}
// Abbreviated name
// ----------------------------------------------------------------------
/**
* <p>Gets the abbreviated name of a {@code Class}.
*
* @param cls the class to get the abbreviated name for, may be {@code null}
* @param len the desired length of the abbreviated name
* @return the abbreviated name or an empty string
* @throws IllegalArgumentException if len <= 0
* @see #getAbbreviatedName(String, int)
* @since 3.4
*/
public static String getAbbreviatedName(final Class<?> cls, int len) {
if (cls == null) {
return StringUtils.EMPTY;
}
return getAbbreviatedName(cls.getName(), len);
}
/**
* <p>Gets the abbreviated class name from a {@code String}.
*
* <p>The string passed in is assumed to be a class name - it is not checked.
*
* <p>The abbreviation algorithm will shorten the class name, usually without
* significant loss of meaning.</p>
* <p>The abbreviated class name will always include the complete package hierarchy.
* If enough space is available, rightmost sub-packages will be displayed in full
* length.</p>
*
* <p>The following table illustrates the algorithm:
* <table summary="abbreviation examples">
* <tr>className | len | return | |
* <tr>