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 * https://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.reflect; 018 019import java.lang.reflect.Array; 020import java.lang.reflect.GenericArrayType; 021import java.lang.reflect.GenericDeclaration; 022import java.lang.reflect.ParameterizedType; 023import java.lang.reflect.Type; 024import java.lang.reflect.TypeVariable; 025import java.lang.reflect.WildcardType; 026import java.util.Arrays; 027import java.util.Collection; 028import java.util.Collections; 029import java.util.HashMap; 030import java.util.HashSet; 031import java.util.IdentityHashMap; 032import java.util.List; 033import java.util.Map; 034import java.util.Objects; 035import java.util.Set; 036import java.util.TreeSet; 037 038import org.apache.commons.lang3.AppendableJoiner; 039import org.apache.commons.lang3.ArrayUtils; 040import org.apache.commons.lang3.ClassUtils; 041import org.apache.commons.lang3.ObjectUtils; 042import org.apache.commons.lang3.Validate; 043import org.apache.commons.lang3.builder.Builder; 044 045/** 046 * Utility methods focusing on type inspection, particularly with regard to generics. 047 * 048 * @since 3.0 049 */ 050public class TypeUtils { 051 052 /** 053 * GenericArrayType implementation class. 054 */ 055 private static final class GenericArrayTypeImpl implements GenericArrayType { 056 private final Type componentType; 057 058 /** 059 * Constructs a new instance. 060 * 061 * @param componentType of this array type. 062 */ 063 private GenericArrayTypeImpl(final Type componentType) { 064 this.componentType = componentType; 065 } 066 067 /** 068 * {@inheritDoc} 069 */ 070 @Override 071 public boolean equals(final Object obj) { 072 return obj == this || obj instanceof GenericArrayType && TypeUtils.equals(this, (GenericArrayType) obj); 073 } 074 075 /** 076 * {@inheritDoc} 077 */ 078 @Override 079 public Type getGenericComponentType() { 080 return componentType; 081 } 082 083 /** 084 * {@inheritDoc} 085 */ 086 @Override 087 public int hashCode() { 088 int result = 67 << 4; 089 result |= componentType.hashCode(); 090 return result; 091 } 092 093 /** 094 * {@inheritDoc} 095 */ 096 @Override 097 public String toString() { 098 return TypeUtils.toString(this); 099 } 100 } 101 102 /** 103 * ParameterizedType implementation class. 104 */ 105 private static final class ParameterizedTypeImpl implements ParameterizedType { 106 private final Class<?> raw; 107 private final Type useOwner; 108 private final Type[] typeArguments; 109 110 /** 111 * Constructs a new instance. 112 * 113 * @param rawClass type. 114 * @param useOwner owner type to use, if any. 115 * @param typeArguments formal type arguments. 116 */ 117 private ParameterizedTypeImpl(final Class<?> rawClass, final Type useOwner, final Type[] typeArguments) { 118 this.raw = rawClass; 119 this.useOwner = useOwner; 120 this.typeArguments = Arrays.copyOf(typeArguments, typeArguments.length, Type[].class); 121 } 122 123 /** 124 * {@inheritDoc} 125 */ 126 @Override 127 public boolean equals(final Object obj) { 128 return obj == this || obj instanceof ParameterizedType && TypeUtils.equals(this, (ParameterizedType) obj); 129 } 130 131 /** 132 * {@inheritDoc} 133 */ 134 @Override 135 public Type[] getActualTypeArguments() { 136 return typeArguments.clone(); 137 } 138 139 /** 140 * {@inheritDoc} 141 */ 142 @Override 143 public Type getOwnerType() { 144 return useOwner; 145 } 146 147 /** 148 * {@inheritDoc} 149 */ 150 @Override 151 public Type getRawType() { 152 return raw; 153 } 154 155 /** 156 * {@inheritDoc} 157 */ 158 @Override 159 public int hashCode() { 160 int result = 71 << 4; 161 result |= raw.hashCode(); 162 result <<= 4; 163 result |= Objects.hashCode(useOwner); 164 result <<= 8; 165 result |= Arrays.hashCode(typeArguments); 166 return result; 167 } 168 169 /** 170 * {@inheritDoc} 171 */ 172 @Override 173 public String toString() { 174 return TypeUtils.toString(this); 175 } 176 } 177 178 /** 179 * {@link WildcardType} builder. 180 * 181 * @since 3.2 182 */ 183 public static class WildcardTypeBuilder implements Builder<WildcardType> { 184 private Type[] upperBounds; 185 186 private Type[] lowerBounds; 187 188 /** 189 * Constructor. 190 */ 191 private WildcardTypeBuilder() { 192 } 193 194 /** 195 * {@inheritDoc} 196 */ 197 @Override 198 public WildcardType build() { 199 return new WildcardTypeImpl(upperBounds, lowerBounds); 200 } 201 202 /** 203 * Specify lower bounds of the wildcard type to build. 204 * 205 * @param bounds to set. 206 * @return {@code this} instance. 207 */ 208 public WildcardTypeBuilder withLowerBounds(final Type... bounds) { 209 this.lowerBounds = bounds; 210 return this; 211 } 212 213 /** 214 * Specify upper bounds of the wildcard type to build. 215 * 216 * @param bounds to set. 217 * @return {@code this} instance. 218 */ 219 public WildcardTypeBuilder withUpperBounds(final Type... bounds) { 220 this.upperBounds = bounds; 221 return this; 222 } 223 } 224 225 /** 226 * WildcardType implementation class. 227 */ 228 private static final class WildcardTypeImpl implements WildcardType { 229 private final Type[] upperBounds; 230 private final Type[] lowerBounds; 231 232 /** 233 * Constructs a new instance. 234 * 235 * @param upperBounds of this type. 236 * @param lowerBounds of this type. 237 */ 238 private WildcardTypeImpl(final Type[] upperBounds, final Type[] lowerBounds) { 239 this.upperBounds = upperBounds != null ? upperBounds.clone() : ArrayUtils.EMPTY_TYPE_ARRAY; 240 this.lowerBounds = lowerBounds != null ? lowerBounds.clone() : ArrayUtils.EMPTY_TYPE_ARRAY; 241 } 242 243 /** 244 * {@inheritDoc} 245 */ 246 @Override 247 public boolean equals(final Object obj) { 248 return obj == this || obj instanceof WildcardType && TypeUtils.equals(this, (WildcardType) obj); 249 } 250 251 /** 252 * {@inheritDoc} 253 */ 254 @Override 255 public Type[] getLowerBounds() { 256 return lowerBounds.clone(); 257 } 258 259 /** 260 * {@inheritDoc} 261 */ 262 @Override 263 public Type[] getUpperBounds() { 264 return upperBounds.clone(); 265 } 266 267 /** 268 * {@inheritDoc} 269 */ 270 @Override 271 public int hashCode() { 272 int result = 73 << 8; 273 result |= Arrays.hashCode(upperBounds); 274 result <<= 8; 275 result |= Arrays.hashCode(lowerBounds); 276 return result; 277 } 278 279 /** 280 * {@inheritDoc} 281 */ 282 @Override 283 public String toString() { 284 return TypeUtils.toString(this); 285 } 286 } 287 288 /** 289 * Ampersand sign joiner. 290 */ 291 // @formatter:off 292 private static final AppendableJoiner<Type> AMP_JOINER = AppendableJoiner.<Type>builder() 293 .setDelimiter(" & ") 294 .setElementAppender((a, e) -> a.append(toReferenceString(e))) 295 .get(); 296 // @formatter:on 297 298 /** 299 * Method classToString joiner. 300 */ 301 // @formatter:off 302// private static final AppendableJoiner<TypeVariable<Class<?>>> CTJ_JOINER = AppendableJoiner.<TypeVariable<Class<?>>>builder() 303// .setDelimiter(", ") 304// .setElementAppender((a, e) -> a.append(anyToString(e))) 305// .get(); 306 // @formatter:on 307 308 /** 309 * Greater than and lesser than sign joiner. 310 */ 311 // @formatter:off 312 private static final AppendableJoiner<Object> GT_JOINER = AppendableJoiner.builder() 313 .setPrefix("<") 314 .setSuffix(">") 315 .setDelimiter(", ") 316 .setElementAppender((a, e) -> a.append(anyToString(e))) 317 .get(); 318 // @formatter:on 319 320 /** 321 * Type arguments joiner. 322 */ 323 // @formatter:off 324 private static final AppendableJoiner<Type> TYPE_ARG_JOINER = AppendableJoiner.<Type>builder() 325 .setPrefix("<") 326 .setSuffix(">") 327 .setDelimiter(", ") 328 .setElementAppender((a, e) -> a.append(toReferenceString(e))) 329 .get(); 330 // @formatter:on 331 332 /** 333 * A wildcard instance matching {@code ?}. 334 * 335 * @since 3.2 336 */ 337 public static final WildcardType WILDCARD_ALL = wildcardType().withUpperBounds(Object.class).build(); 338 339 private static final ThreadLocal<Set<Type>> VISITING = ThreadLocal.withInitial(() -> Collections.newSetFromMap(new IdentityHashMap<>())); 340 341 private static <T> String anyToString(final T object) { 342 return object instanceof Type ? toString((Type) object) : object.toString(); 343 } 344 345 346 /** 347 * Formats a {@link Class} as a {@link String}. 348 * 349 * @param cls {@link Class} to format. 350 * @return The class as a String. 351 */ 352 private static <T> String classToString(final Class<T> cls) { 353 if (cls.isArray()) { 354 return toString(cls.getComponentType()) + "[]"; 355 } 356 if (isCyclical(cls)) { 357 return cls.getSimpleName() + "(cycle)"; 358 } 359 final StringBuilder buf = new StringBuilder(); 360 if (cls.getEnclosingClass() != null) { 361 buf.append(classToString(cls.getEnclosingClass())).append('.').append(cls.getSimpleName()); 362 } else { 363 buf.append(cls.getName()); 364 } 365 if (cls.getTypeParameters().length > 0) { 366 GT_JOINER.join(buf, (Object[]) cls.getTypeParameters()); 367 } 368 return buf.toString(); 369 } 370 371 /** 372 * Tests, recursively, whether any of the type parameters associated with {@code type} are bound to variables. 373 * 374 * @param type The type to check for type variables. 375 * @return Whether any of the type parameters associated with {@code type} are bound to variables. 376 * @since 3.2 377 */ 378 public static boolean containsTypeVariables(final Type type) { 379 if (type instanceof TypeVariable<?>) { 380 return true; 381 } 382 if (type instanceof Class<?>) { 383 return ((Class<?>) type).getTypeParameters().length > 0; 384 } 385 if (type instanceof ParameterizedType) { 386 for (final Type arg : ((ParameterizedType) type).getActualTypeArguments()) { 387 if (containsTypeVariables(arg)) { 388 return true; 389 } 390 } 391 return false; 392 } 393 if (type instanceof WildcardType) { 394 final WildcardType wild = (WildcardType) type; 395 for (final Type bound : getImplicitLowerBounds(wild)) { 396 if (containsTypeVariables(bound)) { 397 return true; 398 } 399 } 400 for (final Type bound : getImplicitUpperBounds(wild)) { 401 if (containsTypeVariables(bound)) { 402 return true; 403 } 404 } 405 return false; 406 } 407 if (type instanceof GenericArrayType) { 408 return containsTypeVariables(((GenericArrayType) type).getGenericComponentType()); 409 } 410 return false; 411 } 412 413 /** 414 * Tries to determine the type arguments of a class/interface based on a super parameterized type's type arguments. This method is the inverse of 415 * {@link #getTypeArguments(Type, Class)} which gets a class/interface's type arguments based on a subtype. It is far more limited in determining the type 416 * arguments for the subject class's type variables in that it can only determine those parameters that map from the subject {@link Class} object to the 417 * supertype. 418 * 419 * <p> 420 * Example: {@link java.util.TreeSet TreeSet} sets its parameter as the parameter for {@link java.util.NavigableSet NavigableSet}, which in turn sets the 421 * parameter of {@link java.util.SortedSet}, which in turn sets the parameter of {@link Set}, which in turn sets the parameter of 422 * {@link java.util.Collection}, which in turn sets the parameter of {@link Iterable}. Since {@link TreeSet}'s parameter maps (indirectly) to 423 * {@link Iterable}'s parameter, it will be able to determine that based on the super type {@code Iterable<? extends 424 * Map<Integer, ? extends Collection<?>>>}, the parameter of {@link TreeSet} is {@code ? extends Map<Integer, ? extends 425 * Collection<?>>}. 426 * </p> 427 * 428 * @param cls The class whose type parameters are to be determined, not {@code null}. 429 * @param superParameterizedType The super type from which {@code cls}'s type arguments are to be determined, not {@code null}. 430 * @return A {@link Map} of the type assignments that could be determined for the type variables in each type in the inheritance hierarchy from {@code type} 431 * to {@code toClass} inclusive. 432 * @throws NullPointerException Thrown if either {@code cls} or {@code superParameterizedType} is {@code null}. 433 */ 434 public static Map<TypeVariable<?>, Type> determineTypeArguments(final Class<?> cls, final ParameterizedType superParameterizedType) { 435 Objects.requireNonNull(cls, "cls"); 436 Objects.requireNonNull(superParameterizedType, "superParameterizedType"); 437 final Class<?> superClass = getRawType(superParameterizedType); 438 // compatibility check 439 if (!isAssignable(cls, superClass)) { 440 return null; 441 } 442 if (cls.equals(superClass)) { 443 return getTypeArguments(superParameterizedType, superClass, null); 444 } 445 // get the next class in the inheritance hierarchy 446 final Type midType = getClosestParentType(cls, superClass); 447 // can only be a class or a parameterized type 448 if (midType instanceof Class<?>) { 449 return determineTypeArguments((Class<?>) midType, superParameterizedType); 450 } 451 final ParameterizedType midParameterizedType = (ParameterizedType) midType; 452 final Class<?> midClass = getRawType(midParameterizedType); 453 // get the type variables of the mid class that map to the type 454 // arguments of the super class 455 final Map<TypeVariable<?>, Type> typeVarAssigns = determineTypeArguments(midClass, superParameterizedType); 456 // map the arguments of the mid type to the class type variables 457 mapTypeVariablesToArguments(cls, midParameterizedType, typeVarAssigns); 458 return typeVarAssigns; 459 } 460 461 /** 462 * Tests whether {@code t} equals {@code a}. 463 * 464 * @param genericArrayType LHS. 465 * @param type RHS. 466 * @return boolean. 467 */ 468 private static boolean equals(final GenericArrayType genericArrayType, final Type type) { 469 return type instanceof GenericArrayType && equals(genericArrayType.getGenericComponentType(), ((GenericArrayType) type).getGenericComponentType()); 470 } 471 472 /** 473 * Tests whether {@code t} equals {@code p}. 474 * 475 * @param parameterizedType LHS. 476 * @param type RHS. 477 * @return boolean. 478 */ 479 private static boolean equals(final ParameterizedType parameterizedType, final Type type) { 480 if (type instanceof ParameterizedType) { 481 final ParameterizedType other = (ParameterizedType) type; 482 if (equals(parameterizedType.getRawType(), other.getRawType()) && equals(parameterizedType.getOwnerType(), other.getOwnerType())) { 483 return equals(parameterizedType.getActualTypeArguments(), other.getActualTypeArguments()); 484 } 485 } 486 return false; 487 } 488 489 /** 490 * Tests whether the given types are equal. 491 * 492 * @param type1 The first type. 493 * @param type2 The second type. 494 * @return Whether the given types are equal. 495 * @since 3.2 496 */ 497 public static boolean equals(final Type type1, final Type type2) { 498 if (Objects.equals(type1, type2)) { 499 return true; 500 } 501 if (type1 instanceof ParameterizedType) { 502 return equals((ParameterizedType) type1, type2); 503 } 504 if (type1 instanceof GenericArrayType) { 505 return equals((GenericArrayType) type1, type2); 506 } 507 if (type1 instanceof WildcardType) { 508 return equals((WildcardType) type1, type2); 509 } 510 return false; 511 } 512 513 /** 514 * Tests whether the given type arrays are equal. 515 * 516 * @param type1 LHS. 517 * @param type2 RHS. 518 * @return Whether the given type arrays are equal. 519 */ 520 private static boolean equals(final Type[] type1, final Type[] type2) { 521 if (type1.length == type2.length) { 522 for (int i = 0; i < type1.length; i++) { 523 if (!equals(type1[i], type2[i])) { 524 return false; 525 } 526 } 527 return true; 528 } 529 return false; 530 } 531 532 /** 533 * Tests whether {@code wildcardType} equals {@code type}. 534 * 535 * @param wildcardType LHS. 536 * @param type RHS. 537 * @return Whether {@code wildcardType} equals {@code type}. 538 */ 539 private static boolean equals(final WildcardType wildcardType, final Type type) { 540 if (type instanceof WildcardType) { 541 final WildcardType other = (WildcardType) type; 542 return equals(getImplicitLowerBounds(wildcardType), getImplicitLowerBounds(other)) 543 && equals(getImplicitUpperBounds(wildcardType), getImplicitUpperBounds(other)); 544 } 545 return false; 546 } 547 548 /** 549 * Helper method to establish the formal parameters for a parameterized type. 550 * 551 * @param mappings map containing the assignments. 552 * @param variables expected map keys. 553 * @return array of map values corresponding to specified keys. 554 */ 555 private static Type[] extractTypeArgumentsFrom(final Map<TypeVariable<?>, Type> mappings, final TypeVariable<?>[] variables) { 556 final Type[] result = new Type[variables.length]; 557 int index = 0; 558 for (final TypeVariable<?> var : variables) { 559 Validate.isTrue(mappings.containsKey(var), () -> String.format("missing argument mapping for %s", toString(var))); 560 result[index++] = mappings.get(var); 561 } 562 return result; 563 } 564 565 566 /** 567 * Creates a generic array type instance. 568 * 569 * @param componentType The type of the elements of the array. For example the component type of {@code boolean[]} is {@code boolean}. 570 * @return {@link GenericArrayType}. 571 * @since 3.2 572 */ 573 public static GenericArrayType genericArrayType(final Type componentType) { 574 return new GenericArrayTypeImpl(Objects.requireNonNull(componentType, "componentType")); 575 } 576 577 /** 578 * Formats a {@link GenericArrayType} as a {@link String}. 579 * 580 * @param genericArrayType {@link GenericArrayType} to format. 581 * @return String. 582 */ 583 private static String genericArrayTypeToString(final GenericArrayType genericArrayType) { 584 return String.format("%s[]", toReferenceString(genericArrayType.getGenericComponentType())); 585 } 586 587 /** 588 * Gets the array component type of {@code type}. 589 * 590 * @param type The type to be checked. 591 * @return component type or null if type is not an array type. 592 */ 593 public static Type getArrayComponentType(final Type type) { 594 if (type instanceof Class<?>) { 595 final Class<?> cls = (Class<?>) type; 596 return cls.isArray() ? cls.getComponentType() : null; 597 } 598 if (type instanceof GenericArrayType) { 599 return ((GenericArrayType) type).getGenericComponentType(); 600 } 601 return null; 602 } 603 604 /** 605 * Gets the closest parent type to the super class specified by {@code superClass}. 606 * 607 * @param cls The class in question. 608 * @param superClass The super class. 609 * @return The closes parent type. 610 */ 611 private static Type getClosestParentType(final Class<?> cls, final Class<?> superClass) { 612 // only look at the interfaces if the super class is also an interface 613 if (superClass.isInterface()) { 614 // get the generic interfaces of the subject class 615 final Type[] interfaceTypes = cls.getGenericInterfaces(); 616 // will hold the best generic interface match found 617 Type genericInterface = null; 618 // find the interface closest to the super class 619 for (final Type midType : interfaceTypes) { 620 final Class<?> midClass; 621 if (midType instanceof ParameterizedType) { 622 midClass = getRawType((ParameterizedType) midType); 623 } else if (midType instanceof Class<?>) { 624 midClass = (Class<?>) midType; 625 } else { 626 throw new IllegalStateException("Unexpected generic interface type found: " + midType); 627 } 628 // check if this interface is further up the inheritance chain 629 // than the previously found match 630 if (isAssignable(midClass, superClass) && isAssignable(genericInterface, (Type) midClass)) { 631 genericInterface = midType; 632 } 633 } 634 // found a match? 635 if (genericInterface != null) { 636 return genericInterface; 637 } 638 } 639 // none of the interfaces were descendants of the target class, so the 640 // super class has to be one, instead 641 return cls.getGenericSuperclass(); 642 } 643 644 /** 645 * Gets an array containing the sole type of {@link Object} if {@link TypeVariable#getBounds()} returns an empty array. Otherwise, it returns the result of 646 * {@link TypeVariable#getBounds()} passed into {@link #normalizeUpperBounds}. 647 * 648 * @param typeVariable The subject type variable, not {@code null}. 649 * @return A non-empty array containing the bounds of the type variable, which could be {@link Object}. 650 * @throws NullPointerException Thrown if {@code typeVariable} is {@code null}. 651 */ 652 public static Type[] getImplicitBounds(final TypeVariable<?> typeVariable) { 653 return normalizeUpperToObject(Objects.requireNonNull(typeVariable, "typeVariable").getBounds()); 654 } 655 656 /** 657 * Gets an array containing a single value of {@code null} if {@link WildcardType#getLowerBounds()} returns an empty array. Otherwise, it returns the result 658 * of {@link WildcardType#getLowerBounds()}. 659 * 660 * @param wildcardType The subject wildcard type, not {@code null}. 661 * @return A non-empty array containing the lower bounds of the wildcard type, which could be null. 662 * @throws NullPointerException Thrown if {@code wildcardType} is {@code null}. 663 */ 664 public static Type[] getImplicitLowerBounds(final WildcardType wildcardType) { 665 Objects.requireNonNull(wildcardType, "wildcardType"); 666 final Type[] bounds = wildcardType.getLowerBounds(); 667 return bounds.length == 0 ? new Type[] { null } : bounds; 668 } 669 670 /** 671 * Gets an array containing the sole value of {@link Object} if {@link WildcardType#getUpperBounds()} returns an empty array. Otherwise, it returns the 672 * result of {@link WildcardType#getUpperBounds()} passed into {@link #normalizeUpperBounds}. 673 * 674 * @param wildcardType The subject wildcard type, not {@code null}. 675 * @return A non-empty array containing the upper bounds of the wildcard type. 676 * @throws NullPointerException Thrown if {@code wildcardType} is {@code null}. 677 */ 678 public static Type[] getImplicitUpperBounds(final WildcardType wildcardType) { 679 return normalizeUpperToObject(Objects.requireNonNull(wildcardType, "wildcardType").getUpperBounds()); 680 } 681 682 /** 683 * Gets the raw {@link Class} corresponding to the given type. 684 * 685 * @param parameterizedType The type to be converted. 686 * @return The corresponding {@link Class} object. 687 * @throws IllegalStateException Thrown if the conversion fails. 688 */ 689 private static Class<?> getRawType(final ParameterizedType parameterizedType) { 690 final Type rawType = parameterizedType.getRawType(); 691 // check if raw type is a Class object 692 // not currently necessary, but since the return type is Type instead of 693 // Class, there's enough reason to believe that future versions of Java 694 // may return other Type implementations. And type-safety checking is 695 // rarely a bad idea. 696 if (!(rawType instanceof Class<?>)) { 697 throw new IllegalStateException("Type of rawType: " + rawType); 698 } 699 return (Class<?>) rawType; 700 } 701 702 /** 703 * Gets the raw type of a Java type, given its context. Primarily for use with {@link TypeVariable}s and {@link GenericArrayType}s, or when you do not know 704 * the runtime type of {@code type}: if you know you have a {@link Class} instance, it is already raw; if you know you have a {@link ParameterizedType}, its 705 * raw type is only a method call away. 706 * 707 * @param type to resolve. 708 * @param assigningType type to be resolved against. 709 * @return The resolved {@link Class} object or {@code null} if the type could not be resolved. 710 */ 711 public static Class<?> getRawType(final Type type, final Type assigningType) { 712 if (type instanceof Class<?>) { 713 // it is raw, no problem 714 return (Class<?>) type; 715 } 716 if (type instanceof ParameterizedType) { 717 // simple enough to get the raw type of a ParameterizedType 718 return getRawType((ParameterizedType) type); 719 } 720 if (type instanceof TypeVariable<?>) { 721 if (assigningType == null) { 722 return null; 723 } 724 // get the entity declaring this type variable 725 final Object genericDeclaration = ((TypeVariable<?>) type).getGenericDeclaration(); 726 // can't get the raw type of a method- or constructor-declared type 727 // variable 728 if (!(genericDeclaration instanceof Class<?>)) { 729 return null; 730 } 731 // get the type arguments for the declaring class/interface based 732 // on the enclosing type 733 final Map<TypeVariable<?>, Type> typeVarAssigns = getTypeArguments(assigningType, (Class<?>) genericDeclaration); 734 // enclosingType has to be a subclass (or subinterface) of the 735 // declaring type 736 if (typeVarAssigns == null) { 737 return null; 738 } 739 // get the argument assigned to this type variable 740 final Type typeArgument = typeVarAssigns.get(type); 741 if (typeArgument == null) { 742 return null; 743 } 744 // get the argument for this type variable 745 return getRawType(typeArgument, assigningType); 746 } 747 if (type instanceof GenericArrayType) { 748 // get raw component type 749 final Class<?> rawComponentType = getRawType(((GenericArrayType) type).getGenericComponentType(), assigningType); 750 // create array type from raw component type and return its class 751 return rawComponentType != null ? Array.newInstance(rawComponentType, 0).getClass() : null; 752 } 753 // (hand-waving) this is not the method you're looking for 754 if (type instanceof WildcardType) { 755 return null; 756 } 757 throw new IllegalArgumentException("unknown type: " + type); 758 } 759 760 /** 761 * Gets a map of the type arguments of a class in the context of {@code toClass}. 762 * 763 * @param cls The class in question. 764 * @param toClass The context class. 765 * @param subtypeVarAssigns A map with type variables. 766 * @return The {@link Map} with type arguments. 767 */ 768 private static Map<TypeVariable<?>, Type> getTypeArguments(Class<?> cls, final Class<?> toClass, final Map<TypeVariable<?>, Type> subtypeVarAssigns) { 769 // make sure they're assignable 770 if (!isAssignable(cls, toClass)) { 771 return null; 772 } 773 // can't work with primitives 774 if (cls.isPrimitive()) { 775 // both classes are primitives? 776 if (toClass.isPrimitive()) { 777 // dealing with widening here. No type arguments to be 778 // harvested with these two types. 779 return new HashMap<>(); 780 } 781 // work with wrapper the wrapper class instead of the primitive 782 cls = ClassUtils.primitiveToWrapper(cls); 783 } 784 // create a copy of the incoming map, or an empty one if it's null 785 final HashMap<TypeVariable<?>, Type> typeVarAssigns = subtypeVarAssigns == null ? new HashMap<>() : new HashMap<>(subtypeVarAssigns); 786 // has target class been reached? 787 if (toClass.equals(cls)) { 788 return typeVarAssigns; 789 } 790 // walk the inheritance hierarchy until the target class is reached 791 return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns); 792 } 793 794 /** 795 * Gets all the type arguments for this parameterized type including owner hierarchy arguments such as {@code Outer<K, V>.Inner<T>.DeepInner<E>} . The 796 * arguments are returned in a {@link Map} specifying the argument type for each {@link TypeVariable}. 797 * 798 * @param type specifies the subject parameterized type from which to harvest the parameters. 799 * @return A {@link Map} of the type arguments to their respective type variables. 800 */ 801 public static Map<TypeVariable<?>, Type> getTypeArguments(final ParameterizedType type) { 802 return getTypeArguments(type, getRawType(type), null); 803 } 804 805 /** 806 * Gets a map of the type arguments of a parameterized type in the context of {@code toClass}. 807 * 808 * @param parameterizedType The parameterized type. 809 * @param toClass The class. 810 * @param subtypeVarAssigns A map with type variables. 811 * @return The {@link Map} with type arguments. 812 */ 813 private static Map<TypeVariable<?>, Type> getTypeArguments(final ParameterizedType parameterizedType, final Class<?> toClass, 814 final Map<TypeVariable<?>, Type> subtypeVarAssigns) { 815 final Class<?> cls = getRawType(parameterizedType); 816 // make sure they're assignable 817 if (!isAssignable(cls, toClass)) { 818 return null; 819 } 820 final Type ownerType = parameterizedType.getOwnerType(); 821 final Map<TypeVariable<?>, Type> typeVarAssigns; 822 if (ownerType instanceof ParameterizedType) { 823 // get the owner type arguments first 824 final ParameterizedType parameterizedOwnerType = (ParameterizedType) ownerType; 825 typeVarAssigns = getTypeArguments(parameterizedOwnerType, getRawType(parameterizedOwnerType), subtypeVarAssigns); 826 } else { 827 // no owner, prep the type variable assignments map 828 typeVarAssigns = subtypeVarAssigns == null ? new HashMap<>() : new HashMap<>(subtypeVarAssigns); 829 } 830 // get the subject parameterized type's arguments 831 final Type[] typeArgs = parameterizedType.getActualTypeArguments(); 832 // and get the corresponding type variables from the raw class 833 final TypeVariable<?>[] typeParams = cls.getTypeParameters(); 834 // map the arguments to their respective type variables 835 for (int i = 0; i < typeParams.length; i++) { 836 final Type typeArg = typeArgs[i]; 837 typeVarAssigns.put(typeParams[i], typeVarAssigns.getOrDefault(typeArg, typeArg)); 838 } 839 if (toClass.equals(cls)) { 840 // target class has been reached. Done. 841 return typeVarAssigns; 842 } 843 // walk the inheritance hierarchy until the target class is reached 844 final Type parentType = getClosestParentType(cls, toClass); 845 if (parentType instanceof ParameterizedType) { 846 final ParameterizedType parameterizedParentType = (ParameterizedType) parentType; 847 final Type[] parentTypeArgs = parameterizedParentType.getActualTypeArguments().clone(); 848 for (int i = 0; i < parentTypeArgs.length; i++) { 849 final Type unrolled = unrollVariables(typeVarAssigns, parentTypeArgs[i]); 850 if (unrolled != null) { 851 parentTypeArgs[i] = unrolled; 852 } 853 } 854 return getTypeArguments(parameterizeWithOwner(parameterizedParentType.getOwnerType(), (Class<?>) parameterizedParentType.getRawType(), parentTypeArgs), toClass, typeVarAssigns); 855 } 856 return getTypeArguments(parentType, toClass, typeVarAssigns); 857 } 858 859 /** 860 * Gets the type arguments of a class/interface based on a subtype. For instance, this method will determine that both of the parameters for the interface 861 * {@link Map} are {@link Object} for the subtype {@link java.util.Properties Properties} even though the subtype does not directly implement the 862 * {@link Map} interface. 863 * 864 * <p> 865 * This method returns {@code null} if {@code type} is not assignable to {@code toClass}. It returns an empty map if none of the classes or interfaces in 866 * its inheritance hierarchy specify any type arguments. 867 * </p> 868 * 869 * <p> 870 * A side effect of this method is that it also retrieves the type arguments for the classes and interfaces that are part of the hierarchy between 871 * {@code type} and {@code toClass}. So with the above example, this method will also determine that the type arguments for {@link java.util.Hashtable 872 * Hashtable} are also both {@link Object}. In cases where the interface specified by {@code toClass} is (indirectly) implemented more than once (e.g. where 873 * {@code toClass} specifies the interface {@link Iterable Iterable} and {@code type} specifies a parameterized type that implements both 874 * {@link java.util.Set Set} and {@link java.util.Collection Collection}), this method will look at the inheritance hierarchy of only one of the 875 * implementations/subclasses; the first interface encountered that isn't a subinterface to one of the others in the {@code type} to {@code toClass} 876 * hierarchy. 877 * </p> 878 * 879 * @param type The type from which to determine the type parameters of {@code toClass} 880 * @param toClass The class whose type parameters are to be determined based on the subtype {@code type} 881 * @return A {@link Map} of the type assignments for the type variables in each type in the inheritance hierarchy from {@code type} to {@code toClass} 882 * inclusive. 883 */ 884 public static Map<TypeVariable<?>, Type> getTypeArguments(final Type type, final Class<?> toClass) { 885 return getTypeArguments(type, toClass, null); 886 } 887 888 /** 889 * Gets a map of the type arguments of {@code type} in the context of {@code toClass}. 890 * 891 * @param type The type in question. 892 * @param toClass The class. 893 * @param subtypeVarAssigns A map with type variables. 894 * @return The {@link Map} with type arguments. 895 */ 896 private static Map<TypeVariable<?>, Type> getTypeArguments(final Type type, final Class<?> toClass, final Map<TypeVariable<?>, Type> subtypeVarAssigns) { 897 if (type instanceof Class<?>) { 898 return getTypeArguments((Class<?>) type, toClass, subtypeVarAssigns); 899 } 900 if (type instanceof ParameterizedType) { 901 return getTypeArguments((ParameterizedType) type, toClass, subtypeVarAssigns); 902 } 903 if (type instanceof GenericArrayType) { 904 return getTypeArguments(((GenericArrayType) type).getGenericComponentType(), toClass.isArray() ? toClass.getComponentType() : toClass, 905 subtypeVarAssigns); 906 } 907 // since wildcard types are not assignable to classes, should this just 908 // return null? 909 if (type instanceof WildcardType) { 910 for (final Type bound : getImplicitUpperBounds((WildcardType) type)) { 911 // find the first bound that is assignable to the target class 912 if (isAssignable(bound, toClass)) { 913 return getTypeArguments(bound, toClass, subtypeVarAssigns); 914 } 915 } 916 return null; 917 } 918 if (type instanceof TypeVariable<?>) { 919 for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) { 920 // find the first bound that is assignable to the target class 921 if (isAssignable(bound, toClass)) { 922 return getTypeArguments(bound, toClass, subtypeVarAssigns); 923 } 924 } 925 return null; 926 } 927 throw new IllegalStateException("found an unhandled type: " + type); 928 } 929 930 /** 931 * Tests whether the specified type denotes an array type. 932 * 933 * @param type The type to be checked. 934 * @return {@code true} if {@code type} is an array class or a {@link GenericArrayType}. 935 */ 936 public static boolean isArrayType(final Type type) { 937 return type instanceof GenericArrayType || type instanceof Class<?> && ((Class<?>) type).isArray(); 938 } 939 940 /** 941 * Tests if the subject type may be implicitly cast to the target class following the Java generics rules. 942 * 943 * @param type The subject type to be assigned to the target type. 944 * @param toClass The target class. 945 * @return {@code true} if {@code type} is assignable to {@code toClass}. 946 */ 947 private static boolean isAssignable(final Type type, final Class<?> toClass) { 948 if (type == null) { 949 // consistency with ClassUtils.isAssignable() behavior 950 return toClass == null || !toClass.isPrimitive(); 951 } 952 // only a null type can be assigned to null type which 953 // would have cause the previous to return true 954 if (toClass == null) { 955 return false; 956 } 957 // all types are assignable to themselves 958 if (toClass.equals(type)) { 959 return true; 960 } 961 if (type instanceof Class<?>) { 962 // just comparing two classes 963 return ClassUtils.isAssignable((Class<?>) type, toClass); 964 } 965 if (type instanceof ParameterizedType) { 966 // only have to compare the raw type to the class 967 return isAssignable(getRawType((ParameterizedType) type), toClass); 968 } 969 // * 970 if (type instanceof TypeVariable<?>) { 971 // if any of the bounds are assignable to the class, then the 972 // type is assignable to the class. 973 for (final Type bound : ((TypeVariable<?>) type).getBounds()) { 974 if (isAssignable(bound, toClass)) { 975 return true; 976 } 977 } 978 return false; 979 } 980 // the only classes to which a generic array type can be assigned 981 // are class Object and array classes 982 if (type instanceof GenericArrayType) { 983 return toClass.equals(Object.class) 984 || toClass.isArray() && isAssignable(((GenericArrayType) type).getGenericComponentType(), toClass.getComponentType()); 985 } 986 // wildcard types are not assignable to a class (though one would think 987 // "? super Object" would be assignable to Object) 988 if (type instanceof WildcardType) { 989 return false; 990 } 991 throw new IllegalStateException("found an unhandled type: " + type); 992 } 993 994 /** 995 * Tests if the subject type may be implicitly cast to the target generic array type following the Java generics rules. 996 * 997 * @param type The subject type to be assigned to the target type. 998 * @param toGenericArrayType The target generic array type. 999 * @param typeVarAssigns A map with type variables. 1000 * @return {@code true} if {@code type} is assignable to {@code toGenericArrayType}. 1001 */ 1002 private static boolean isAssignable(final Type type, final GenericArrayType toGenericArrayType, final Map<TypeVariable<?>, Type> typeVarAssigns) { 1003 if (type == null) { 1004 return true; 1005 } 1006 // only a null type can be assigned to null type which 1007 // would have cause the previous to return true 1008 if (toGenericArrayType == null) { 1009 return false; 1010 } 1011 // all types are assignable to themselves 1012 if (toGenericArrayType.equals(type)) { 1013 return true; 1014 } 1015 final Type toComponentType = toGenericArrayType.getGenericComponentType(); 1016 if (type instanceof Class<?>) { 1017 final Class<?> cls = (Class<?>) type; 1018 // compare the component types 1019 return cls.isArray() && isAssignable(cls.getComponentType(), toComponentType, typeVarAssigns); 1020 } 1021 if (type instanceof GenericArrayType) { 1022 // compare the component types 1023 return isAssignable(((GenericArrayType) type).getGenericComponentType(), toComponentType, typeVarAssigns); 1024 } 1025 if (type instanceof WildcardType) { 1026 // so long as one of the upper bounds is assignable, it's good 1027 for (final Type bound : getImplicitUpperBounds((WildcardType) type)) { 1028 if (isAssignable(bound, toGenericArrayType)) { 1029 return true; 1030 } 1031 } 1032 return false; 1033 } 1034 if (type instanceof TypeVariable<?>) { 1035 // probably should remove the following logic and just return false. 1036 // type variables cannot specify arrays as bounds. 1037 for (final Type bound : getImplicitBounds((TypeVariable<?>) type)) { 1038 if (isAssignable(bound, toGenericArrayType)) { 1039 return true; 1040 } 1041 } 1042 return false; 1043 } 1044 if (type instanceof ParameterizedType) { 1045 // the raw type of a parameterized type is never an array or 1046 // generic array, otherwise the declaration would look like this: 1047 // Collection[]< ? extends String > collection; 1048 return false; 1049 } 1050 throw new IllegalStateException("found an unhandled type: " + type); 1051 } 1052 1053 /** 1054 * Tests if the subject type may be implicitly cast to the target parameterized type following the Java generics rules. 1055 * 1056 * @param type The subject type to be assigned to the target type. 1057 * @param toParameterizedType The target parameterized type. 1058 * @param typeVarAssigns A map with type variables. 1059 * @return {@code true} if {@code type} is assignable to {@code toType}. 1060 */ 1061 private static boolean isAssignable(final Type type, final ParameterizedType toParameterizedType, final Map<TypeVariable<?>, Type> typeVarAssigns) { 1062 if (type == null) { 1063 return true; 1064 } 1065 // only a null type can be assigned to null type which 1066 // would have cause the previous to return true 1067 if (toParameterizedType == null) { 1068 return false; 1069 } 1070 // cannot cast an array type to a parameterized type. 1071 if (type instanceof GenericArrayType) { 1072 return false; 1073 } 1074 // all types are assignable to themselves 1075 if (toParameterizedType.equals(type)) { 1076 return true; 1077 } 1078 // get the target type's raw type 1079 final Class<?> toClass = getRawType(toParameterizedType); 1080 // get the subject type's type arguments including owner type arguments 1081 // and supertype arguments up to and including the target class. 1082 final Map<TypeVariable<?>, Type> fromTypeVarAssigns = getTypeArguments(type, toClass, null); 1083 // null means the two types are not compatible 1084 if (fromTypeVarAssigns == null) { 1085 return false; 1086 } 1087 // compatible types, but there's no type arguments. this is equivalent 1088 // to comparing Map< ?, ? > to Map, and raw types are always assignable 1089 // to parameterized types. 1090 if (fromTypeVarAssigns.isEmpty()) { 1091 return true; 1092 } 1093 // get the target type's type arguments including owner type arguments 1094 final Map<TypeVariable<?>, Type> toTypeVarAssigns = getTypeArguments(toParameterizedType, toClass, typeVarAssigns); 1095 // Class<T> is not assignable to Class<S> if T is not S (even if T extends S) 1096 if (toClass.equals(Class.class)) { 1097 final TypeVariable<?>[] typeParams = toClass.getTypeParameters(); 1098 if (typeParams.length > 0) { 1099 final Type toTypeArg = unrollVariableAssignments(typeParams[0], toTypeVarAssigns); 1100 final Type fromTypeArg = unrollVariableAssignments(typeParams[0], fromTypeVarAssigns); 1101 if (toTypeArg != null && (fromTypeArg == null || !toTypeArg.equals(fromTypeArg))) { 1102 return false; 1103 } 1104 } 1105 } 1106 // now to check each type argument 1107 for (final TypeVariable<?> var : toTypeVarAssigns.keySet()) { 1108 final Type toTypeArg = unrollVariableAssignments(var, toTypeVarAssigns); 1109 final Type fromTypeArg = unrollVariableAssignments(var, fromTypeVarAssigns); 1110 if (toTypeArg == null && fromTypeArg instanceof Class) { 1111 continue; 1112 } 1113 // parameters must either be absent from the subject type, within 1114 // the bounds of the wildcard type, or be an exact match to the 1115 // parameters of the target type. 1116 if (fromTypeArg != null && toTypeArg != null && !toTypeArg.equals(fromTypeArg) 1117 && !(toTypeArg instanceof WildcardType && isAssignable(fromTypeArg, toTypeArg, typeVarAssigns))) { 1118 return false; 1119 } 1120 } 1121 return true; 1122 } 1123 1124 /** 1125 * Tests if the subject type may be implicitly cast to the target type following the Java generics rules. If both types are {@link Class} objects, the 1126 * method returns the result of {@link ClassUtils#isAssignable(Class, Class)}. 1127 * 1128 * @param type The subject type to be assigned to the target type. 1129 * @param toType The target type. 1130 * @return {@code true} if {@code type} is assignable to {@code toType}. 1131 */ 1132 public static boolean isAssignable(final Type type, final Type toType) { 1133 return isAssignable(type, toType, null); 1134 } 1135 1136 /** 1137 * Tests if the subject type may be implicitly cast to the target type following the Java generics rules. 1138 * 1139 * @param type The subject type to be assigned to the target type. 1140 * @param toType The target type. 1141 * @param typeVarAssigns optional map of type variable assignments. 1142 * @return {@code true} if {@code type} is assignable to {@code toType}. 1143 */ 1144 private static boolean isAssignable(final Type type, final Type toType, final Map<TypeVariable<?>, Type> typeVarAssigns) { 1145 if (toType == null || toType instanceof Class<?>) { 1146 return isAssignable(type, (Class<?>) toType); 1147 } 1148 if (toType instanceof ParameterizedType) { 1149 return isAssignable(type, (ParameterizedType) toType, typeVarAssigns); 1150 } 1151 if (toType instanceof GenericArrayType) { 1152 return isAssignable(type, (GenericArrayType) toType, typeVarAssigns); 1153 } 1154 if (toType instanceof WildcardType) { 1155 return isAssignable(type, (WildcardType) toType, typeVarAssigns); 1156 } 1157 if (toType instanceof TypeVariable<?>) { 1158 return isAssignable(type, (TypeVariable<?>) toType, typeVarAssigns); 1159 } 1160 throw new IllegalStateException("found an unhandled type: " + toType); 1161 } 1162 1163 /** 1164 * Tests if the subject type may be implicitly cast to the target type variable following the Java generics rules. 1165 * 1166 * @param type The subject type to be assigned to the target type. 1167 * @param toTypeVariable The target type variable. 1168 * @param typeVarAssigns A map with type variables. 1169 * @return {@code true} if {@code type} is assignable to {@code toTypeVariable}. 1170 */ 1171 private static boolean isAssignable(final Type type, final TypeVariable<?> toTypeVariable, final Map<TypeVariable<?>, Type> typeVarAssigns) { 1172 if (type == null) { 1173 return true; 1174 } 1175 // only a null type can be assigned to null type which 1176 // would have cause the previous to return true 1177 if (toTypeVariable == null) { 1178 return false; 1179 } 1180 // all types are assignable to themselves 1181 if (toTypeVariable.equals(type)) { 1182 return true; 1183 } 1184 if (type instanceof TypeVariable<?>) { 1185 // a type variable is assignable to another type variable, if 1186 // and only if the former is the latter, extends the latter, or 1187 // is otherwise a descendant of the latter. 1188 final Type[] bounds = getImplicitBounds((TypeVariable<?>) type); 1189 for (final Type bound : bounds) { 1190 if (isAssignable(bound, toTypeVariable, typeVarAssigns)) { 1191 return true; 1192 } 1193 } 1194 } 1195 if (type instanceof Class<?> || type instanceof ParameterizedType || type instanceof GenericArrayType || type instanceof WildcardType) { 1196 return false; 1197 } 1198 throw new IllegalStateException("found an unhandled type: " + type); 1199 } 1200 1201 /** 1202 * Tests if the subject type may be implicitly cast to the target wildcard type following the Java generics rules. 1203 * 1204 * @param type The subject type to be assigned to the target type. 1205 * @param toWildcardType The target wildcard type. 1206 * @param typeVarAssigns A map with type variables. 1207 * @return {@code true} if {@code type} is assignable to {@code toWildcardType}. 1208 */ 1209 private static boolean isAssignable(final Type type, final WildcardType toWildcardType, final Map<TypeVariable<?>, Type> typeVarAssigns) { 1210 if (type == null) { 1211 return true; 1212 } 1213 // only a null type can be assigned to null type which 1214 // would have cause the previous to return true 1215 if (toWildcardType == null) { 1216 return false; 1217 } 1218 // all types are assignable to themselves 1219 if (toWildcardType.equals(type)) { 1220 return true; 1221 } 1222 final Type[] toUpperBounds = getImplicitUpperBounds(toWildcardType); 1223 final Type[] toLowerBounds = getImplicitLowerBounds(toWildcardType); 1224 if (type instanceof WildcardType) { 1225 final WildcardType wildcardType = (WildcardType) type; 1226 final Type[] upperBounds = getImplicitUpperBounds(wildcardType); 1227 final Type[] lowerBounds = getImplicitLowerBounds(wildcardType); 1228 for (Type toBound : toUpperBounds) { 1229 // if there are assignments for unresolved type variables, 1230 // now's the time to substitute them. 1231 toBound = substituteTypeVariables(toBound, typeVarAssigns); 1232 // at least one upper bound of the subject type has to be assignable to 1233 // each upper bound of the target type 1234 boolean satisfied = false; 1235 for (final Type bound : upperBounds) { 1236 if (isAssignable(bound, toBound, typeVarAssigns)) { 1237 satisfied = true; 1238 break; 1239 } 1240 } 1241 if (!satisfied) { 1242 return false; 1243 } 1244 } 1245 for (Type toBound : toLowerBounds) { 1246 // if there are assignments for unresolved type variables, 1247 // now's the time to substitute them. 1248 toBound = substituteTypeVariables(toBound, typeVarAssigns); 1249 // each lower bound of the target type has to be assignable to 1250 // each lower bound of the subject type 1251 for (final Type bound : lowerBounds) { 1252 if (!isAssignable(toBound, bound, typeVarAssigns)) { 1253 return false; 1254 } 1255 } 1256 } 1257 return true; 1258 } 1259 for (final Type toBound : toUpperBounds) { 1260 // if there are assignments for unresolved type variables, 1261 // now's the time to substitute them. 1262 if (!isAssignable(type, substituteTypeVariables(toBound, typeVarAssigns), typeVarAssigns)) { 1263 return false; 1264 } 1265 } 1266 for (final Type toBound : toLowerBounds) { 1267 // if there are assignments for unresolved type variables, 1268 // now's the time to substitute them. 1269 if (!isAssignable(substituteTypeVariables(toBound, typeVarAssigns), type, typeVarAssigns)) { 1270 return false; 1271 } 1272 } 1273 return true; 1274 } 1275 1276 /** 1277 * Tests whether the class contains a cyclical reference in the qualified name of a class. If any of the type parameters of A class is extending X class 1278 * which is in scope of A class, then it forms cycle. 1279 * 1280 * @param cls The class to test. 1281 * @return whether the class contains a cyclical reference. 1282 */ 1283 private static boolean isCyclical(final Class<?> cls) { 1284 for (final TypeVariable<?> typeParameter : cls.getTypeParameters()) { 1285 for (final Type bound : typeParameter.getBounds()) { 1286 if (bound.getTypeName().contains(cls.getName())) { 1287 return true; 1288 } 1289 } 1290 } 1291 return false; 1292 } 1293 1294 /** 1295 * Tests if the given value can be assigned to the target type following the Java generics rules. 1296 * 1297 * @param value The value to be checked. 1298 * @param type The target type. 1299 * @return {@code true} if {@code value} is an instance of {@code type}. 1300 */ 1301 public static boolean isInstance(final Object value, final Type type) { 1302 if (type == null) { 1303 return false; 1304 } 1305 return value == null ? !(type instanceof Class<?>) || !((Class<?>) type).isPrimitive() : isAssignable(value.getClass(), type, null); 1306 } 1307 1308 /** 1309 * Maps type variables. 1310 * 1311 * @param <T> the generic type of the class in question. 1312 * @param cls The class in question. 1313 * @param parameterizedType The parameterized type. 1314 * @param typeVarAssigns The map to be filled. 1315 */ 1316 private static <T> void mapTypeVariablesToArguments(final Class<T> cls, final ParameterizedType parameterizedType, 1317 final Map<TypeVariable<?>, Type> typeVarAssigns) { 1318 // capture the type variables from the owner type that have assignments 1319 final Type ownerType = parameterizedType.getOwnerType(); 1320 if (ownerType instanceof ParameterizedType) { 1321 // recursion to make sure the owner's owner type gets processed 1322 mapTypeVariablesToArguments(cls, (ParameterizedType) ownerType, typeVarAssigns); 1323 } 1324 // parameterizedType is a generic interface/class (or it's in the owner 1325 // hierarchy of said interface/class) implemented/extended by the class 1326 // cls. Find out which type variables of cls are type arguments of 1327 // parameterizedType: 1328 final Type[] typeArgs = parameterizedType.getActualTypeArguments(); 1329 // of the cls's type variables that are arguments of parameterizedType, 1330 // find out which ones can be determined from the super type's arguments 1331 final TypeVariable<?>[] typeVars = getRawType(parameterizedType).getTypeParameters(); 1332 // use List view of type parameters of cls so the contains() method can be used: 1333 final List<TypeVariable<Class<T>>> typeVarList = Arrays.asList(cls.getTypeParameters()); 1334 for (int i = 0; i < typeArgs.length; i++) { 1335 final TypeVariable<?> typeVar = typeVars[i]; 1336 final Type typeArg = typeArgs[i]; 1337 // argument of parameterizedType is a type variable of cls 1338 if (typeVarList.contains(typeArg) 1339 // type variable of parameterizedType has an assignment in 1340 // the super type. 1341 && typeVarAssigns.containsKey(typeVar)) { 1342 // map the assignment to the cls's type variable 1343 typeVarAssigns.put((TypeVariable<?>) typeArg, typeVarAssigns.get(typeVar)); 1344 } 1345 } 1346 } 1347 1348 /** 1349 * Strips out the redundant upper bound types in type variable types and wildcard types (or it would with wildcard types if multiple upper bounds were 1350 * allowed). 1351 * 1352 * <p> 1353 * Example, with the variable type declaration: 1354 * </p> 1355 * 1356 * <pre>{@code 1357 * <K extends java.util.Collection<String> & java.util.List<String>> 1358 * }</pre> 1359 * 1360 * <p> 1361 * since {@link List} is a subinterface of {@link Collection}, this method will return the bounds as if the declaration had been: 1362 * </p> 1363 * 1364 * <pre>{@code 1365 * <K extends java.util.List<String>> 1366 * }</pre> 1367 * 1368 * @param bounds An array of types representing the upper bounds of either {@link WildcardType} or {@link TypeVariable}, not {@code null}. 1369 * @return An array containing the values from {@code bounds} minus the redundant types. 1370 * @throws NullPointerException Thrown if {@code bounds} is {@code null}. 1371 */ 1372 public static Type[] normalizeUpperBounds(final Type[] bounds) { 1373 Objects.requireNonNull(bounds, "bounds"); 1374 // don't bother if there's only one (or none) type 1375 if (bounds.length < 2) { 1376 return bounds; 1377 } 1378 final Set<Type> types = new HashSet<>(bounds.length); 1379 for (final Type type1 : bounds) { 1380 boolean subtypeFound = false; 1381 for (final Type type2 : bounds) { 1382 if (type1 != type2 && isAssignable(type2, type1, null)) { 1383 subtypeFound = true; 1384 break; 1385 } 1386 } 1387 if (!subtypeFound) { 1388 types.add(type1); 1389 } 1390 } 1391 return types.toArray(ArrayUtils.EMPTY_TYPE_ARRAY); 1392 } 1393 1394 /** 1395 * Delegates to {@link #normalizeUpperBounds(Type[])} unless {@code bounds} is empty in which case return an array with the element {@code Object.class}. 1396 * 1397 * @param bounds bounds an array of types representing the upper bounds of either {@link WildcardType} or {@link TypeVariable}, not {@code null}. 1398 * @return result from {@link #normalizeUpperBounds(Type[])} unless {@code bounds} is empty in which case return an array with the element 1399 * {@code Object.class}. 1400 */ 1401 private static Type[] normalizeUpperToObject(final Type[] bounds) { 1402 return bounds.length == 0 ? new Type[] { Object.class } : normalizeUpperBounds(bounds); 1403 } 1404 1405 /** 1406 * Creates a parameterized type instance. 1407 * 1408 * @param rawClass The raw class to create a parameterized type instance for. 1409 * @param typeVariableMap The map used for parameterization. 1410 * @return {@link ParameterizedType}. 1411 * @throws NullPointerException Thrown if either {@code rawClass} or {@code typeVariableMap} is {@code null}. 1412 * @since 3.2 1413 */ 1414 public static final ParameterizedType parameterize(final Class<?> rawClass, final Map<TypeVariable<?>, Type> typeVariableMap) { 1415 Objects.requireNonNull(rawClass, "rawClass"); 1416 Objects.requireNonNull(typeVariableMap, "typeVariableMap"); 1417 return parameterizeWithOwner(null, rawClass, extractTypeArgumentsFrom(typeVariableMap, rawClass.getTypeParameters())); 1418 } 1419 1420 /** 1421 * Creates a parameterized type instance. 1422 * 1423 * @param rawClass The raw class to create a parameterized type instance for. 1424 * @param typeArguments The types used for parameterization. 1425 * @return {@link ParameterizedType}. 1426 * @throws NullPointerException Thrown if {@code rawClass} is {@code null}. 1427 * @since 3.2 1428 */ 1429 public static final ParameterizedType parameterize(final Class<?> rawClass, final Type... typeArguments) { 1430 return parameterizeWithOwner(null, rawClass, typeArguments); 1431 } 1432 1433 /** 1434 * Formats a {@link ParameterizedType} as a {@link String}. 1435 * 1436 * @param parameterizedType {@link ParameterizedType} to format. 1437 * @return String. 1438 */ 1439 private static String parameterizedTypeToString(final ParameterizedType parameterizedType) { 1440 final StringBuilder builder = new StringBuilder(); 1441 final Type useOwner = parameterizedType.getOwnerType(); 1442 final Class<?> raw = (Class<?>) parameterizedType.getRawType(); 1443 if (useOwner == null) { 1444 builder.append(raw.getName()); 1445 } else { 1446 if (useOwner instanceof Class<?>) { 1447 builder.append(((Class<?>) useOwner).getName()); 1448 } else { 1449 builder.append(toString(useOwner)); 1450 } 1451 builder.append('.').append(raw.getSimpleName()); 1452 } 1453 final Type[] typeArguments = parameterizedType.getActualTypeArguments(); 1454 if (typeArguments.length > 0) { 1455 TYPE_ARG_JOINER.join(builder, typeArguments); 1456 } 1457 return builder.toString(); 1458 } 1459 1460 /** 1461 * Creates a parameterized type instance. 1462 * 1463 * @param owner The owning type. 1464 * @param rawClass The raw class to create a parameterized type instance for. 1465 * @param typeVariableMap The map used for parameterization. 1466 * @return {@link ParameterizedType}. 1467 * @throws NullPointerException Thrown if either {@code rawClass} or {@code typeVariableMap} is {@code null}. 1468 * @since 3.2 1469 */ 1470 public static final ParameterizedType parameterizeWithOwner(final Type owner, final Class<?> rawClass, final Map<TypeVariable<?>, Type> typeVariableMap) { 1471 Objects.requireNonNull(rawClass, "rawClass"); 1472 Objects.requireNonNull(typeVariableMap, "typeVariableMap"); 1473 return parameterizeWithOwner(owner, rawClass, extractTypeArgumentsFrom(typeVariableMap, rawClass.getTypeParameters())); 1474 } 1475 1476 /** 1477 * Creates a parameterized type instance. 1478 * 1479 * @param owner The owning type. 1480 * @param rawClass The raw class to create a parameterized type instance for. 1481 * @param typeArguments The types used for parameterization. 1482 * @return {@link ParameterizedType}. 1483 * @throws NullPointerException Thrown if {@code rawClass} is {@code null}. 1484 * @since 3.2 1485 */ 1486 public static final ParameterizedType parameterizeWithOwner(final Type owner, final Class<?> rawClass, final Type... typeArguments) { 1487 Objects.requireNonNull(rawClass, "rawClass"); 1488 final Type useOwner; 1489 if (rawClass.getEnclosingClass() == null) { 1490 Validate.isTrue(owner == null, "no owner allowed for top-level %s", rawClass); 1491 useOwner = null; 1492 } else if (owner == null) { 1493 useOwner = rawClass.getEnclosingClass(); 1494 } else { 1495 Validate.isTrue(isAssignable(owner, rawClass.getEnclosingClass()), "%s is invalid owner type for parameterized %s", owner, rawClass); 1496 useOwner = owner; 1497 } 1498 Validate.noNullElements(typeArguments, "null type argument at index %s"); 1499 Validate.isTrue(rawClass.getTypeParameters().length == typeArguments.length, "invalid number of type parameters specified: expected %d, got %d", 1500 rawClass.getTypeParameters().length, typeArguments.length); 1501 return new ParameterizedTypeImpl(rawClass, useOwner, typeArguments); 1502 } 1503 1504 /** 1505 * Finds the mapping for {@code type} in {@code typeVarAssigns}. 1506 * 1507 * @param type The type to be replaced. 1508 * @param typeVarAssigns The map with type variables. 1509 * @return The replaced type. 1510 * @throws IllegalArgumentException Thrown if the type cannot be substituted. 1511 */ 1512 private static Type substituteTypeVariables(final Type type, final Map<TypeVariable<?>, Type> typeVarAssigns) { 1513 if (type instanceof TypeVariable<?> && typeVarAssigns != null) { 1514 final Type replacementType = typeVarAssigns.get(type); 1515 if (replacementType == null) { 1516 throw new IllegalArgumentException("missing assignment type for type variable " + type); 1517 } 1518 return replacementType; 1519 } 1520 return type; 1521 } 1522 1523 private static String toCyclicString(final Type type) { 1524 if (type instanceof Class<?>) { 1525 return ((Class<?>) type).getSimpleName() + "(cycle)"; 1526 } 1527 if (type instanceof TypeVariable<?>) { 1528 return ((TypeVariable<?>) type).getName() + "(cycle)"; 1529 } 1530 if (type instanceof WildcardType) { 1531 return "? (cycle)"; 1532 } 1533 if (type instanceof ParameterizedType) { 1534 final ParameterizedType pt = (ParameterizedType) type; 1535 final Type raw = pt.getRawType(); 1536 final String rawName = raw instanceof Class<?> ? ((Class<?>) raw).getSimpleName() : raw.getTypeName(); 1537 return rawName + "(cycle)"; 1538 } 1539 if (type instanceof GenericArrayType) { 1540 return "(cycle)"; 1541 } 1542 return ObjectUtils.identityToString(type) + "(cycle)"; 1543 } 1544 1545 /** 1546 * Formats a {@link TypeVariable} including its {@link GenericDeclaration}. 1547 * 1548 * @param typeVariable The type variable to create a String representation for, not {@code null}. 1549 * @return String. 1550 * @throws NullPointerException Thrown if {@code typeVariable} is {@code null}. 1551 * @since 3.2 1552 */ 1553 public static String toLongString(final TypeVariable<?> typeVariable) { 1554 Objects.requireNonNull(typeVariable, "typeVariable"); 1555 final StringBuilder buf = new StringBuilder(); 1556 final GenericDeclaration d = typeVariable.getGenericDeclaration(); 1557 if (d instanceof Class<?>) { 1558 Class<?> c = (Class<?>) d; 1559 while (true) { 1560 if (c.getEnclosingClass() == null) { 1561 buf.insert(0, c.getName()); 1562 break; 1563 } 1564 buf.insert(0, c.getSimpleName()).insert(0, '.'); 1565 c = c.getEnclosingClass(); 1566 } 1567 } else if (d instanceof Type) { // not possible as of now 1568 buf.append(toString((Type) d)); 1569 } else { 1570 buf.append(d); 1571 } 1572 return buf.append(':').append(toString(typeVariable)).toString(); 1573 } 1574 1575 /** 1576 * Formats a {@link Type} as a type reference string (type variables are formatted by name only without bounds). 1577 * 1578 * @param type The type to format. 1579 * @return String. 1580 */ 1581 private static String toReferenceString(final Type type) { 1582 if (type instanceof TypeVariable<?>) { 1583 return ((TypeVariable<?>) type).getName(); 1584 } 1585 return toString(type); 1586 } 1587 1588 /** 1589 * Formats a given type as a Java-esque String. 1590 * 1591 * @param type The type to create a String representation for, not {@code null}. 1592 * @return String. 1593 * @throws NullPointerException Thrown if {@code type} is {@code null}. 1594 * @since 3.2 1595 */ 1596 public static String toString(final Type type) { 1597 Objects.requireNonNull(type, "type"); 1598 final Set<Type> visiting = VISITING.get(); 1599 if (!visiting.add(type)) { 1600 return toCyclicString(type); 1601 } 1602 try { 1603 if (type instanceof Class<?>) { 1604 return classToString((Class<?>) type); 1605 } 1606 if (type instanceof ParameterizedType) { 1607 return parameterizedTypeToString((ParameterizedType) type); 1608 } 1609 if (type instanceof WildcardType) { 1610 return wildcardTypeToString((WildcardType) type); 1611 } 1612 if (type instanceof TypeVariable<?>) { 1613 return typeVariableToString((TypeVariable<?>) type); 1614 } 1615 if (type instanceof GenericArrayType) { 1616 return genericArrayTypeToString((GenericArrayType) type); 1617 } 1618 throw new IllegalArgumentException(ObjectUtils.identityToString(type)); 1619 } finally { 1620 visiting.remove(type); 1621 if (visiting.isEmpty()) { 1622 VISITING.remove(); 1623 } 1624 } 1625 } 1626 1627 /** 1628 * Determines whether or not specified types satisfy the bounds of their mapped type variables. When a type parameter extends another (such as 1629 * {@code <T, S extends T>}), uses another as a type parameter (such as {@code <T, S extends Comparable>>}), or otherwise depends on another type variable 1630 * to be specified, the dependencies must be included in {@code typeVarAssigns}. 1631 * 1632 * @param typeVariableMap specifies the potential types to be assigned to the type variables, not {@code null}. 1633 * @return whether or not the types can be assigned to their respective type variables. 1634 * @throws NullPointerException Thrown if {@code typeVariableMap} is {@code null}. 1635 */ 1636 public static boolean typesSatisfyVariables(final Map<TypeVariable<?>, Type> typeVariableMap) { 1637 Objects.requireNonNull(typeVariableMap, "typeVariableMap"); 1638 // all types must be assignable to all the bounds of their mapped 1639 // type variable. 1640 for (final Map.Entry<TypeVariable<?>, Type> entry : typeVariableMap.entrySet()) { 1641 final TypeVariable<?> typeVar = entry.getKey(); 1642 final Type type = entry.getValue(); 1643 for (final Type bound : getImplicitBounds(typeVar)) { 1644 if (!isAssignable(type, substituteTypeVariables(bound, typeVariableMap), typeVariableMap)) { 1645 return false; 1646 } 1647 } 1648 } 1649 return true; 1650 } 1651 1652 /** 1653 * Formats a {@link TypeVariable} as a {@link String}. 1654 * 1655 * @param typeVariable {@link TypeVariable} to format. 1656 * @return String. 1657 */ 1658 private static String typeVariableToString(final TypeVariable<?> typeVariable) { 1659 final StringBuilder builder = new StringBuilder(typeVariable.getName()); 1660 final Type[] bounds = typeVariable.getBounds(); 1661 if (bounds.length > 0 && !(bounds.length == 1 && Object.class.equals(bounds[0]))) { 1662 builder.append(" extends "); 1663 AMP_JOINER.join(builder, bounds); 1664 } 1665 return builder.toString(); 1666 } 1667 1668 /** 1669 * Unrolls variables in a type bounds array. 1670 * 1671 * @param typeArguments assignments {@link Map}. 1672 * @param bounds in which to expand variables. 1673 * @return {@code bounds} with any variables reassigned. 1674 */ 1675 private static Type[] unrollBounds(final Map<TypeVariable<?>, Type> typeArguments, final Type[] bounds) { 1676 Type[] result = bounds; 1677 int i = 0; 1678 for (; i < result.length; i++) { 1679 final Type unrolled = unrollVariables(typeArguments, result[i]); 1680 if (unrolled == null) { 1681 result = ArrayUtils.remove(result, i--); 1682 } else { 1683 result[i] = unrolled; 1684 } 1685 } 1686 return result; 1687 } 1688 1689 /** 1690 * Looks up {@code typeVariable} in {@code typeVarAssigns} <em>transitively</em>, i.e. keep looking until the value found is <em>not</em> a type variable. 1691 * 1692 * @param typeVariable The type variable to look up. 1693 * @param typeVarAssigns The map used for the look-up. 1694 * @return Type or {@code null} if some variable was not in the map. 1695 */ 1696 private static Type unrollVariableAssignments(TypeVariable<?> typeVariable, final Map<TypeVariable<?>, Type> typeVarAssigns) { 1697 Type result; 1698 do { 1699 result = typeVarAssigns.get(typeVariable); 1700 if (!(result instanceof TypeVariable<?>) || result.equals(typeVariable)) { 1701 break; 1702 } 1703 typeVariable = (TypeVariable<?>) result; 1704 } while (true); 1705 return result; 1706 } 1707 1708 /** 1709 * Gets a type representing {@code type} with variable assignments "unrolled." 1710 * 1711 * @param typeArguments as from {@link TypeUtils#getTypeArguments(Type, Class)}. 1712 * @param type The type to unroll variable assignments for. 1713 * @return Type. 1714 * @since 3.2 1715 */ 1716 public static Type unrollVariables(Map<TypeVariable<?>, Type> typeArguments, final Type type) { 1717 if (typeArguments == null) { 1718 typeArguments = Collections.emptyMap(); 1719 } 1720 return unrollVariables(typeArguments, type, new HashSet<>()); 1721 } 1722 1723 private static Type unrollVariables(final Map<TypeVariable<?>, Type> typeArguments, final Type type, final Set<TypeVariable<?>> visited) { 1724 if (containsTypeVariables(type)) { 1725 if (type instanceof TypeVariable<?>) { 1726 final TypeVariable<?> var = (TypeVariable<?>) type; 1727 if (!visited.add(var)) { 1728 return var; 1729 } 1730 return unrollVariables(typeArguments, typeArguments.get(type), visited); 1731 } 1732 if (type instanceof ParameterizedType) { 1733 final ParameterizedType p = (ParameterizedType) type; 1734 final Map<TypeVariable<?>, Type> parameterizedTypeArguments; 1735 if (p.getOwnerType() == null) { 1736 parameterizedTypeArguments = typeArguments; 1737 } else { 1738 parameterizedTypeArguments = new HashMap<>(typeArguments); 1739 parameterizedTypeArguments.putAll(getTypeArguments(p)); 1740 } 1741 final Type[] args = p.getActualTypeArguments().clone(); 1742 for (int i = 0; i < args.length; i++) { 1743 final Type unrolled = unrollVariables(parameterizedTypeArguments, args[i], visited); 1744 if (unrolled != null) { 1745 args[i] = unrolled; 1746 } 1747 } 1748 return parameterizeWithOwner(p.getOwnerType(), (Class<?>) p.getRawType(), args); 1749 } 1750 if (type instanceof WildcardType) { 1751 final WildcardType wild = (WildcardType) type; 1752 return wildcardType().withUpperBounds(unrollBounds(typeArguments, wild.getUpperBounds())) 1753 .withLowerBounds(unrollBounds(typeArguments, wild.getLowerBounds())).build(); 1754 } 1755 } 1756 return type; 1757 } 1758 1759 /** 1760 * Creates a new {@link WildcardTypeBuilder}. 1761 * 1762 * @return A new {@link WildcardTypeBuilder}. 1763 * @since 3.2 1764 */ 1765 public static WildcardTypeBuilder wildcardType() { 1766 return new WildcardTypeBuilder(); 1767 } 1768 1769 /** 1770 * Formats a {@link WildcardType} as a {@link String}. 1771 * 1772 * @param wildcardType {@link WildcardType} to format. 1773 * @return String. 1774 */ 1775 private static String wildcardTypeToString(final WildcardType wildcardType) { 1776 final StringBuilder builder = new StringBuilder().append('?'); 1777 final Type[] lowerBounds = wildcardType.getLowerBounds(); 1778 final Type[] upperBounds = wildcardType.getUpperBounds(); 1779 if (lowerBounds.length > 1 || lowerBounds.length == 1 && lowerBounds[0] != null) { 1780 AMP_JOINER.join(builder.append(" super "), lowerBounds); 1781 } else if (upperBounds.length > 1 || upperBounds.length == 1 && !Object.class.equals(upperBounds[0])) { 1782 AMP_JOINER.join(builder.append(" extends "), upperBounds); 1783 } 1784 return builder.toString(); 1785 } 1786 1787 /** 1788 * Wraps the specified {@link Class} in a {@link Typed} wrapper. 1789 * 1790 * @param <T> generic type. 1791 * @param type to wrap. 1792 * @return {@code Typed<T>}. 1793 * @since 3.2 1794 */ 1795 public static <T> Typed<T> wrap(final Class<T> type) { 1796 return wrap((Type) type); 1797 } 1798 1799 /** 1800 * Wraps the specified {@link Type} in a {@link Typed} wrapper. 1801 * 1802 * @param <T> inferred generic type. 1803 * @param type to wrap. 1804 * @return {@code Typed<T>}. 1805 * @since 3.2 1806 */ 1807 public static <T> Typed<T> wrap(final Type type) { 1808 return () -> type; 1809 } 1810 1811 /** 1812 * {@link TypeUtils} instances should NOT be constructed in standard programming. Instead, the class should be used as 1813 * {@code TypeUtils.isAssignable(cls, toClass)}. 1814 * <p> 1815 * This constructor is public to permit tools that require a JavaBean instance to operate. 1816 * </p> 1817 * 1818 * @deprecated TODO Make private in 4.0. 1819 */ 1820 @Deprecated 1821 public TypeUtils() { 1822 // empty 1823 } 1824 1825}