001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3; 018 019import java.lang.reflect.Method; 020import java.lang.reflect.Modifier; 021import java.util.ArrayList; 022import java.util.Collections; 023import java.util.HashMap; 024import java.util.HashSet; 025import java.util.Iterator; 026import java.util.LinkedHashSet; 027import java.util.List; 028import java.util.Map; 029import java.util.Set; 030 031import org.apache.commons.lang3.mutable.MutableObject; 032 033/** 034 * <p>Operates on classes without using reflection.</p> 035 * 036 * <p>This class handles invalid {@code null} inputs as best it can. 037 * Each method documents its behaviour in more detail.</p> 038 * 039 * <p>The notion of a {@code canonical name} includes the human 040 * readable name for the type, for example {@code int[]}. The 041 * non-canonical method variants work with the JVM names, such as 042 * {@code [I}. </p> 043 * 044 * @since 2.0 045 * @version $Id: ClassUtils.java 1534839 2013-10-22 22:48:58Z mbenson $ 046 */ 047public class ClassUtils { 048 /** 049 * Inclusivity literals for {@link #hierarchy(Class, Interfaces)}. 050 * @since 3.2 051 */ 052 public enum Interfaces { 053 INCLUDE, EXCLUDE; 054 } 055 056 /** 057 * The package separator character: <code>'.' == {@value}</code>. 058 */ 059 public static final char PACKAGE_SEPARATOR_CHAR = '.'; 060 061 /** 062 * The package separator String: <code>"."</code>. 063 */ 064 public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR); 065 066 /** 067 * The inner class separator character: <code>'$' == {@value}</code>. 068 */ 069 public static final char INNER_CLASS_SEPARATOR_CHAR = '$'; 070 071 /** 072 * The inner class separator String: {@code "$"}. 073 */ 074 public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR); 075 076 /** 077 * Maps primitive {@code Class}es to their corresponding wrapper {@code Class}. 078 */ 079 private static final Map<Class<?>, Class<?>> primitiveWrapperMap = new HashMap<Class<?>, Class<?>>(); 080 static { 081 primitiveWrapperMap.put(Boolean.TYPE, Boolean.class); 082 primitiveWrapperMap.put(Byte.TYPE, Byte.class); 083 primitiveWrapperMap.put(Character.TYPE, Character.class); 084 primitiveWrapperMap.put(Short.TYPE, Short.class); 085 primitiveWrapperMap.put(Integer.TYPE, Integer.class); 086 primitiveWrapperMap.put(Long.TYPE, Long.class); 087 primitiveWrapperMap.put(Double.TYPE, Double.class); 088 primitiveWrapperMap.put(Float.TYPE, Float.class); 089 primitiveWrapperMap.put(Void.TYPE, Void.TYPE); 090 } 091 092 /** 093 * Maps wrapper {@code Class}es to their corresponding primitive types. 094 */ 095 private static final Map<Class<?>, Class<?>> wrapperPrimitiveMap = new HashMap<Class<?>, Class<?>>(); 096 static { 097 for (final Class<?> primitiveClass : primitiveWrapperMap.keySet()) { 098 final Class<?> wrapperClass = primitiveWrapperMap.get(primitiveClass); 099 if (!primitiveClass.equals(wrapperClass)) { 100 wrapperPrimitiveMap.put(wrapperClass, primitiveClass); 101 } 102 } 103 } 104 105 /** 106 * Maps a primitive class name to its corresponding abbreviation used in array class names. 107 */ 108 private static final Map<String, String> abbreviationMap; 109 110 /** 111 * Maps an abbreviation used in array class names to corresponding primitive class name. 112 */ 113 private static final Map<String, String> reverseAbbreviationMap; 114 115 /** 116 * Feed abbreviation maps 117 */ 118 static { 119 final Map<String, String> m = new HashMap<String, String>(); 120 m.put("int", "I"); 121 m.put("boolean", "Z"); 122 m.put("float", "F"); 123 m.put("long", "J"); 124 m.put("short", "S"); 125 m.put("byte", "B"); 126 m.put("double", "D"); 127 m.put("char", "C"); 128 m.put("void", "V"); 129 final Map<String, String> r = new HashMap<String, String>(); 130 for (Map.Entry<String, String> e : m.entrySet()) { 131 r.put(e.getValue(), e.getKey()); 132 } 133 abbreviationMap = Collections.unmodifiableMap(m); 134 reverseAbbreviationMap = Collections.unmodifiableMap(r); 135 } 136 137 /** 138 * <p>ClassUtils instances should NOT be constructed in standard programming. 139 * Instead, the class should be used as 140 * {@code ClassUtils.getShortClassName(cls)}.</p> 141 * 142 * <p>This constructor is public to permit tools that require a JavaBean 143 * instance to operate.</p> 144 */ 145 public ClassUtils() { 146 super(); 147 } 148 149 // Short class name 150 // ---------------------------------------------------------------------- 151 /** 152 * <p>Gets the class name minus the package name for an {@code Object}.</p> 153 * 154 * @param object the class to get the short name for, may be null 155 * @param valueIfNull the value to return if null 156 * @return the class name of the object without the package name, or the null value 157 */ 158 public static String getShortClassName(final Object object, final String valueIfNull) { 159 if (object == null) { 160 return valueIfNull; 161 } 162 return getShortClassName(object.getClass()); 163 } 164 165 /** 166 * <p>Gets the class name minus the package name from a {@code Class}.</p> 167 * 168 * <p>Consider using the Java 5 API {@link Class#getSimpleName()} instead. 169 * The one known difference is that this code will return {@code "Map.Entry"} while 170 * the {@code java.lang.Class} variant will simply return {@code "Entry"}. </p> 171 * 172 * @param cls the class to get the short name for. 173 * @return the class name without the package name or an empty string 174 */ 175 public static String getShortClassName(final Class<?> cls) { 176 if (cls == null) { 177 return StringUtils.EMPTY; 178 } 179 return getShortClassName(cls.getName()); 180 } 181 182 /** 183 * <p>Gets the class name minus the package name from a String.</p> 184 * 185 * <p>The string passed in is assumed to be a class name - it is not checked.</p> 186 187 * <p>Note that this method differs from Class.getSimpleName() in that this will 188 * return {@code "Map.Entry"} whilst the {@code java.lang.Class} variant will simply 189 * return {@code "Entry"}. </p> 190 * 191 * @param className the className to get the short name for 192 * @return the class name of the class without the package name or an empty string 193 */ 194 public static String getShortClassName(String className) { 195 if (StringUtils.isEmpty(className)) { 196 return StringUtils.EMPTY; 197 } 198 199 final StringBuilder arrayPrefix = new StringBuilder(); 200 201 // Handle array encoding 202 if (className.startsWith("[")) { 203 while (className.charAt(0) == '[') { 204 className = className.substring(1); 205 arrayPrefix.append("[]"); 206 } 207 // Strip Object type encoding 208 if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') { 209 className = className.substring(1, className.length() - 1); 210 } 211 212 if (reverseAbbreviationMap.containsKey(className)) { 213 className = reverseAbbreviationMap.get(className); 214 } 215 } 216 217 final int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR); 218 final int innerIdx = className.indexOf( 219 INNER_CLASS_SEPARATOR_CHAR, lastDotIdx == -1 ? 0 : lastDotIdx + 1); 220 String out = className.substring(lastDotIdx + 1); 221 if (innerIdx != -1) { 222 out = out.replace(INNER_CLASS_SEPARATOR_CHAR, PACKAGE_SEPARATOR_CHAR); 223 } 224 return out + arrayPrefix; 225 } 226 227 /** 228 * <p>Null-safe version of <code>aClass.getSimpleName()</code></p> 229 * 230 * @param cls the class for which to get the simple name. 231 * @return the simple class name. 232 * @since 3.0 233 * @see Class#getSimpleName() 234 */ 235 public static String getSimpleName(final Class<?> cls) { 236 if (cls == null) { 237 return StringUtils.EMPTY; 238 } 239 return cls.getSimpleName(); 240 } 241 242 /** 243 * <p>Null-safe version of <code>aClass.getSimpleName()</code></p> 244 * 245 * @param object the object for which to get the simple class name. 246 * @param valueIfNull the value to return if <code>object</code> is <code>null</code> 247 * @return the simple class name. 248 * @since 3.0 249 * @see Class#getSimpleName() 250 */ 251 public static String getSimpleName(final Object object, final String valueIfNull) { 252 if (object == null) { 253 return valueIfNull; 254 } 255 return getSimpleName(object.getClass()); 256 } 257 258 // Package name 259 // ---------------------------------------------------------------------- 260 /** 261 * <p>Gets the package name of an {@code Object}.</p> 262 * 263 * @param object the class to get the package name for, may be null 264 * @param valueIfNull the value to return if null 265 * @return the package name of the object, or the null value 266 */ 267 public static String getPackageName(final Object object, final String valueIfNull) { 268 if (object == null) { 269 return valueIfNull; 270 } 271 return getPackageName(object.getClass()); 272 } 273 274 /** 275 * <p>Gets the package name of a {@code Class}.</p> 276 * 277 * @param cls the class to get the package name for, may be {@code null}. 278 * @return the package name or an empty string 279 */ 280 public static String getPackageName(final Class<?> cls) { 281 if (cls == null) { 282 return StringUtils.EMPTY; 283 } 284 return getPackageName(cls.getName()); 285 } 286 287 /** 288 * <p>Gets the package name from a {@code String}.</p> 289 * 290 * <p>The string passed in is assumed to be a class name - it is not checked.</p> 291 * <p>If the class is unpackaged, return an empty string.</p> 292 * 293 * @param className the className to get the package name for, may be {@code null} 294 * @return the package name or an empty string 295 */ 296 public static String getPackageName(String className) { 297 if (StringUtils.isEmpty(className)) { 298 return StringUtils.EMPTY; 299 } 300 301 // Strip array encoding 302 while (className.charAt(0) == '[') { 303 className = className.substring(1); 304 } 305 // Strip Object type encoding 306 if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') { 307 className = className.substring(1); 308 } 309 310 final int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR); 311 if (i == -1) { 312 return StringUtils.EMPTY; 313 } 314 return className.substring(0, i); 315 } 316 317 // Superclasses/Superinterfaces 318 // ---------------------------------------------------------------------- 319 /** 320 * <p>Gets a {@code List} of superclasses for the given class.</p> 321 * 322 * @param cls the class to look up, may be {@code null} 323 * @return the {@code List} of superclasses in order going up from this one 324 * {@code null} if null input 325 */ 326 public static List<Class<?>> getAllSuperclasses(final Class<?> cls) { 327 if (cls == null) { 328 return null; 329 } 330 final List<Class<?>> classes = new ArrayList<Class<?>>(); 331 Class<?> superclass = cls.getSuperclass(); 332 while (superclass != null) { 333 classes.add(superclass); 334 superclass = superclass.getSuperclass(); 335 } 336 return classes; 337 } 338 339 /** 340 * <p>Gets a {@code List} of all interfaces implemented by the given 341 * class and its superclasses.</p> 342 * 343 * <p>The order is determined by looking through each interface in turn as 344 * declared in the source file and following its hierarchy up. Then each 345 * superclass is considered in the same way. Later duplicates are ignored, 346 * so the order is maintained.</p> 347 * 348 * @param cls the class to look up, may be {@code null} 349 * @return the {@code List} of interfaces in order, 350 * {@code null} if null input 351 */ 352 public static List<Class<?>> getAllInterfaces(final Class<?> cls) { 353 if (cls == null) { 354 return null; 355 } 356 357 final LinkedHashSet<Class<?>> interfacesFound = new LinkedHashSet<Class<?>>(); 358 getAllInterfaces(cls, interfacesFound); 359 360 return new ArrayList<Class<?>>(interfacesFound); 361 } 362 363 /** 364 * Get the interfaces for the specified class. 365 * 366 * @param cls the class to look up, may be {@code null} 367 * @param interfacesFound the {@code Set} of interfaces for the class 368 */ 369 private static void getAllInterfaces(Class<?> cls, final HashSet<Class<?>> interfacesFound) { 370 while (cls != null) { 371 final Class<?>[] interfaces = cls.getInterfaces(); 372 373 for (final Class<?> i : interfaces) { 374 if (interfacesFound.add(i)) { 375 getAllInterfaces(i, interfacesFound); 376 } 377 } 378 379 cls = cls.getSuperclass(); 380 } 381 } 382 383 // Convert list 384 // ---------------------------------------------------------------------- 385 /** 386 * <p>Given a {@code List} of class names, this method converts them into classes.</p> 387 * 388 * <p>A new {@code List} is returned. If the class name cannot be found, {@code null} 389 * is stored in the {@code List}. If the class name in the {@code List} is 390 * {@code null}, {@code null} is stored in the output {@code List}.</p> 391 * 392 * @param classNames the classNames to change 393 * @return a {@code List} of Class objects corresponding to the class names, 394 * {@code null} if null input 395 * @throws ClassCastException if classNames contains a non String entry 396 */ 397 public static List<Class<?>> convertClassNamesToClasses(final List<String> classNames) { 398 if (classNames == null) { 399 return null; 400 } 401 final List<Class<?>> classes = new ArrayList<Class<?>>(classNames.size()); 402 for (final String className : classNames) { 403 try { 404 classes.add(Class.forName(className)); 405 } catch (final Exception ex) { 406 classes.add(null); 407 } 408 } 409 return classes; 410 } 411 412 /** 413 * <p>Given a {@code List} of {@code Class} objects, this method converts 414 * them into class names.</p> 415 * 416 * <p>A new {@code List} is returned. {@code null} objects will be copied into 417 * the returned list as {@code null}.</p> 418 * 419 * @param classes the classes to change 420 * @return a {@code List} of class names corresponding to the Class objects, 421 * {@code null} if null input 422 * @throws ClassCastException if {@code classes} contains a non-{@code Class} entry 423 */ 424 public static List<String> convertClassesToClassNames(final List<Class<?>> classes) { 425 if (classes == null) { 426 return null; 427 } 428 final List<String> classNames = new ArrayList<String>(classes.size()); 429 for (final Class<?> cls : classes) { 430 if (cls == null) { 431 classNames.add(null); 432 } else { 433 classNames.add(cls.getName()); 434 } 435 } 436 return classNames; 437 } 438 439 // Is assignable 440 // ---------------------------------------------------------------------- 441 /** 442 * <p>Checks if an array of Classes can be assigned to another array of Classes.</p> 443 * 444 * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each 445 * Class pair in the input arrays. It can be used to check if a set of arguments 446 * (the first parameter) are suitably compatible with a set of method parameter types 447 * (the second parameter).</p> 448 * 449 * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this 450 * method takes into account widenings of primitive classes and 451 * {@code null}s.</p> 452 * 453 * <p>Primitive widenings allow an int to be assigned to a {@code long}, 454 * {@code float} or {@code double}. This method returns the correct 455 * result for these cases.</p> 456 * 457 * <p>{@code Null} may be assigned to any reference type. This method will 458 * return {@code true} if {@code null} is passed in and the toClass is 459 * non-primitive.</p> 460 * 461 * <p>Specifically, this method tests whether the type represented by the 462 * specified {@code Class} parameter can be converted to the type 463 * represented by this {@code Class} object via an identity conversion 464 * widening primitive or widening reference conversion. See 465 * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>, 466 * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p> 467 * 468 * <p><strong>Since Lang 3.0,</strong> this method will default behavior for 469 * calculating assignability between primitive and wrapper types <em>corresponding 470 * to the running Java version</em>; i.e. autoboxing will be the default 471 * behavior in VMs running Java versions >= 1.5.</p> 472 * 473 * @param classArray the array of Classes to check, may be {@code null} 474 * @param toClassArray the array of Classes to try to assign into, may be {@code null} 475 * @return {@code true} if assignment possible 476 */ 477 public static boolean isAssignable(final Class<?>[] classArray, final Class<?>... toClassArray) { 478 return isAssignable(classArray, toClassArray, SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_5)); 479 } 480 481 /** 482 * <p>Checks if an array of Classes can be assigned to another array of Classes.</p> 483 * 484 * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each 485 * Class pair in the input arrays. It can be used to check if a set of arguments 486 * (the first parameter) are suitably compatible with a set of method parameter types 487 * (the second parameter).</p> 488 * 489 * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this 490 * method takes into account widenings of primitive classes and 491 * {@code null}s.</p> 492 * 493 * <p>Primitive widenings allow an int to be assigned to a {@code long}, 494 * {@code float} or {@code double}. This method returns the correct 495 * result for these cases.</p> 496 * 497 * <p>{@code Null} may be assigned to any reference type. This method will 498 * return {@code true} if {@code null} is passed in and the toClass is 499 * non-primitive.</p> 500 * 501 * <p>Specifically, this method tests whether the type represented by the 502 * specified {@code Class} parameter can be converted to the type 503 * represented by this {@code Class} object via an identity conversion 504 * widening primitive or widening reference conversion. See 505 * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>, 506 * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p> 507 * 508 * @param classArray the array of Classes to check, may be {@code null} 509 * @param toClassArray the array of Classes to try to assign into, may be {@code null} 510 * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers 511 * @return {@code true} if assignment possible 512 */ 513 public static boolean isAssignable(Class<?>[] classArray, Class<?>[] toClassArray, final boolean autoboxing) { 514 if (ArrayUtils.isSameLength(classArray, toClassArray) == false) { 515 return false; 516 } 517 if (classArray == null) { 518 classArray = ArrayUtils.EMPTY_CLASS_ARRAY; 519 } 520 if (toClassArray == null) { 521 toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY; 522 } 523 for (int i = 0; i < classArray.length; i++) { 524 if (isAssignable(classArray[i], toClassArray[i], autoboxing) == false) { 525 return false; 526 } 527 } 528 return true; 529 } 530 531 /** 532 * Returns whether the given {@code type} is a primitive or primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, 533 * {@link Short}, {@link Integer}, {@link Long}, {@link Double}, {@link Float}). 534 * 535 * @param type 536 * The class to query or null. 537 * @return true if the given {@code type} is a primitive or primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, 538 * {@link Short}, {@link Integer}, {@link Long}, {@link Double}, {@link Float}). 539 * @since 3.1 540 */ 541 public static boolean isPrimitiveOrWrapper(final Class<?> type) { 542 if (type == null) { 543 return false; 544 } 545 return type.isPrimitive() || isPrimitiveWrapper(type); 546 } 547 548 /** 549 * Returns whether the given {@code type} is a primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, {@link Short}, 550 * {@link Integer}, {@link Long}, {@link Double}, {@link Float}). 551 * 552 * @param type 553 * The class to query or null. 554 * @return true if the given {@code type} is a primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, {@link Short}, 555 * {@link Integer}, {@link Long}, {@link Double}, {@link Float}). 556 * @since 3.1 557 */ 558 public static boolean isPrimitiveWrapper(final Class<?> type) { 559 return wrapperPrimitiveMap.containsKey(type); 560 } 561 562 /** 563 * <p>Checks if one {@code Class} can be assigned to a variable of 564 * another {@code Class}.</p> 565 * 566 * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, 567 * this method takes into account widenings of primitive classes and 568 * {@code null}s.</p> 569 * 570 * <p>Primitive widenings allow an int to be assigned to a long, float or 571 * double. This method returns the correct result for these cases.</p> 572 * 573 * <p>{@code Null} may be assigned to any reference type. This method 574 * will return {@code true} if {@code null} is passed in and the 575 * toClass is non-primitive.</p> 576 * 577 * <p>Specifically, this method tests whether the type represented by the 578 * specified {@code Class} parameter can be converted to the type 579 * represented by this {@code Class} object via an identity conversion 580 * widening primitive or widening reference conversion. See 581 * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>, 582 * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p> 583 * 584 * <p><strong>Since Lang 3.0,</strong> this method will default behavior for 585 * calculating assignability between primitive and wrapper types <em>corresponding 586 * to the running Java version</em>; i.e. autoboxing will be the default 587 * behavior in VMs running Java versions >= 1.5.</p> 588 * 589 * @param cls the Class to check, may be null 590 * @param toClass the Class to try to assign into, returns false if null 591 * @return {@code true} if assignment possible 592 */ 593 public static boolean isAssignable(final Class<?> cls, final Class<?> toClass) { 594 return isAssignable(cls, toClass, SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_5)); 595 } 596 597 /** 598 * <p>Checks if one {@code Class} can be assigned to a variable of 599 * another {@code Class}.</p> 600 * 601 * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, 602 * this method takes into account widenings of primitive classes and 603 * {@code null}s.</p> 604 * 605 * <p>Primitive widenings allow an int to be assigned to a long, float or 606 * double. This method returns the correct result for these cases.</p> 607 * 608 * <p>{@code Null} may be assigned to any reference type. This method 609 * will return {@code true} if {@code null} is passed in and the 610 * toClass is non-primitive.</p> 611 * 612 * <p>Specifically, this method tests whether the type represented by the 613 * specified {@code Class} parameter can be converted to the type 614 * represented by this {@code Class} object via an identity conversion 615 * widening primitive or widening reference conversion. See 616 * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>, 617 * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p> 618 * 619 * @param cls the Class to check, may be null 620 * @param toClass the Class to try to assign into, returns false if null 621 * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers 622 * @return {@code true} if assignment possible 623 */ 624 public static boolean isAssignable(Class<?> cls, final Class<?> toClass, final boolean autoboxing) { 625 if (toClass == null) { 626 return false; 627 } 628 // have to check for null, as isAssignableFrom doesn't 629 if (cls == null) { 630 return !toClass.isPrimitive(); 631 } 632 //autoboxing: 633 if (autoboxing) { 634 if (cls.isPrimitive() && !toClass.isPrimitive()) { 635 cls = primitiveToWrapper(cls); 636 if (cls == null) { 637 return false; 638 } 639 } 640 if (toClass.isPrimitive() && !cls.isPrimitive()) { 641 cls = wrapperToPrimitive(cls); 642 if (cls == null) { 643 return false; 644 } 645 } 646 } 647 if (cls.equals(toClass)) { 648 return true; 649 } 650 if (cls.isPrimitive()) { 651 if (toClass.isPrimitive() == false) { 652 return false; 653 } 654 if (Integer.TYPE.equals(cls)) { 655 return Long.TYPE.equals(toClass) 656 || Float.TYPE.equals(toClass) 657 || Double.TYPE.equals(toClass); 658 } 659 if (Long.TYPE.equals(cls)) { 660 return Float.TYPE.equals(toClass) 661 || Double.TYPE.equals(toClass); 662 } 663 if (Boolean.TYPE.equals(cls)) { 664 return false; 665 } 666 if (Double.TYPE.equals(cls)) { 667 return false; 668 } 669 if (Float.TYPE.equals(cls)) { 670 return Double.TYPE.equals(toClass); 671 } 672 if (Character.TYPE.equals(cls)) { 673 return Integer.TYPE.equals(toClass) 674 || Long.TYPE.equals(toClass) 675 || Float.TYPE.equals(toClass) 676 || Double.TYPE.equals(toClass); 677 } 678 if (Short.TYPE.equals(cls)) { 679 return Integer.TYPE.equals(toClass) 680 || Long.TYPE.equals(toClass) 681 || Float.TYPE.equals(toClass) 682 || Double.TYPE.equals(toClass); 683 } 684 if (Byte.TYPE.equals(cls)) { 685 return Short.TYPE.equals(toClass) 686 || Integer.TYPE.equals(toClass) 687 || Long.TYPE.equals(toClass) 688 || Float.TYPE.equals(toClass) 689 || Double.TYPE.equals(toClass); 690 } 691 // should never get here 692 return false; 693 } 694 return toClass.isAssignableFrom(cls); 695 } 696 697 /** 698 * <p>Converts the specified primitive Class object to its corresponding 699 * wrapper Class object.</p> 700 * 701 * <p>NOTE: From v2.2, this method handles {@code Void.TYPE}, 702 * returning {@code Void.TYPE}.</p> 703 * 704 * @param cls the class to convert, may be null 705 * @return the wrapper class for {@code cls} or {@code cls} if 706 * {@code cls} is not a primitive. {@code null} if null input. 707 * @since 2.1 708 */ 709 public static Class<?> primitiveToWrapper(final Class<?> cls) { 710 Class<?> convertedClass = cls; 711 if (cls != null && cls.isPrimitive()) { 712 convertedClass = primitiveWrapperMap.get(cls); 713 } 714 return convertedClass; 715 } 716 717 /** 718 * <p>Converts the specified array of primitive Class objects to an array of 719 * its corresponding wrapper Class objects.</p> 720 * 721 * @param classes the class array to convert, may be null or empty 722 * @return an array which contains for each given class, the wrapper class or 723 * the original class if class is not a primitive. {@code null} if null input. 724 * Empty array if an empty array passed in. 725 * @since 2.1 726 */ 727 public static Class<?>[] primitivesToWrappers(final Class<?>... classes) { 728 if (classes == null) { 729 return null; 730 } 731 732 if (classes.length == 0) { 733 return classes; 734 } 735 736 final Class<?>[] convertedClasses = new Class[classes.length]; 737 for (int i = 0; i < classes.length; i++) { 738 convertedClasses[i] = primitiveToWrapper(classes[i]); 739 } 740 return convertedClasses; 741 } 742 743 /** 744 * <p>Converts the specified wrapper class to its corresponding primitive 745 * class.</p> 746 * 747 * <p>This method is the counter part of {@code primitiveToWrapper()}. 748 * If the passed in class is a wrapper class for a primitive type, this 749 * primitive type will be returned (e.g. {@code Integer.TYPE} for 750 * {@code Integer.class}). For other classes, or if the parameter is 751 * <b>null</b>, the return value is <b>null</b>.</p> 752 * 753 * @param cls the class to convert, may be <b>null</b> 754 * @return the corresponding primitive type if {@code cls} is a 755 * wrapper class, <b>null</b> otherwise 756 * @see #primitiveToWrapper(Class) 757 * @since 2.4 758 */ 759 public static Class<?> wrapperToPrimitive(final Class<?> cls) { 760 return wrapperPrimitiveMap.get(cls); 761 } 762 763 /** 764 * <p>Converts the specified array of wrapper Class objects to an array of 765 * its corresponding primitive Class objects.</p> 766 * 767 * <p>This method invokes {@code wrapperToPrimitive()} for each element 768 * of the passed in array.</p> 769 * 770 * @param classes the class array to convert, may be null or empty 771 * @return an array which contains for each given class, the primitive class or 772 * <b>null</b> if the original class is not a wrapper class. {@code null} if null input. 773 * Empty array if an empty array passed in. 774 * @see #wrapperToPrimitive(Class) 775 * @since 2.4 776 */ 777 public static Class<?>[] wrappersToPrimitives(final Class<?>... classes) { 778 if (classes == null) { 779 return null; 780 } 781 782 if (classes.length == 0) { 783 return classes; 784 } 785 786 final Class<?>[] convertedClasses = new Class[classes.length]; 787 for (int i = 0; i < classes.length; i++) { 788 convertedClasses[i] = wrapperToPrimitive(classes[i]); 789 } 790 return convertedClasses; 791 } 792 793 // Inner class 794 // ---------------------------------------------------------------------- 795 /** 796 * <p>Is the specified class an inner class or static nested class.</p> 797 * 798 * @param cls the class to check, may be null 799 * @return {@code true} if the class is an inner or static nested class, 800 * false if not or {@code null} 801 */ 802 public static boolean isInnerClass(final Class<?> cls) { 803 return cls != null && cls.getEnclosingClass() != null; 804 } 805 806 // Class loading 807 // ---------------------------------------------------------------------- 808 /** 809 * Returns the class represented by {@code className} using the 810 * {@code classLoader}. This implementation supports the syntaxes 811 * "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}", 812 * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}". 813 * 814 * @param classLoader the class loader to use to load the class 815 * @param className the class name 816 * @param initialize whether the class must be initialized 817 * @return the class represented by {@code className} using the {@code classLoader} 818 * @throws ClassNotFoundException if the class is not found 819 */ 820 public static Class<?> getClass( 821 final ClassLoader classLoader, final String className, final boolean initialize) throws ClassNotFoundException { 822 try { 823 Class<?> clazz; 824 if (abbreviationMap.containsKey(className)) { 825 final String clsName = "[" + abbreviationMap.get(className); 826 clazz = Class.forName(clsName, initialize, classLoader).getComponentType(); 827 } else { 828 clazz = Class.forName(toCanonicalName(className), initialize, classLoader); 829 } 830 return clazz; 831 } catch (final ClassNotFoundException ex) { 832 // allow path separators (.) as inner class name separators 833 final int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR); 834 835 if (lastDotIndex != -1) { 836 try { 837 return getClass(classLoader, className.substring(0, lastDotIndex) + 838 INNER_CLASS_SEPARATOR_CHAR + className.substring(lastDotIndex + 1), 839 initialize); 840 } catch (final ClassNotFoundException ex2) { // NOPMD 841 // ignore exception 842 } 843 } 844 845 throw ex; 846 } 847 } 848 849 /** 850 * Returns the (initialized) class represented by {@code className} 851 * using the {@code classLoader}. This implementation supports 852 * the syntaxes "{@code java.util.Map.Entry[]}", 853 * "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}", 854 * and "{@code [Ljava.util.Map$Entry;}". 855 * 856 * @param classLoader the class loader to use to load the class 857 * @param className the class name 858 * @return the class represented by {@code className} using the {@code classLoader} 859 * @throws ClassNotFoundException if the class is not found 860 */ 861 public static Class<?> getClass(final ClassLoader classLoader, final String className) throws ClassNotFoundException { 862 return getClass(classLoader, className, true); 863 } 864 865 /** 866 * Returns the (initialized) class represented by {@code className} 867 * using the current thread's context class loader. This implementation 868 * supports the syntaxes "{@code java.util.Map.Entry[]}", 869 * "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}", 870 * and "{@code [Ljava.util.Map$Entry;}". 871 * 872 * @param className the class name 873 * @return the class represented by {@code className} using the current thread's context class loader 874 * @throws ClassNotFoundException if the class is not found 875 */ 876 public static Class<?> getClass(final String className) throws ClassNotFoundException { 877 return getClass(className, true); 878 } 879 880 /** 881 * Returns the class represented by {@code className} using the 882 * current thread's context class loader. This implementation supports the 883 * syntaxes "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}", 884 * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}". 885 * 886 * @param className the class name 887 * @param initialize whether the class must be initialized 888 * @return the class represented by {@code className} using the current thread's context class loader 889 * @throws ClassNotFoundException if the class is not found 890 */ 891 public static Class<?> getClass(final String className, final boolean initialize) throws ClassNotFoundException { 892 final ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); 893 final ClassLoader loader = contextCL == null ? ClassUtils.class.getClassLoader() : contextCL; 894 return getClass(loader, className, initialize); 895 } 896 897 // Public method 898 // ---------------------------------------------------------------------- 899 /** 900 * <p>Returns the desired Method much like {@code Class.getMethod}, however 901 * it ensures that the returned Method is from a public class or interface and not 902 * from an anonymous inner class. This means that the Method is invokable and 903 * doesn't fall foul of Java bug 904 * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4071957">4071957</a>). 905 * 906 * <code><pre>Set set = Collections.unmodifiableSet(...); 907 * Method method = ClassUtils.getPublicMethod(set.getClass(), "isEmpty", new Class[0]); 908 * Object result = method.invoke(set, new Object[]);</pre></code> 909 * </p> 910 * 911 * @param cls the class to check, not null 912 * @param methodName the name of the method 913 * @param parameterTypes the list of parameters 914 * @return the method 915 * @throws NullPointerException if the class is null 916 * @throws SecurityException if a security violation occurred 917 * @throws NoSuchMethodException if the method is not found in the given class 918 * or if the metothod doen't conform with the requirements 919 */ 920 public static Method getPublicMethod(final Class<?> cls, final String methodName, final Class<?>... parameterTypes) 921 throws SecurityException, NoSuchMethodException { 922 923 final Method declaredMethod = cls.getMethod(methodName, parameterTypes); 924 if (Modifier.isPublic(declaredMethod.getDeclaringClass().getModifiers())) { 925 return declaredMethod; 926 } 927 928 final List<Class<?>> candidateClasses = new ArrayList<Class<?>>(); 929 candidateClasses.addAll(getAllInterfaces(cls)); 930 candidateClasses.addAll(getAllSuperclasses(cls)); 931 932 for (final Class<?> candidateClass : candidateClasses) { 933 if (!Modifier.isPublic(candidateClass.getModifiers())) { 934 continue; 935 } 936 Method candidateMethod; 937 try { 938 candidateMethod = candidateClass.getMethod(methodName, parameterTypes); 939 } catch (final NoSuchMethodException ex) { 940 continue; 941 } 942 if (Modifier.isPublic(candidateMethod.getDeclaringClass().getModifiers())) { 943 return candidateMethod; 944 } 945 } 946 947 throw new NoSuchMethodException("Can't find a public method for " + 948 methodName + " " + ArrayUtils.toString(parameterTypes)); 949 } 950 951 // ---------------------------------------------------------------------- 952 /** 953 * Converts a class name to a JLS style class name. 954 * 955 * @param className the class name 956 * @return the converted name 957 */ 958 private static String toCanonicalName(String className) { 959 className = StringUtils.deleteWhitespace(className); 960 if (className == null) { 961 throw new NullPointerException("className must not be null."); 962 } else if (className.endsWith("[]")) { 963 final StringBuilder classNameBuffer = new StringBuilder(); 964 while (className.endsWith("[]")) { 965 className = className.substring(0, className.length() - 2); 966 classNameBuffer.append("["); 967 } 968 final String abbreviation = abbreviationMap.get(className); 969 if (abbreviation != null) { 970 classNameBuffer.append(abbreviation); 971 } else { 972 classNameBuffer.append("L").append(className).append(";"); 973 } 974 className = classNameBuffer.toString(); 975 } 976 return className; 977 } 978 979 /** 980 * <p>Converts an array of {@code Object} in to an array of {@code Class} objects. 981 * If any of these objects is null, a null element will be inserted into the array.</p> 982 * 983 * <p>This method returns {@code null} for a {@code null} input array.</p> 984 * 985 * @param array an {@code Object} array 986 * @return a {@code Class} array, {@code null} if null array input 987 * @since 2.4 988 */ 989 public static Class<?>[] toClass(final Object... array) { 990 if (array == null) { 991 return null; 992 } else if (array.length == 0) { 993 return ArrayUtils.EMPTY_CLASS_ARRAY; 994 } 995 final Class<?>[] classes = new Class[array.length]; 996 for (int i = 0; i < array.length; i++) { 997 classes[i] = array[i] == null ? null : array[i].getClass(); 998 } 999 return classes; 1000 } 1001 1002 // Short canonical name 1003 // ---------------------------------------------------------------------- 1004 /** 1005 * <p>Gets the canonical name minus the package name for an {@code Object}.</p> 1006 * 1007 * @param object the class to get the short name for, may be null 1008 * @param valueIfNull the value to return if null 1009 * @return the canonical name of the object without the package name, or the null value 1010 * @since 2.4 1011 */ 1012 public static String getShortCanonicalName(final Object object, final String valueIfNull) { 1013 if (object == null) { 1014 return valueIfNull; 1015 } 1016 return getShortCanonicalName(object.getClass().getName()); 1017 } 1018 1019 /** 1020 * <p>Gets the canonical name minus the package name from a {@code Class}.</p> 1021 * 1022 * @param cls the class to get the short name for. 1023 * @return the canonical name without the package name or an empty string 1024 * @since 2.4 1025 */ 1026 public static String getShortCanonicalName(final Class<?> cls) { 1027 if (cls == null) { 1028 return StringUtils.EMPTY; 1029 } 1030 return getShortCanonicalName(cls.getName()); 1031 } 1032 1033 /** 1034 * <p>Gets the canonical name minus the package name from a String.</p> 1035 * 1036 * <p>The string passed in is assumed to be a canonical name - it is not checked.</p> 1037 * 1038 * @param canonicalName the class name to get the short name for 1039 * @return the canonical name of the class without the package name or an empty string 1040 * @since 2.4 1041 */ 1042 public static String getShortCanonicalName(final String canonicalName) { 1043 return ClassUtils.getShortClassName(getCanonicalName(canonicalName)); 1044 } 1045 1046 // Package name 1047 // ---------------------------------------------------------------------- 1048 /** 1049 * <p>Gets the package name from the canonical name of an {@code Object}.</p> 1050 * 1051 * @param object the class to get the package name for, may be null 1052 * @param valueIfNull the value to return if null 1053 * @return the package name of the object, or the null value 1054 * @since 2.4 1055 */ 1056 public static String getPackageCanonicalName(final Object object, final String valueIfNull) { 1057 if (object == null) { 1058 return valueIfNull; 1059 } 1060 return getPackageCanonicalName(object.getClass().getName()); 1061 } 1062 1063 /** 1064 * <p>Gets the package name from the canonical name of a {@code Class}.</p> 1065 * 1066 * @param cls the class to get the package name for, may be {@code null}. 1067 * @return the package name or an empty string 1068 * @since 2.4 1069 */ 1070 public static String getPackageCanonicalName(final Class<?> cls) { 1071 if (cls == null) { 1072 return StringUtils.EMPTY; 1073 } 1074 return getPackageCanonicalName(cls.getName()); 1075 } 1076 1077 /** 1078 * <p>Gets the package name from the canonical name. </p> 1079 * 1080 * <p>The string passed in is assumed to be a canonical name - it is not checked.</p> 1081 * <p>If the class is unpackaged, return an empty string.</p> 1082 * 1083 * @param canonicalName the canonical name to get the package name for, may be {@code null} 1084 * @return the package name or an empty string 1085 * @since 2.4 1086 */ 1087 public static String getPackageCanonicalName(final String canonicalName) { 1088 return ClassUtils.getPackageName(getCanonicalName(canonicalName)); 1089 } 1090 1091 /** 1092 * <p>Converts a given name of class into canonical format. 1093 * If name of class is not a name of array class it returns 1094 * unchanged name.</p> 1095 * <p>Example: 1096 * <ul> 1097 * <li>{@code getCanonicalName("[I") = "int[]"}</li> 1098 * <li>{@code getCanonicalName("[Ljava.lang.String;") = "java.lang.String[]"}</li> 1099 * <li>{@code getCanonicalName("java.lang.String") = "java.lang.String"}</li> 1100 * </ul> 1101 * </p> 1102 * 1103 * @param className the name of class 1104 * @return canonical form of class name 1105 * @since 2.4 1106 */ 1107 private static String getCanonicalName(String className) { 1108 className = StringUtils.deleteWhitespace(className); 1109 if (className == null) { 1110 return null; 1111 } else { 1112 int dim = 0; 1113 while (className.startsWith("[")) { 1114 dim++; 1115 className = className.substring(1); 1116 } 1117 if (dim < 1) { 1118 return className; 1119 } else { 1120 if (className.startsWith("L")) { 1121 className = className.substring( 1122 1, 1123 className.endsWith(";") 1124 ? className.length() - 1 1125 : className.length()); 1126 } else { 1127 if (className.length() > 0) { 1128 className = reverseAbbreviationMap.get(className.substring(0, 1)); 1129 } 1130 } 1131 final StringBuilder canonicalClassNameBuffer = new StringBuilder(className); 1132 for (int i = 0; i < dim; i++) { 1133 canonicalClassNameBuffer.append("[]"); 1134 } 1135 return canonicalClassNameBuffer.toString(); 1136 } 1137 } 1138 } 1139 1140 /** 1141 * Get an {@link Iterable} that can iterate over a class hierarchy in ascending (subclass to superclass) order, 1142 * excluding interfaces. 1143 * 1144 * @param type the type to get the class hierarchy from 1145 * @return Iterable an Iterable over the class hierarchy of the given class 1146 * @since 3.2 1147 */ 1148 public static Iterable<Class<?>> hierarchy(final Class<?> type) { 1149 return hierarchy(type, Interfaces.EXCLUDE); 1150 } 1151 1152 /** 1153 * Get an {@link Iterable} that can iterate over a class hierarchy in ascending (subclass to superclass) order. 1154 * 1155 * @param type the type to get the class hierarchy from 1156 * @param interfacesBehavior switch indicating whether to include or exclude interfaces 1157 * @return Iterable an Iterable over the class hierarchy of the given class 1158 * @since 3.2 1159 */ 1160 public static Iterable<Class<?>> hierarchy(final Class<?> type, Interfaces interfacesBehavior) { 1161 final Iterable<Class<?>> classes = new Iterable<Class<?>>() { 1162 1163 @Override 1164 public Iterator<Class<?>> iterator() { 1165 final MutableObject<Class<?>> next = new MutableObject<Class<?>>(type); 1166 return new Iterator<Class<?>>() { 1167 1168 @Override 1169 public boolean hasNext() { 1170 return next.getValue() != null; 1171 } 1172 1173 @Override 1174 public Class<?> next() { 1175 final Class<?> result = next.getValue(); 1176 next.setValue(result.getSuperclass()); 1177 return result; 1178 } 1179 1180 @Override 1181 public void remove() { 1182 throw new UnsupportedOperationException(); 1183 } 1184 1185 }; 1186 } 1187 1188 }; 1189 if (interfacesBehavior != Interfaces.INCLUDE) { 1190 return classes; 1191 } 1192 return new Iterable<Class<?>>() { 1193 1194 @Override 1195 public Iterator<Class<?>> iterator() { 1196 final Set<Class<?>> seenInterfaces = new HashSet<Class<?>>(); 1197 final Iterator<Class<?>> wrapped = classes.iterator(); 1198 1199 return new Iterator<Class<?>>() { 1200 Iterator<Class<?>> interfaces = Collections.<Class<?>> emptySet().iterator(); 1201 1202 @Override 1203 public boolean hasNext() { 1204 return interfaces.hasNext() || wrapped.hasNext(); 1205 } 1206 1207 @Override 1208 public Class<?> next() { 1209 if (interfaces.hasNext()) { 1210 final Class<?> nextInterface = interfaces.next(); 1211 seenInterfaces.add(nextInterface); 1212 return nextInterface; 1213 } 1214 final Class<?> nextSuperclass = wrapped.next(); 1215 final Set<Class<?>> currentInterfaces = new LinkedHashSet<Class<?>>(); 1216 walkInterfaces(currentInterfaces, nextSuperclass); 1217 interfaces = currentInterfaces.iterator(); 1218 return nextSuperclass; 1219 } 1220 1221 private void walkInterfaces(Set<Class<?>> addTo, Class<?> c) { 1222 for (Class<?> iface : c.getInterfaces()) { 1223 if (!seenInterfaces.contains(iface)) { 1224 addTo.add(iface); 1225 } 1226 walkInterfaces(addTo, iface); 1227 } 1228 } 1229 1230 @Override 1231 public void remove() { 1232 throw new UnsupportedOperationException(); 1233 } 1234 1235 }; 1236 } 1237 }; 1238 } 1239 1240}