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 */ 017 package org.apache.commons.lang3.reflect; 018 019 import java.lang.reflect.Array; 020 import java.lang.reflect.GenericArrayType; 021 import java.lang.reflect.ParameterizedType; 022 import java.lang.reflect.Type; 023 import java.lang.reflect.TypeVariable; 024 import java.lang.reflect.WildcardType; 025 import java.util.Arrays; 026 import java.util.HashMap; 027 import java.util.HashSet; 028 import java.util.List; 029 import java.util.Map; 030 import java.util.Set; 031 032 import org.apache.commons.lang3.ClassUtils; 033 034 /** 035 * <p> Utility methods focusing on type inspection, particularly with regard to 036 * generics. </p> 037 * 038 * @author David M. Sledge 039 * @author Matt Benson 040 * @author James Carman 041 * @since 3.0 042 * @version $Id: TypeUtils.java 966171 2010-07-21 10:47:57Z sebb $ 043 */ 044 public class TypeUtils { 045 046 /** 047 * <p> TypeUtils instances should NOT be constructed in standard 048 * programming. Instead, the class should be used as 049 * <code>TypeUtils.isAssignable(cls, toClass)</code>. </p> <p> This 050 * constructor is public to permit tools that require a JavaBean instance to 051 * operate. </p> 052 */ 053 public TypeUtils() { 054 super(); 055 } 056 057 /** 058 * <p> Checks if the subject type may be implicitly cast to the target type 059 * following the Java generics rules. If both types are {@link Class} 060 * objects, the method returns the result of 061 * {@link ClassUtils#isAssignable(Class, Class)}. </p> 062 * 063 * @param type the subject type to be assigned to the target type 064 * @param toType the target type 065 * @return <code>true</code> if <code>type</code> is assignable to <code>toType</code>. 066 */ 067 public static boolean isAssignable(Type type, Type toType) { 068 return isAssignable(type, toType, null); 069 } 070 071 /** 072 * <p> Checks if the subject type may be implicitly cast to the target type 073 * following the Java generics rules. </p> 074 * 075 * @param type the subject type to be assigned to the target type 076 * @param toType the target type 077 * @param typeVarAssigns optional map of type variable assignments 078 * @return <code>true</code> if <code>type</code> is assignable to <code>toType</code>. 079 */ 080 private static boolean isAssignable(Type type, Type toType, 081 Map<TypeVariable<?>, Type> typeVarAssigns) { 082 if (toType == null || toType instanceof Class<?>) { 083 return isAssignable(type, (Class<?>) toType); 084 } 085 086 if (toType instanceof ParameterizedType) { 087 return isAssignable(type, (ParameterizedType) toType, typeVarAssigns); 088 } 089 090 if (toType instanceof GenericArrayType) { 091 return isAssignable(type, (GenericArrayType) toType, typeVarAssigns); 092 } 093 094 if (toType instanceof WildcardType) { 095 return isAssignable(type, (WildcardType) toType, typeVarAssigns); 096 } 097 098 // * 099 if (toType instanceof TypeVariable<?>) { 100 return isAssignable(type, (TypeVariable<?>) toType, typeVarAssigns); 101 } 102 // */ 103 104 throw new IllegalStateException("found an unhandled type: " + toType); 105 } 106 107 /** 108 * <p> Checks if the subject type may be implicitly cast to the target class 109 * following the Java generics rules. </p> 110 * 111 * @param type the subject type to be assigned to the target type 112 * @param toClass the target class 113 * @return true if <code>type</code> is assignable to <code>toClass</code>. 114 */ 115 private static boolean isAssignable(Type type, Class<?> toClass) { 116 if (type == null) { 117 // consistency with ClassUtils.isAssignable() behavior 118 return toClass == null || !toClass.isPrimitive(); 119 } 120 121 // only a null type can be assigned to null type which 122 // would have cause the previous to return true 123 if (toClass == null) { 124 return false; 125 } 126 127 // all types are assignable to themselves 128 if (toClass.equals(type)) { 129 return true; 130 } 131 132 if (type instanceof Class<?>) { 133 // just comparing two classes 134 return ClassUtils.isAssignable((Class<?>) type, toClass); 135 } 136 137 if (type instanceof ParameterizedType) { 138 // only have to compare the raw type to the class 139 return isAssignable(getRawType((ParameterizedType) type), toClass); 140 } 141 142 // * 143 if (type instanceof TypeVariable<?>) { 144 // if any of the bounds are assignable to the class, then the 145 // type is assignable to the class. 146 for (Type bound : ((TypeVariable<?>) type).getBounds()) { 147 if (isAssignable(bound, toClass)) { 148 return true; 149 } 150 } 151 152 return false; 153 } 154 155 // the only classes to which a generic array type can be assigned 156 // are class Object and array classes 157 if (type instanceof GenericArrayType) { 158 return toClass.equals(Object.class) 159 || toClass.isArray() 160 && isAssignable(((GenericArrayType) type).getGenericComponentType(), toClass 161 .getComponentType()); 162 } 163 164 // wildcard types are not assignable to a class (though one would think 165 // "? super Object" would be assignable to Object) 166 if (type instanceof WildcardType) { 167 return false; 168 } 169 170 throw new IllegalStateException("found an unhandled type: " + type); 171 } 172 173 /** 174 * <p> Checks if the subject type may be implicitly cast to the target 175 * parameterized type following the Java generics rules. </p> 176 * 177 * @param type the subject type to be assigned to the target type 178 * @param toParameterizedType the target parameterized type 179 * @return true if <code>type</code> is assignable to <code>toType</code>. 180 */ 181 private static boolean isAssignable(Type type, ParameterizedType toParameterizedType, 182 Map<TypeVariable<?>, Type> typeVarAssigns) { 183 if (type == null) { 184 return true; 185 } 186 187 // only a null type can be assigned to null type which 188 // would have cause the previous to return true 189 if (toParameterizedType == null) { 190 return false; 191 } 192 193 // all types are assignable to themselves 194 if (toParameterizedType.equals(type)) { 195 return true; 196 } 197 198 // get the target type's raw type 199 Class<?> toClass = getRawType(toParameterizedType); 200 // get the subject type's type arguments including owner type arguments 201 // and supertype arguments up to and including the target class. 202 Map<TypeVariable<?>, Type> fromTypeVarAssigns = getTypeArguments(type, toClass, null); 203 204 // null means the two types are not compatible 205 if (fromTypeVarAssigns == null) { 206 return false; 207 } 208 209 // compatible types, but there's no type arguments. this is equivalent 210 // to comparing Map< ?, ? > to Map, and raw types are always assignable 211 // to parameterized types. 212 if (fromTypeVarAssigns.isEmpty()) { 213 return true; 214 } 215 216 // get the target type's type arguments including owner type arguments 217 Map<TypeVariable<?>, Type> toTypeVarAssigns = getTypeArguments(toParameterizedType, 218 toClass, typeVarAssigns); 219 220 // now to check each type argument 221 for (Map.Entry<TypeVariable<?>, Type> entry : toTypeVarAssigns.entrySet()) { 222 Type toTypeArg = entry.getValue(); 223 Type fromTypeArg = fromTypeVarAssigns.get(entry.getKey()); 224 225 // parameters must either be absent from the subject type, within 226 // the bounds of the wildcard type, or be an exact match to the 227 // parameters of the target type. 228 if (fromTypeArg != null 229 && !toTypeArg.equals(fromTypeArg) 230 && !(toTypeArg instanceof WildcardType && isAssignable(fromTypeArg, toTypeArg, 231 typeVarAssigns))) { 232 return false; 233 } 234 } 235 236 return true; 237 } 238 239 /** 240 * <p> Checks if the subject type may be implicitly cast to the target 241 * generic array type following the Java generics rules. </p> 242 * 243 * @param type the subject type to be assigned to the target type 244 * @param toGenericArrayType the target generic array type 245 * @return true if <code>type</code> is assignable to 246 * <code>toGenericArrayType</code>. 247 */ 248 private static boolean isAssignable(Type type, GenericArrayType toGenericArrayType, 249 Map<TypeVariable<?>, Type> typeVarAssigns) { 250 if (type == null) { 251 return true; 252 } 253 254 // only a null type can be assigned to null type which 255 // would have cause the previous to return true 256 if (toGenericArrayType == null) { 257 return false; 258 } 259 260 // all types are assignable to themselves 261 if (toGenericArrayType.equals(type)) { 262 return true; 263 } 264 265 Type toComponentType = toGenericArrayType.getGenericComponentType(); 266 267 if (type instanceof Class<?>) { 268 Class<?> cls = (Class<?>) type; 269 270 // compare the component types 271 return cls.isArray() 272 && isAssignable(cls.getComponentType(), toComponentType, typeVarAssigns); 273 } 274 275 if (type instanceof GenericArrayType) { 276 // compare the component types 277 return isAssignable(((GenericArrayType) type).getGenericComponentType(), 278 toComponentType, typeVarAssigns); 279 } 280 281 if (type instanceof WildcardType) { 282 // so long as one of the upper bounds is assignable, it's good 283 for (Type bound : getImplicitUpperBounds((WildcardType) type)) { 284 if (isAssignable(bound, toGenericArrayType)) { 285 return true; 286 } 287 } 288 289 return false; 290 } 291 292 if (type instanceof TypeVariable<?>) { 293 // probably should remove the following logic and just return false. 294 // type variables cannot specify arrays as bounds. 295 for (Type bound : getImplicitBounds((TypeVariable<?>) type)) { 296 if (isAssignable(bound, toGenericArrayType)) { 297 return true; 298 } 299 } 300 301 return false; 302 } 303 304 if (type instanceof ParameterizedType) { 305 // the raw type of a parameterized type is never an array or 306 // generic array, otherwise the declaration would look like this: 307 // Collection[]< ? extends String > collection; 308 return false; 309 } 310 311 throw new IllegalStateException("found an unhandled type: " + type); 312 } 313 314 /** 315 * <p> Checks if the subject type may be implicitly cast to the target 316 * wildcard type following the Java generics rules. </p> 317 * 318 * @param type the subject type to be assigned to the target type 319 * @param toWildcardType the target wildcard type 320 * @return true if <code>type</code> is assignable to 321 * <code>toWildcardType</code>. 322 */ 323 private static boolean isAssignable(Type type, WildcardType toWildcardType, 324 Map<TypeVariable<?>, Type> typeVarAssigns) { 325 if (type == null) { 326 return true; 327 } 328 329 // only a null type can be assigned to null type which 330 // would have cause the previous to return true 331 if (toWildcardType == null) { 332 return false; 333 } 334 335 // all types are assignable to themselves 336 if (toWildcardType.equals(type)) { 337 return true; 338 } 339 340 Type[] toUpperBounds = getImplicitUpperBounds(toWildcardType); 341 Type[] toLowerBounds = getImplicitLowerBounds(toWildcardType); 342 343 if (type instanceof WildcardType) { 344 WildcardType wildcardType = (WildcardType) type; 345 Type[] upperBounds = getImplicitUpperBounds(wildcardType); 346 Type[] lowerBounds = getImplicitLowerBounds(wildcardType); 347 348 for (Type toBound : toUpperBounds) { 349 // if there are assignments for unresolved type variables, 350 // now's the time to substitute them. 351 toBound = substituteTypeVariables(toBound, typeVarAssigns); 352 353 // each upper bound of the subject type has to be assignable to 354 // each 355 // upper bound of the target type 356 for (Type bound : upperBounds) { 357 if (!isAssignable(bound, toBound, typeVarAssigns)) { 358 return false; 359 } 360 } 361 } 362 363 for (Type toBound : toLowerBounds) { 364 // if there are assignments for unresolved type variables, 365 // now's the time to substitute them. 366 toBound = substituteTypeVariables(toBound, typeVarAssigns); 367 368 // each lower bound of the target type has to be assignable to 369 // each 370 // lower bound of the subject type 371 for (Type bound : lowerBounds) { 372 if (!isAssignable(toBound, bound, typeVarAssigns)) { 373 return false; 374 } 375 } 376 } 377 378 return true; 379 } 380 381 for (Type toBound : toUpperBounds) { 382 // if there are assignments for unresolved type variables, 383 // now's the time to substitute them. 384 if (!isAssignable(type, substituteTypeVariables(toBound, typeVarAssigns), 385 typeVarAssigns)) { 386 return false; 387 } 388 } 389 390 for (Type toBound : toLowerBounds) { 391 // if there are assignments for unresolved type variables, 392 // now's the time to substitute them. 393 if (!isAssignable(substituteTypeVariables(toBound, typeVarAssigns), type, 394 typeVarAssigns)) { 395 return false; 396 } 397 } 398 399 return true; 400 } 401 402 /** 403 * <p> Checks if the subject type may be implicitly cast to the target type 404 * variable following the Java generics rules. </p> 405 * 406 * @param type the subject type to be assigned to the target type 407 * @param toTypeVariable the target type variable 408 * @return true if <code>type</code> is assignable to 409 * <code>toTypeVariable</code>. 410 */ 411 private static boolean isAssignable(Type type, TypeVariable<?> toTypeVariable, 412 Map<TypeVariable<?>, Type> typeVarAssigns) { 413 if (type == null) { 414 return true; 415 } 416 417 // only a null type can be assigned to null type which 418 // would have cause the previous to return true 419 if (toTypeVariable == null) { 420 return false; 421 } 422 423 // all types are assignable to themselves 424 if (toTypeVariable.equals(type)) { 425 return true; 426 } 427 428 if (type instanceof TypeVariable<?>) { 429 // a type variable is assignable to another type variable, if 430 // and only if the former is the latter, extends the latter, or 431 // is otherwise a descendant of the latter. 432 Type[] bounds = getImplicitBounds((TypeVariable<?>) type); 433 434 for (Type bound : bounds) { 435 if (isAssignable(bound, toTypeVariable, typeVarAssigns)) { 436 return true; 437 } 438 } 439 } 440 441 if (type instanceof Class<?> || type instanceof ParameterizedType 442 || type instanceof GenericArrayType || type instanceof WildcardType) { 443 return false; 444 } 445 446 throw new IllegalStateException("found an unhandled type: " + type); 447 } 448 449 /** 450 * <p> </p> 451 * 452 * @param type 453 * @param typeVarAssigns 454 * @return 455 */ 456 private static Type substituteTypeVariables(Type type, Map<TypeVariable<?>, Type> typeVarAssigns) { 457 if (type instanceof TypeVariable<?> && typeVarAssigns != null) { 458 Type replacementType = typeVarAssigns.get(type); 459 460 if (replacementType == null) { 461 throw new IllegalArgumentException("missing assignment type for type variable " 462 + type); 463 } 464 465 return replacementType; 466 } 467 468 return type; 469 } 470 471 /** 472 * <p> Retrieves all the type arguments for this parameterized type 473 * including owner hierarchy arguments such as <code> 474 * Outer<K,V>.Inner<T>.DeepInner<E></code> . The arguments are returned in a 475 * {@link Map} specifying the argument type for each {@link TypeVariable}. 476 * </p> 477 * 478 * @param type specifies the subject parameterized type from which to 479 * harvest the parameters. 480 * @return a map of the type arguments to their respective type variables. 481 */ 482 public static Map<TypeVariable<?>, Type> getTypeArguments(ParameterizedType type) { 483 return getTypeArguments(type, getRawType(type), null); 484 } 485 486 /** 487 * <p> Gets the type arguments of a class/interface based on a subtype. For 488 * instance, this method will determine that both of the parameters for the 489 * interface {@link Map} are {@link Object} for the subtype 490 * {@link java.util.Properties Properties} even though the subtype does not 491 * directly implement the <code>Map</code> interface. <p> </p> This method 492 * returns <code>null</code> if <code>type</code> is not assignable to 493 * <code>toClass</code>. It returns an empty map if none of the classes or 494 * interfaces in its inheritance hierarchy specify any type arguments. </p> 495 * <p> A side-effect of this method is that it also retrieves the type 496 * arguments for the classes and interfaces that are part of the hierarchy 497 * between <code>type</code> and <code>toClass</code>. So with the above 498 * example, this method will also determine that the type arguments for 499 * {@link java.util.Hashtable Hashtable} are also both <code>Object</code>. 500 * In cases where the interface specified by <code>toClass</code> is 501 * (indirectly) implemented more than once (e.g. where <code>toClass</code> 502 * specifies the interface {@link java.lang.Iterable Iterable} and 503 * <code>type</code> specifies a parameterized type that implements both 504 * {@link java.util.Set Set} and {@link java.util.Collection Collection}), 505 * this method will look at the inheritance hierarchy of only one of the 506 * implementations/subclasses; the first interface encountered that isn't a 507 * subinterface to one of the others in the <code>type</code> to 508 * <code>toClass</code> hierarchy. </p> 509 * 510 * @param type the type from which to determine the type parameters of 511 * <code>toClass</code> 512 * @param toClass the class whose type parameters are to be determined based 513 * on the subtype <code>type</code> 514 * @return a map of the type assignments for the type variables in each type 515 * in the inheritance hierarchy from <code>type</code> to 516 * <code>toClass</code> inclusive. 517 */ 518 public static Map<TypeVariable<?>, Type> getTypeArguments(Type type, Class<?> toClass) { 519 return getTypeArguments(type, toClass, null); 520 } 521 522 /** 523 * <p> Return a map of the type arguments of <code>type</code> in the context of <code>toClass</code>. </p> 524 * 525 * @param type 526 * @param toClass 527 * @param subtypeVarAssigns 528 * @return 529 */ 530 private static Map<TypeVariable<?>, Type> getTypeArguments(Type type, Class<?> toClass, 531 Map<TypeVariable<?>, Type> subtypeVarAssigns) { 532 if (type instanceof Class<?>) { 533 return getTypeArguments((Class<?>) type, toClass, subtypeVarAssigns); 534 } 535 536 if (type instanceof ParameterizedType) { 537 return getTypeArguments((ParameterizedType) type, toClass, subtypeVarAssigns); 538 } 539 540 if (type instanceof GenericArrayType) { 541 return getTypeArguments(((GenericArrayType) type).getGenericComponentType(), toClass 542 .isArray() ? toClass.getComponentType() : toClass, subtypeVarAssigns); 543 } 544 545 // since wildcard types are not assignable to classes, should this just 546 // return null? 547 if (type instanceof WildcardType) { 548 for (Type bound : getImplicitUpperBounds((WildcardType) type)) { 549 // find the first bound that is assignable to the target class 550 if (isAssignable(bound, toClass)) { 551 return getTypeArguments(bound, toClass, subtypeVarAssigns); 552 } 553 } 554 555 return null; 556 } 557 558 // * 559 if (type instanceof TypeVariable<?>) { 560 for (Type bound : getImplicitBounds((TypeVariable<?>) type)) { 561 // find the first bound that is assignable to the target class 562 if (isAssignable(bound, toClass)) { 563 return getTypeArguments(bound, toClass, subtypeVarAssigns); 564 } 565 } 566 567 return null; 568 } 569 // */ 570 571 throw new IllegalStateException("found an unhandled type: " + type); 572 } 573 574 /** 575 * <p> </p> 576 * 577 * @param parameterizedType 578 * @param toClass 579 * @param subtypeVarAssigns 580 * @return 581 */ 582 private static Map<TypeVariable<?>, Type> getTypeArguments( 583 ParameterizedType parameterizedType, Class<?> toClass, 584 Map<TypeVariable<?>, Type> subtypeVarAssigns) { 585 Class<?> cls = getRawType(parameterizedType); 586 587 // make sure they're assignable 588 if (!isAssignable(cls, toClass)) { 589 return null; 590 } 591 592 Type ownerType = parameterizedType.getOwnerType(); 593 Map<TypeVariable<?>, Type> typeVarAssigns; 594 595 if (ownerType instanceof ParameterizedType) { 596 // get the owner type arguments first 597 ParameterizedType parameterizedOwnerType = (ParameterizedType) ownerType; 598 typeVarAssigns = getTypeArguments(parameterizedOwnerType, 599 getRawType(parameterizedOwnerType), subtypeVarAssigns); 600 } else { 601 // no owner, prep the type variable assignments map 602 typeVarAssigns = subtypeVarAssigns == null ? new HashMap<TypeVariable<?>, Type>() 603 : new HashMap<TypeVariable<?>, Type>(subtypeVarAssigns); 604 } 605 606 // get the subject parameterized type's arguments 607 Type[] typeArgs = parameterizedType.getActualTypeArguments(); 608 // and get the corresponding type variables from the raw class 609 TypeVariable<?>[] typeParams = cls.getTypeParameters(); 610 611 // map the arguments to their respective type variables 612 for (int i = 0; i < typeParams.length; i++) { 613 Type typeArg = typeArgs[i]; 614 typeVarAssigns.put(typeParams[i], typeVarAssigns.containsKey(typeArg) ? typeVarAssigns 615 .get(typeArg) : typeArg); 616 } 617 618 if (toClass.equals(cls)) { 619 // target class has been reached. Done. 620 return typeVarAssigns; 621 } 622 623 // walk the inheritance hierarchy until the target class is reached 624 return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns); 625 } 626 627 /** 628 * <p> </p> 629 * 630 * @param cls 631 * @param toClass 632 * @param subtypeVarAssigns 633 * @return 634 */ 635 private static Map<TypeVariable<?>, Type> getTypeArguments(Class<?> cls, Class<?> toClass, 636 Map<TypeVariable<?>, Type> subtypeVarAssigns) { 637 // make sure they're assignable 638 if (!isAssignable(cls, toClass)) { 639 return null; 640 } 641 642 // can't work with primitives 643 if (cls.isPrimitive()) { 644 // both classes are primitives? 645 if (toClass.isPrimitive()) { 646 // dealing with widening here. No type arguments to be 647 // harvested with these two types. 648 return new HashMap<TypeVariable<?>, Type>(); 649 } 650 651 // work with wrapper the wrapper class instead of the primitive 652 cls = ClassUtils.primitiveToWrapper(cls); 653 } 654 655 // create a copy of the incoming map, or an empty one if it's null 656 HashMap<TypeVariable<?>, Type> typeVarAssigns = subtypeVarAssigns == null ? new HashMap<TypeVariable<?>, Type>() 657 : new HashMap<TypeVariable<?>, Type>(subtypeVarAssigns); 658 659 // no arguments for the parameters, or target class has been reached 660 if (cls.getTypeParameters().length > 0 || toClass.equals(cls)) { 661 return typeVarAssigns; 662 } 663 664 // walk the inheritance hierarchy until the target class is reached 665 return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns); 666 } 667 668 /** 669 * <p> Tries to determine the type arguments of a class/interface based on a 670 * super parameterized type's type arguments. This method is the inverse of 671 * {@link #getTypeArguments(Type, Class)} which gets a class/interface's 672 * type arguments based on a subtype. It is far more limited in determining 673 * the type arguments for the subject class's type variables in that it can 674 * only determine those parameters that map from the subject {@link Class} 675 * object to the supertype. </p> <p> Example: {@link java.util.TreeSet 676 * TreeSet} sets its parameter as the parameter for 677 * {@link java.util.NavigableSet NavigableSet}, which in turn sets the 678 * parameter of {@link java.util.SortedSet}, which in turn sets the 679 * parameter of {@link Set}, which in turn sets the parameter of 680 * {@link java.util.Collection}, which in turn sets the parameter of 681 * {@link java.lang.Iterable}. Since <code>TreeSet</code>'s parameter maps 682 * (indirectly) to <code>Iterable</code>'s parameter, it will be able to 683 * determine that based on the super type <code>Iterable<? extends 684 * Map<Integer,? extends Collection<?>>></code>, the parameter of 685 * <code>TreeSet</code> is <code>? extends Map<Integer,? extends 686 * Collection<?>></code>. </p> 687 * 688 * @param cls the class whose type parameters are to be determined 689 * @param superType the super type from which <code>cls</code>'s type 690 * arguments are to be determined 691 * @return a map of the type assignments that could be determined for the 692 * type variables in each type in the inheritance hierarchy from 693 * <code>type</code> to <code>toClass</code> inclusive. 694 */ 695 public static Map<TypeVariable<?>, Type> determineTypeArguments(Class<?> cls, 696 ParameterizedType superType) { 697 Class<?> superClass = getRawType(superType); 698 699 // compatibility check 700 if (!isAssignable(cls, superClass)) { 701 return null; 702 } 703 704 if (cls.equals(superClass)) { 705 return getTypeArguments(superType, superClass, null); 706 } 707 708 // get the next class in the inheritance hierarchy 709 Type midType = getClosestParentType(cls, superClass); 710 711 // can only be a class or a parameterized type 712 if (midType instanceof Class<?>) { 713 return determineTypeArguments((Class<?>) midType, superType); 714 } 715 716 ParameterizedType midParameterizedType = (ParameterizedType) midType; 717 Class<?> midClass = getRawType(midParameterizedType); 718 // get the type variables of the mid class that map to the type 719 // arguments of the super class 720 Map<TypeVariable<?>, Type> typeVarAssigns = determineTypeArguments(midClass, superType); 721 // map the arguments of the mid type to the class type variables 722 mapTypeVariablesToArguments(cls, midParameterizedType, typeVarAssigns); 723 724 return typeVarAssigns; 725 } 726 727 /** 728 * <p> </p> 729 * 730 * @param cls 731 * @param parameterizedType 732 * @param typeVarAssigns 733 */ 734 private static <T> void mapTypeVariablesToArguments(Class<T> cls, 735 ParameterizedType parameterizedType, Map<TypeVariable<?>, Type> typeVarAssigns) { 736 // capture the type variables from the owner type that have assignments 737 Type ownerType = parameterizedType.getOwnerType(); 738 739 if (ownerType instanceof ParameterizedType) { 740 // recursion to make sure the owner's owner type gets processed 741 mapTypeVariablesToArguments(cls, (ParameterizedType) ownerType, typeVarAssigns); 742 } 743 744 // parameterizedType is a generic interface/class (or it's in the owner 745 // hierarchy of said interface/class) implemented/extended by the class 746 // cls. Find out which type variables of cls are type arguments of 747 // parameterizedType: 748 Type[] typeArgs = parameterizedType.getActualTypeArguments(); 749 750 // of the cls's type variables that are arguments of parameterizedType, 751 // find out which ones can be determined from the super type's arguments 752 TypeVariable<?>[] typeVars = getRawType(parameterizedType).getTypeParameters(); 753 754 // use List view of type parameters of cls so the contains() method can be used: 755 List<TypeVariable<Class<T>>> typeVarList = Arrays.asList(cls 756 .getTypeParameters()); 757 758 for (int i = 0; i < typeArgs.length; i++) { 759 TypeVariable<?> typeVar = typeVars[i]; 760 Type typeArg = typeArgs[i]; 761 762 // argument of parameterizedType is a type variable of cls 763 if (typeVarList.contains(typeArg) 764 // type variable of parameterizedType has an assignment in 765 // the super type. 766 && typeVarAssigns.containsKey(typeVar)) { 767 // map the assignment to the cls's type variable 768 typeVarAssigns.put((TypeVariable<?>) typeArg, typeVarAssigns.get(typeVar)); 769 } 770 } 771 } 772 773 /** 774 * <p> Closest parent type? Closest to what? The closest parent type to the 775 * super class specified by <code>superClass</code>. </p> 776 * 777 * @param cls 778 * @param superClass 779 * @return 780 */ 781 private static Type getClosestParentType(Class<?> cls, Class<?> superClass) { 782 // only look at the interfaces if the super class is also an interface 783 if (superClass.isInterface()) { 784 // get the generic interfaces of the subject class 785 Type[] interfaceTypes = cls.getGenericInterfaces(); 786 // will hold the best generic interface match found 787 Type genericInterface = null; 788 789 // find the interface closest to the super class 790 for (int i = 0; i < interfaceTypes.length; i++) { 791 Type midType = interfaceTypes[i]; 792 Class<?> midClass = null; 793 794 if (midType instanceof ParameterizedType) { 795 midClass = getRawType((ParameterizedType) midType); 796 } else if (midType instanceof Class<?>) { 797 midClass = (Class<?>) midType; 798 } else { 799 throw new IllegalStateException("Unexpected generic" 800 + " interface type found: " + midType); 801 } 802 803 // check if this interface is further up the inheritance chain 804 // than the previously found match 805 if (isAssignable(midClass, superClass) 806 && isAssignable(genericInterface, (Type) midClass)) { 807 genericInterface = midType; 808 } 809 } 810 811 // found a match? 812 if (genericInterface != null) { 813 return genericInterface; 814 } 815 } 816 817 // none of the interfaces were descendants of the target class, so the 818 // super class has to be one, instead 819 return cls.getGenericSuperclass(); 820 } 821 822 /** 823 * <p> Checks if the given value can be assigned to the target type 824 * following the Java generics rules. </p> 825 * 826 * @param value 827 * @param type 828 * @return true of <code>value</code> is an instance of <code>type</code>. 829 */ 830 public static boolean isInstance(Object value, Type type) { 831 if (type == null) { 832 return false; 833 } 834 835 return value == null ? !(type instanceof Class<?>) || !((Class<?>) type).isPrimitive() 836 : isAssignable(value.getClass(), type, null); 837 } 838 839 /** 840 * <p> This method strips out the redundant upper bound types in type 841 * variable types and wildcard types (or it would with wildcard types if 842 * multiple upper bounds were allowed). </p> <p> Example: with the variable 843 * type declaration: 844 * 845 * <pre> <K extends java.util.Collection<String> & 846 * java.util.List<String>> </pre> 847 * 848 * since <code>List</code> is a subinterface of <code>Collection</code>, 849 * this method will return the bounds as if the declaration had been: 850 * 851 * <pre> <K extends java.util.List<String>> </pre> 852 * 853 * </p> 854 * 855 * @param bounds an array of types representing the upper bounds of either 856 * <code>WildcardType</code> or <code>TypeVariable</code>. 857 * @return an array containing the values from <code>bounds</code> minus the 858 * redundant types. 859 */ 860 public static Type[] normalizeUpperBounds(Type[] bounds) { 861 // don't bother if there's only one (or none) type 862 if (bounds.length < 2) { 863 return bounds; 864 } 865 866 Set<Type> types = new HashSet<Type>(bounds.length); 867 868 for (Type type1 : bounds) { 869 boolean subtypeFound = false; 870 871 for (Type type2 : bounds) { 872 if (type1 != type2 && isAssignable(type2, type1, null)) { 873 subtypeFound = true; 874 break; 875 } 876 } 877 878 if (!subtypeFound) { 879 types.add(type1); 880 } 881 } 882 883 return types.toArray(new Type[0]); 884 } 885 886 /** 887 * <p> Returns an array containing the sole type of {@link Object} if 888 * {@link TypeVariable#getBounds()} returns an empty array. Otherwise, it 889 * returns the result of <code>TypeVariable.getBounds()</code> passed into 890 * {@link #normalizeUpperBounds}. </p> 891 * 892 * @param typeVariable the subject type variable 893 * @return a non-empty array containing the bounds of the type variable. 894 */ 895 public static Type[] getImplicitBounds(TypeVariable<?> typeVariable) { 896 Type[] bounds = typeVariable.getBounds(); 897 898 return bounds.length == 0 ? new Type[] { Object.class } : normalizeUpperBounds(bounds); 899 } 900 901 /** 902 * <p> Returns an array containing the sole value of {@link Object} if 903 * {@link WildcardType#getUpperBounds()} returns an empty array. Otherwise, 904 * it returns the result of <code>WildcardType.getUpperBounds()</code> 905 * passed into {@link #normalizeUpperBounds}. </p> 906 * 907 * @param wildcardType the subject wildcard type 908 * @return a non-empty array containing the upper bounds of the wildcard 909 * type. 910 */ 911 public static Type[] getImplicitUpperBounds(WildcardType wildcardType) { 912 Type[] bounds = wildcardType.getUpperBounds(); 913 914 return bounds.length == 0 ? new Type[] { Object.class } : normalizeUpperBounds(bounds); 915 } 916 917 /** 918 * <p> Returns an array containing a single value of <code>null</code> if 919 * {@link WildcardType#getLowerBounds()} returns an empty array. Otherwise, 920 * it returns the result of <code>WildcardType.getLowerBounds()</code>. </p> 921 * 922 * @param wildcardType the subject wildcard type 923 * @return a non-empty array containing the lower bounds of the wildcard 924 * type. 925 */ 926 public static Type[] getImplicitLowerBounds(WildcardType wildcardType) { 927 Type[] bounds = wildcardType.getLowerBounds(); 928 929 return bounds.length == 0 ? new Type[] { null } : bounds; 930 } 931 932 /** 933 * <p> Determines whether or not specified types satisfy the bounds of their 934 * mapped type variables. When a type parameter extends another (such as 935 * <code><T, S extends T></code>), uses another as a type parameter (such as 936 * <code><T, S extends Comparable<T></code>), or otherwise depends on 937 * another type variable to be specified, the dependencies must be included 938 * in <code>typeVarAssigns</code>. </p> 939 * 940 * @param typeVarAssigns specifies the potential types to be assigned to the 941 * type variables. 942 * @return whether or not the types can be assigned to their respective type 943 * variables. 944 */ 945 public static boolean typesSatisfyVariables(Map<TypeVariable<?>, Type> typeVarAssigns) { 946 // all types must be assignable to all the bounds of the their mapped 947 // type variable. 948 for (Map.Entry<TypeVariable<?>, Type> entry : typeVarAssigns.entrySet()) { 949 TypeVariable<?> typeVar = entry.getKey(); 950 Type type = entry.getValue(); 951 952 for (Type bound : getImplicitBounds(typeVar)) { 953 if (!isAssignable(type, substituteTypeVariables(bound, typeVarAssigns), 954 typeVarAssigns)) { 955 return false; 956 } 957 } 958 } 959 960 return true; 961 } 962 963 /** 964 * <p> Type-checking method of convenience. </p> 965 * 966 * @param parameterizedType 967 * @return 968 */ 969 private static Class<?> getRawType(ParameterizedType parameterizedType) { 970 Type rawType = parameterizedType.getRawType(); 971 972 // check if raw type is a Class object 973 // not currently necessary, but since the return type is Type instead of 974 // Class, there's enough reason to believe that future versions of Java 975 // may return other Type implementations. And type-safety checking is 976 // rarely a bad idea. 977 if (!(rawType instanceof Class<?>)) { 978 throw new IllegalStateException("Wait... What!? Type of rawType: " + rawType); 979 } 980 981 return (Class<?>) rawType; 982 } 983 984 /** 985 * <p> Get the raw type of a Java type, given its context. Primarily for use 986 * with {@link TypeVariable}s and {@link GenericArrayType}s, or when you do 987 * not know the runtime type of <code>type</code>: if you know you have a 988 * {@link Class} instance, it is already raw; if you know you have a 989 * {@link ParameterizedType}, its raw type is only a method call away. </p> 990 * 991 * @param type to resolve 992 * @param assigningType type to be resolved against 993 * @return the resolved <code>Class</code> object or <code>null</code> if 994 * the type could not be resolved 995 */ 996 public static Class<?> getRawType(Type type, Type assigningType) { 997 if (type instanceof Class<?>) { 998 // it is raw, no problem 999 return (Class<?>) type; 1000 } 1001 1002 if (type instanceof ParameterizedType) { 1003 // simple enough to get the raw type of a ParameterizedType 1004 return getRawType((ParameterizedType) type); 1005 } 1006 1007 if (type instanceof TypeVariable<?>) { 1008 if (assigningType == null) { 1009 return null; 1010 } 1011 1012 // get the entity declaring this type variable 1013 Object genericDeclaration = ((TypeVariable<?>) type).getGenericDeclaration(); 1014 1015 // can't get the raw type of a method- or constructor-declared type 1016 // variable 1017 if (!(genericDeclaration instanceof Class<?>)) { 1018 return null; 1019 } 1020 1021 // get the type arguments for the declaring class/interface based 1022 // on the enclosing type 1023 Map<TypeVariable<?>, Type> typeVarAssigns = getTypeArguments(assigningType, 1024 (Class<?>) genericDeclaration); 1025 1026 // enclosingType has to be a subclass (or subinterface) of the 1027 // declaring type 1028 if (typeVarAssigns == null) { 1029 return null; 1030 } 1031 1032 // get the argument assigned to this type variable 1033 Type typeArgument = typeVarAssigns.get(type); 1034 1035 if (typeArgument == null) { 1036 return null; 1037 } 1038 1039 // get the argument for this type variable 1040 return getRawType(typeArgument, assigningType); 1041 } 1042 1043 if (type instanceof GenericArrayType) { 1044 // get raw component type 1045 Class<?> rawComponentType = getRawType(((GenericArrayType) type) 1046 .getGenericComponentType(), assigningType); 1047 1048 // create array type from raw component type and return its class 1049 return Array.newInstance(rawComponentType, 0).getClass(); 1050 } 1051 1052 // (hand-waving) this is not the method you're looking for 1053 if (type instanceof WildcardType) { 1054 return null; 1055 } 1056 1057 throw new IllegalArgumentException("unknown type: " + type); 1058 } 1059 1060 }