Class ClassUtils
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic booleancanAddTo(Collection<?> value) Determines whether the specified collection supports modification operations (e.g.,add(),remove()).static booleanDetermines whether the specified map supports modification operations (e.g.,put(),remove()).static StringReturns the fully-qualified class name for the specified object.static StringclassNameSimple(Object value) Returns the simple (non-qualified) class name for the specified object.static StringclassNameSimpleQualified(Object value) Returns the simple qualified class name for the specified object.static Class<?>[]getClasses(Object... args) Returns the class types for the specified arguments.static Object[]getMatchingArgs(Class<?>[] paramTypes, Object... args) Matches arguments to a list of parameter types.static Class<?>Attempts to unwrap a proxy object and return the underlying "real" class.static booleanstatic booleanstatic booleansetAccessible(Constructor<?> x) Attempts to callx.setAccessible(and quietly ignores security exceptions.true )static booleanAttempts to callx.setAccessible(and quietly ignores security exceptions.true )static booleanAttempts to callx.setAccessible(and quietly ignores security exceptions.true )static Class<?>Returns the specified type as aClass .
-
Field Details
-
NOT_VOID
Predicate check to filter out void classes.
-
-
Constructor Details
-
ClassUtils
public ClassUtils()
-
-
Method Details
-
canAddTo
Determines whether the specified collection supports modification operations (e.g.,add(),remove()).This method performs a heuristic check based on the collection's class name to determine if it's likely modifiable. It checks whether the class name contains indicators of immutability such as "Immutable", "Unmodifiable", or "Arrays$ArrayList" (which represents the unmodifiable list returned by
Arrays.asList(Object...)).Results are cached for performance, so repeated calls for the same collection type are very fast.
Examples:
// Modifiable collections canAddTo(new ArrayList<>());// true canAddTo(new LinkedList<>());// true canAddTo(new HashSet<>());// true // Unmodifiable collections canAddTo(Collections.unmodifiableList(...));// false canAddTo(Collections.unmodifiableSet(...));// false canAddTo(Arrays.asList("a" ,"b" ));// false canAddTo(List.of("a" ,"b" ));// false (ImmutableCollections) Note: This is a heuristic check based on naming conventions. It does not attempt to actually modify the collection, so it never throws exceptions. However, it may produce false positives for custom collection implementations with misleading names.
- Parameters:
value- The collection to check. Must not benull .- Returns:
true if the collection is likely modifiable,false if it's likely unmodifiable.- Throws:
IllegalArgumentException- If value isnull .
-
canPutTo
Determines whether the specified map supports modification operations (e.g.,put(),remove()).This method performs a heuristic check based on the map's class name to determine if it's likely modifiable. It checks whether the class name contains indicators of immutability such as "Immutable", "Unmodifiable", or "Arrays$ArrayList" (which represents unmodifiable collections).
Results are cached for performance, so repeated calls for the same map type are very fast.
Examples:
// Modifiable maps canPutTo(new HashMap<>());// true canPutTo(new LinkedHashMap<>());// true canPutTo(new TreeMap<>());// true // Unmodifiable maps canPutTo(Collections.unmodifiableMap(...));// false canPutTo(Map.of("key" ,"value" ));// false (ImmutableCollections) Note: This is a heuristic check based on naming conventions. It does not attempt to actually modify the map, so it never throws exceptions. However, it may produce false positives for custom map implementations with misleading names.
- Parameters:
value- The map to check. Must not benull .- Returns:
true if the map is likely modifiable,false if it's likely unmodifiable.- Throws:
IllegalArgumentException- If value isnull .
-
className
Returns the fully-qualified class name for the specified object.This method returns the canonical JVM class name including the full package path.
Examples:
// Regular classes className(String.class );// "java.lang.String" className(new HashMap<>());// "java.util.HashMap" // Inner classes className(Map.Entry.class );// "java.util.Map$Entry" // Primitives className(int .class );// "int" className(boolean .class );// "boolean" // Arrays className(String[].class );// "[Ljava.lang.String;" className(int [].class );// "[I" className(String[][].class );// "[[Ljava.lang.String;" // Null className(null );// null - Parameters:
value- The object to get the class name for.- Returns:
- The name of the class or
null if the value was null.
-
classNameSimple
Returns the simple (non-qualified) class name for the specified object.This method returns only the simple class name without any package or outer class information. For inner classes, only the innermost class name is returned.
Examples:
// Regular classes simpleClassName(String.class );// "String" simpleClassName(new HashMap<>());// "HashMap" // Inner classes simpleClassName(Map.Entry.class );// "Entry" // Primitives simpleClassName(int .class );// "int" simpleClassName(boolean .class );// "boolean" // Arrays simpleClassName(String[].class );// "String[]" simpleClassName(int [].class );// "int[]" simpleClassName(String[][].class );// "String[][]" // Null simpleClassName(null );// null - Parameters:
value- The object to get the simple class name for.- Returns:
- The simple name of the class or
null if the value was null.
-
classNameSimpleQualified
Returns the simple qualified class name for the specified object.This returns the simple class name including outer class names, but without the package. Inner class separators ($) are replaced with dots (.). Array types are properly formatted with brackets.
Examples:
// Regular classes simpleQualifiedClassName(String.class );// "String" simpleQualifiedClassName(new HashMap<>());// "HashMap" // Inner classes simpleQualifiedClassName(Map.Entry.class );// "Map.Entry" simpleQualifiedClassName(Outer.Inner.Deep.class );// "Outer.Inner.Deep" // Primitives simpleQualifiedClassName(int .class );// "int" simpleQualifiedClassName(boolean .class );// "boolean" // Object arrays simpleQualifiedClassName(String[].class );// "String[]" simpleQualifiedClassName(Map.Entry[].class );// "Map.Entry[]" simpleQualifiedClassName(String[][].class );// "String[][]" // Primitive arrays simpleQualifiedClassName(int [].class );// "int[]" simpleQualifiedClassName(boolean [][].class );// "boolean[][]" // Null simpleQualifiedClassName(null );// null - Parameters:
value- The object to get the simple qualified class name for.- Returns:
- The simple qualified name of the class or
null if the value was null.
-
getClasses
Returns the class types for the specified arguments.- Parameters:
args- The objects we're getting the classes of.- Returns:
- The classes of the arguments.
-
getMatchingArgs
Matches arguments to a list of parameter types.This method intelligently matches a variable number of arguments to a fixed set of parameter types, handling cases where arguments may be provided in a different order, or where some arguments are missing or extra arguments are provided. This is particularly useful for reflective method/constructor invocation where parameter order flexibility is desired.
Matching Rules:
- If arguments already match parameter types in order and count, they are returned as-is (fast path)
- Otherwise, each parameter type is matched with the first compatible argument
- Extra arguments are ignored
- Missing parameters are left as
null - Primitive types are automatically matched with their wrapper equivalents
- Type hierarchy is respected (subclasses match parent parameters)
Examples:
// Already in correct order - fast path returns original array Class<?>[] types = {String.class , Integer.class }; Object[] args = {"hello" , 42}; Object[] result = getMatchingArgs(types, args);// Returns: ["hello", 42] // Arguments in wrong order - method reorders them Class<?>[] types = {Integer.class , String.class }; Object[] args = {"hello" , 42}; Object[] result = getMatchingArgs(types, args);// Returns: [42, "hello"] // Extra arguments are ignored Class<?>[] types = {String.class }; Object[] args = {"hello" , 42,true }; Object[] result = getMatchingArgs(types, args);// Returns: ["hello"] // Missing arguments become null Class<?>[] types = {String.class , Integer.class , Boolean.class }; Object[] args = {"hello" }; Object[] result = getMatchingArgs(types, args);// Returns: ["hello", null, null] // Handles primitive types and their wrappers Class<?>[] types = {int .class , String.class }; Object[] args = {"hello" , 42};// Integer object matches int.class Object[] result = getMatchingArgs(types, args);// Returns: [42, "hello"] // Respects type hierarchy - subclasses match parent types Class<?>[] types = {Number.class , String.class }; Object[] args = {"hello" , 42};// Integer extends Number Object[] result = getMatchingArgs(types, args);// Returns: [42, "hello"] This method is used internally by
ClassInfo,MethodInfo, andConstructorInfoto provide flexible parameter matching during reflective invocation.- Parameters:
paramTypes- The parameter types to match against. Must not benull .args- The arguments to match to the parameter types. Can be empty or containnull values.- Returns:
- An array of arguments matched to the parameter types. The returned array will always have
the same length as
paramTypes. Returns the originalargsarray if it already matches (fast path optimization).
-
getProxyFor
Attempts to unwrap a proxy object and return the underlying "real" class.This method handles several common proxy types used in Java applications:
- JDK Dynamic Proxies - Created via
Proxy.newProxyInstance(java.lang.ClassLoader, java.lang.Class<?>[], java.lang.reflect.InvocationHandler) - CGLIB Proxies - Created by Spring's CGLIB enhancer (class name contains
"$$EnhancerBySpringCGLIB$$" ) - Javassist Proxies - Created by Javassist proxy factory (class name contains
"_$$_javassist" or"_$$_jvst" ) - ByteBuddy Proxies - Created by ByteBuddy (class name contains
"$ByteBuddy$" )
Example:
// Get the real class behind a Spring proxy @Service class MyService {} MyService proxy = applicationContext.getBean(MyService.class ); Class<?> realClass = ClassUtils.getProxyFor (proxy);// Returns MyService.class instead of the CGLIB proxy class Notes:
- For JDK dynamic proxies, returns the first interface implemented by the proxy
- For CGLIB/Javassist/ByteBuddy proxies, returns the superclass
- For Spring CGLIB proxies with a
getTargetClass() method, invokes that method for more accurate results - Returns
null if the object is not a recognized proxy type
- Parameters:
o- The object to unwrap. Can benull .- Returns:
- The underlying class, or
null if:- The object is
null - The object is not a recognized proxy type
- The proxy cannot be unwrapped
- The object is
- JDK Dynamic Proxies - Created via
-
isNotVoid
- Parameters:
c- The class to check.- Returns:
false if the specific class isnull or orvoid .class Voidor has the simple name"Void .
-
isVoid
- Parameters:
c- The class to check.- Returns:
true if the specific class isnull or orvoid .class Voidor has the simple name"Void .
-
setAccessible
Attempts to callx.setAccessible(and quietly ignores security exceptions.true )- Parameters:
x- The constructor.- Returns:
true if call was successful.
-
setAccessible
Attempts to callx.setAccessible(and quietly ignores security exceptions.true )- Parameters:
x- The field.- Returns:
true if call was successful.
-
setAccessible
Attempts to callx.setAccessible(and quietly ignores security exceptions.true )- Parameters:
x- The method.- Returns:
true if call was successful.
-
toClass
Returns the specified type as aClass .If it's already a
Class , it just does a cast.
If it's aParameterizedType , it returns the raw type.- Parameters:
t- The type to convert.- Returns:
- The type converted to a
Class , ornull if it could not be converted.
-