001/* 002 * Copyright (C) 2012 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.reflect; 016 017import static com.google.common.base.Preconditions.checkNotNull; 018 019import com.google.common.collect.ImmutableList; 020import com.google.errorprone.annotations.CanIgnoreReturnValue; 021import java.lang.annotation.Annotation; 022import java.lang.reflect.AccessibleObject; 023import java.lang.reflect.AnnotatedElement; 024import java.lang.reflect.AnnotatedType; 025import java.lang.reflect.Constructor; 026import java.lang.reflect.InvocationTargetException; 027import java.lang.reflect.Member; 028import java.lang.reflect.Method; 029import java.lang.reflect.Modifier; 030import java.lang.reflect.Type; 031import java.lang.reflect.TypeVariable; 032import java.util.Arrays; 033import javax.annotation.CheckForNull; 034import org.checkerframework.checker.nullness.qual.Nullable; 035 036/** 037 * Wrapper around either a {@link Method} or a {@link Constructor}. Convenience API is provided to 038 * make common reflective operation easier to deal with, such as {@link #isPublic}, {@link 039 * #getParameters} etc. 040 * 041 * <p>In addition to convenience methods, {@link TypeToken#method} and {@link TypeToken#constructor} 042 * will resolve the type parameters of the method or constructor in the context of the owner type, 043 * which may be a subtype of the declaring class. For example: 044 * 045 * <pre>{@code 046 * Method getMethod = List.class.getMethod("get", int.class); 047 * Invokable<List<String>, ?> invokable = new TypeToken<List<String>>() {}.method(getMethod); 048 * assertEquals(TypeToken.of(String.class), invokable.getReturnType()); // Not Object.class! 049 * assertEquals(new TypeToken<List<String>>() {}, invokable.getOwnerType()); 050 * }</pre> 051 * 052 * <p><b>Note:</b> earlier versions of this class inherited from {@link 053 * java.lang.reflect.AccessibleObject AccessibleObject} and {@link 054 * java.lang.reflect.GenericDeclaration GenericDeclaration}. Since version 31.0 that is no longer 055 * the case. However, most methods from those types are present with the same signature in this 056 * class. 057 * 058 * @param <T> the type that owns this method or constructor. 059 * @param <R> the return type of (or supertype thereof) the method or the declaring type of the 060 * constructor. 061 * @author Ben Yu 062 * @since 14.0 (no longer implements {@link AccessibleObject} or {@code GenericDeclaration} since 063 * 31.0) 064 */ 065public abstract class Invokable<T, R> implements AnnotatedElement, Member { 066 private final AccessibleObject accessibleObject; 067 private final Member member; 068 069 <M extends AccessibleObject & Member> Invokable(M member) { 070 checkNotNull(member); 071 this.accessibleObject = member; 072 this.member = member; 073 } 074 075 /** Returns {@link Invokable} of {@code method}. */ 076 public static Invokable<?, Object> from(Method method) { 077 return new MethodInvokable<>(method); 078 } 079 080 /** Returns {@link Invokable} of {@code constructor}. */ 081 public static <T> Invokable<T, T> from(Constructor<T> constructor) { 082 return new ConstructorInvokable<T>(constructor); 083 } 084 085 @Override 086 public final boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { 087 return accessibleObject.isAnnotationPresent(annotationClass); 088 } 089 090 @Override 091 @CheckForNull 092 public final <A extends Annotation> A getAnnotation(Class<A> annotationClass) { 093 return accessibleObject.getAnnotation(annotationClass); 094 } 095 096 @Override 097 public final Annotation[] getAnnotations() { 098 return accessibleObject.getAnnotations(); 099 } 100 101 @Override 102 public final Annotation[] getDeclaredAnnotations() { 103 return accessibleObject.getDeclaredAnnotations(); 104 } 105 106 // We ought to be able to implement GenericDeclaration instead its parent AnnotatedElement. 107 // That would give us this method declaration. But for some reason, implementing 108 // GenericDeclaration leads to weird errors in Android tests: 109 // IncompatibleClassChangeError: interface not implemented 110 /** See {@link java.lang.reflect.GenericDeclaration#getTypeParameters()}. */ 111 public abstract TypeVariable<?>[] getTypeParameters(); 112 113 /** See {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)}. */ 114 public final void setAccessible(boolean flag) { 115 accessibleObject.setAccessible(flag); 116 } 117 118 /** See {@link java.lang.reflect.AccessibleObject#trySetAccessible()}. */ 119 @SuppressWarnings("CatchingUnchecked") // sneaky checked exception 120 public final boolean trySetAccessible() { 121 // We can't call accessibleObject.trySetAccessible since that was added in Java 9 and this code 122 // should work on Java 8. So we emulate it this way. 123 try { 124 accessibleObject.setAccessible(true); 125 return true; 126 } catch (Exception e) { // sneaky checked exception 127 return false; 128 } 129 } 130 131 /** See {@link java.lang.reflect.AccessibleObject#isAccessible()}. */ 132 public final boolean isAccessible() { 133 return accessibleObject.isAccessible(); 134 } 135 136 @Override 137 public final String getName() { 138 return member.getName(); 139 } 140 141 @Override 142 public final int getModifiers() { 143 return member.getModifiers(); 144 } 145 146 @Override 147 public final boolean isSynthetic() { 148 return member.isSynthetic(); 149 } 150 151 /** Returns true if the element is public. */ 152 public final boolean isPublic() { 153 return Modifier.isPublic(getModifiers()); 154 } 155 156 /** Returns true if the element is protected. */ 157 public final boolean isProtected() { 158 return Modifier.isProtected(getModifiers()); 159 } 160 161 /** Returns true if the element is package-private. */ 162 public final boolean isPackagePrivate() { 163 return !isPrivate() && !isPublic() && !isProtected(); 164 } 165 166 /** Returns true if the element is private. */ 167 public final boolean isPrivate() { 168 return Modifier.isPrivate(getModifiers()); 169 } 170 171 /** Returns true if the element is static. */ 172 public final boolean isStatic() { 173 return Modifier.isStatic(getModifiers()); 174 } 175 176 /** 177 * Returns {@code true} if this method is final, per {@code Modifier.isFinal(getModifiers())}. 178 * 179 * <p>Note that a method may still be effectively "final", or non-overridable when it has no 180 * {@code final} keyword. For example, it could be private, or it could be declared by a final 181 * class. To tell whether a method is overridable, use {@link Invokable#isOverridable}. 182 */ 183 public final boolean isFinal() { 184 return Modifier.isFinal(getModifiers()); 185 } 186 187 /** Returns true if the method is abstract. */ 188 public final boolean isAbstract() { 189 return Modifier.isAbstract(getModifiers()); 190 } 191 192 /** Returns true if the element is native. */ 193 public final boolean isNative() { 194 return Modifier.isNative(getModifiers()); 195 } 196 197 /** Returns true if the method is synchronized. */ 198 public final boolean isSynchronized() { 199 return Modifier.isSynchronized(getModifiers()); 200 } 201 202 /** Returns true if the field is volatile. */ 203 final boolean isVolatile() { 204 return Modifier.isVolatile(getModifiers()); 205 } 206 207 /** Returns true if the field is transient. */ 208 final boolean isTransient() { 209 return Modifier.isTransient(getModifiers()); 210 } 211 212 @Override 213 public boolean equals(@CheckForNull Object obj) { 214 if (obj instanceof Invokable) { 215 Invokable<?, ?> that = (Invokable<?, ?>) obj; 216 return getOwnerType().equals(that.getOwnerType()) && member.equals(that.member); 217 } 218 return false; 219 } 220 221 @Override 222 public int hashCode() { 223 return member.hashCode(); 224 } 225 226 @Override 227 public String toString() { 228 return member.toString(); 229 } 230 231 /** 232 * Returns {@code true} if this is an overridable method. Constructors, private, static or final 233 * methods, or methods declared by final classes are not overridable. 234 */ 235 public abstract boolean isOverridable(); 236 237 /** Returns {@code true} if this was declared to take a variable number of arguments. */ 238 public abstract boolean isVarArgs(); 239 240 /** 241 * Invokes with {@code receiver} as 'this' and {@code args} passed to the underlying method and 242 * returns the return value; or calls the underlying constructor with {@code args} and returns the 243 * constructed instance. 244 * 245 * @throws IllegalAccessException if this {@code Constructor} object enforces Java language access 246 * control and the underlying method or constructor is inaccessible. 247 * @throws IllegalArgumentException if the number of actual and formal parameters differ; if an 248 * unwrapping conversion for primitive arguments fails; or if, after possible unwrapping, a 249 * parameter value cannot be converted to the corresponding formal parameter type by a method 250 * invocation conversion. 251 * @throws InvocationTargetException if the underlying method or constructor throws an exception. 252 */ 253 // All subclasses are owned by us and we'll make sure to get the R type right, including nullness. 254 @SuppressWarnings({"unchecked", "nullness"}) 255 @CanIgnoreReturnValue 256 @CheckForNull 257 public final R invoke(@CheckForNull T receiver, @Nullable Object... args) 258 throws InvocationTargetException, IllegalAccessException { 259 return (R) invokeInternal(receiver, checkNotNull(args)); 260 } 261 262 /** Returns the return type of this {@code Invokable}. */ 263 // All subclasses are owned by us and we'll make sure to get the R type right. 264 @SuppressWarnings("unchecked") 265 public final TypeToken<? extends R> getReturnType() { 266 return (TypeToken<? extends R>) TypeToken.of(getGenericReturnType()); 267 } 268 269 /** 270 * Returns all declared parameters of this {@code Invokable}. Note that if this is a constructor 271 * of a non-static inner class, unlike {@link Constructor#getParameterTypes}, the hidden {@code 272 * this} parameter of the enclosing class is excluded from the returned parameters. 273 */ 274 @IgnoreJRERequirement 275 public final ImmutableList<Parameter> getParameters() { 276 Type[] parameterTypes = getGenericParameterTypes(); 277 Annotation[][] annotations = getParameterAnnotations(); 278 @Nullable Object[] annotatedTypes = 279 ANNOTATED_TYPE_EXISTS ? getAnnotatedParameterTypes() : new Object[parameterTypes.length]; 280 ImmutableList.Builder<Parameter> builder = ImmutableList.builder(); 281 for (int i = 0; i < parameterTypes.length; i++) { 282 builder.add( 283 new Parameter( 284 this, i, TypeToken.of(parameterTypes[i]), annotations[i], annotatedTypes[i])); 285 } 286 return builder.build(); 287 } 288 289 /** Returns all declared exception types of this {@code Invokable}. */ 290 public final ImmutableList<TypeToken<? extends Throwable>> getExceptionTypes() { 291 ImmutableList.Builder<TypeToken<? extends Throwable>> builder = ImmutableList.builder(); 292 for (Type type : getGenericExceptionTypes()) { 293 // getGenericExceptionTypes() will never return a type that's not exception 294 @SuppressWarnings("unchecked") 295 TypeToken<? extends Throwable> exceptionType = 296 (TypeToken<? extends Throwable>) TypeToken.of(type); 297 builder.add(exceptionType); 298 } 299 return builder.build(); 300 } 301 302 /** 303 * Explicitly specifies the return type of this {@code Invokable}. For example: 304 * 305 * <pre>{@code 306 * Method factoryMethod = Person.class.getMethod("create"); 307 * Invokable<?, Person> factory = Invokable.of(getNameMethod).returning(Person.class); 308 * }</pre> 309 */ 310 public final <R1 extends R> Invokable<T, R1> returning(Class<R1> returnType) { 311 return returning(TypeToken.of(returnType)); 312 } 313 314 /** Explicitly specifies the return type of this {@code Invokable}. */ 315 public final <R1 extends R> Invokable<T, R1> returning(TypeToken<R1> returnType) { 316 if (!returnType.isSupertypeOf(getReturnType())) { 317 throw new IllegalArgumentException( 318 "Invokable is known to return " + getReturnType() + ", not " + returnType); 319 } 320 @SuppressWarnings("unchecked") // guarded by previous check 321 Invokable<T, R1> specialized = (Invokable<T, R1>) this; 322 return specialized; 323 } 324 325 @SuppressWarnings("unchecked") // The declaring class is T's raw class, or one of its supertypes. 326 @Override 327 public final Class<? super T> getDeclaringClass() { 328 return (Class<? super T>) member.getDeclaringClass(); 329 } 330 331 /** Returns the type of {@code T}. */ 332 // Overridden in TypeToken#method() and TypeToken#constructor() 333 @SuppressWarnings("unchecked") // The declaring class is T. 334 public TypeToken<T> getOwnerType() { 335 return (TypeToken<T>) TypeToken.of(getDeclaringClass()); 336 } 337 338 @CheckForNull 339 abstract Object invokeInternal(@CheckForNull Object receiver, @Nullable Object[] args) 340 throws InvocationTargetException, IllegalAccessException; 341 342 abstract Type[] getGenericParameterTypes(); 343 344 @SuppressWarnings("Java7ApiChecker") 345 abstract AnnotatedType[] getAnnotatedParameterTypes(); 346 347 /** This should never return a type that's not a subtype of Throwable. */ 348 abstract Type[] getGenericExceptionTypes(); 349 350 abstract Annotation[][] getParameterAnnotations(); 351 352 abstract Type getGenericReturnType(); 353 354 /** 355 * Returns the {@link AnnotatedType} for the return type. 356 * 357 * @since 14.0 358 */ 359 @SuppressWarnings("Java7ApiChecker") 360 public abstract AnnotatedType getAnnotatedReturnType(); 361 362 static class MethodInvokable<T> extends Invokable<T, Object> { 363 364 final Method method; 365 366 MethodInvokable(Method method) { 367 super(method); 368 this.method = method; 369 } 370 371 @Override 372 @CheckForNull 373 final Object invokeInternal(@CheckForNull Object receiver, @Nullable Object[] args) 374 throws InvocationTargetException, IllegalAccessException { 375 return method.invoke(receiver, args); 376 } 377 378 @Override 379 Type getGenericReturnType() { 380 return method.getGenericReturnType(); 381 } 382 383 @Override 384 Type[] getGenericParameterTypes() { 385 return method.getGenericParameterTypes(); 386 } 387 388 @Override 389 @SuppressWarnings("Java7ApiChecker") 390 AnnotatedType[] getAnnotatedParameterTypes() { 391 return method.getAnnotatedParameterTypes(); 392 } 393 394 @Override 395 @SuppressWarnings("Java7ApiChecker") 396 public AnnotatedType getAnnotatedReturnType() { 397 return method.getAnnotatedReturnType(); 398 } 399 400 @Override 401 Type[] getGenericExceptionTypes() { 402 return method.getGenericExceptionTypes(); 403 } 404 405 @Override 406 final Annotation[][] getParameterAnnotations() { 407 return method.getParameterAnnotations(); 408 } 409 410 @Override 411 public final TypeVariable<?>[] getTypeParameters() { 412 return method.getTypeParameters(); 413 } 414 415 @Override 416 public final boolean isOverridable() { 417 return !(isFinal() 418 || isPrivate() 419 || isStatic() 420 || Modifier.isFinal(getDeclaringClass().getModifiers())); 421 } 422 423 @Override 424 public final boolean isVarArgs() { 425 return method.isVarArgs(); 426 } 427 } 428 429 static class ConstructorInvokable<T> extends Invokable<T, T> { 430 431 final Constructor<?> constructor; 432 433 ConstructorInvokable(Constructor<?> constructor) { 434 super(constructor); 435 this.constructor = constructor; 436 } 437 438 @Override 439 final Object invokeInternal(@CheckForNull Object receiver, @Nullable Object[] args) 440 throws InvocationTargetException, IllegalAccessException { 441 try { 442 return constructor.newInstance(args); 443 } catch (InstantiationException e) { 444 throw new RuntimeException(constructor + " failed.", e); 445 } 446 } 447 448 /** 449 * If the class is parameterized, such as {@link java.util.ArrayList ArrayList}, this returns 450 * {@code ArrayList<E>}. 451 */ 452 @Override 453 Type getGenericReturnType() { 454 Class<?> declaringClass = getDeclaringClass(); 455 TypeVariable<?>[] typeParams = declaringClass.getTypeParameters(); 456 if (typeParams.length > 0) { 457 return Types.newParameterizedType(declaringClass, typeParams); 458 } else { 459 return declaringClass; 460 } 461 } 462 463 @Override 464 Type[] getGenericParameterTypes() { 465 Type[] types = constructor.getGenericParameterTypes(); 466 if (types.length > 0 && mayNeedHiddenThis()) { 467 Class<?>[] rawParamTypes = constructor.getParameterTypes(); 468 if (types.length == rawParamTypes.length 469 && rawParamTypes[0] == getDeclaringClass().getEnclosingClass()) { 470 // first parameter is the hidden 'this' 471 return Arrays.copyOfRange(types, 1, types.length); 472 } 473 } 474 return types; 475 } 476 477 @Override 478 @SuppressWarnings("Java7ApiChecker") 479 AnnotatedType[] getAnnotatedParameterTypes() { 480 return constructor.getAnnotatedParameterTypes(); 481 } 482 483 @Override 484 @SuppressWarnings("Java7ApiChecker") 485 public AnnotatedType getAnnotatedReturnType() { 486 return constructor.getAnnotatedReturnType(); 487 } 488 489 @Override 490 Type[] getGenericExceptionTypes() { 491 return constructor.getGenericExceptionTypes(); 492 } 493 494 @Override 495 final Annotation[][] getParameterAnnotations() { 496 return constructor.getParameterAnnotations(); 497 } 498 499 /** 500 * {@inheritDoc} 501 * 502 * <p>{@code [<E>]} will be returned for ArrayList's constructor. When both the class and the 503 * constructor have type parameters, the class parameters are prepended before those of the 504 * constructor's. This is an arbitrary rule since no existing language spec mandates one way or 505 * the other. From the declaration syntax, the class type parameter appears first, but the call 506 * syntax may show up in opposite order such as {@code new <A>Foo<B>()}. 507 */ 508 @Override 509 public final TypeVariable<?>[] getTypeParameters() { 510 TypeVariable<?>[] declaredByClass = getDeclaringClass().getTypeParameters(); 511 TypeVariable<?>[] declaredByConstructor = constructor.getTypeParameters(); 512 TypeVariable<?>[] result = 513 new TypeVariable<?>[declaredByClass.length + declaredByConstructor.length]; 514 System.arraycopy(declaredByClass, 0, result, 0, declaredByClass.length); 515 System.arraycopy( 516 declaredByConstructor, 0, result, declaredByClass.length, declaredByConstructor.length); 517 return result; 518 } 519 520 @Override 521 public final boolean isOverridable() { 522 return false; 523 } 524 525 @Override 526 public final boolean isVarArgs() { 527 return constructor.isVarArgs(); 528 } 529 530 private boolean mayNeedHiddenThis() { 531 Class<?> declaringClass = constructor.getDeclaringClass(); 532 if (declaringClass.getEnclosingConstructor() != null) { 533 // Enclosed in a constructor, needs hidden this 534 return true; 535 } 536 Method enclosingMethod = declaringClass.getEnclosingMethod(); 537 if (enclosingMethod != null) { 538 // Enclosed in a method, if it's not static, must need hidden this. 539 return !Modifier.isStatic(enclosingMethod.getModifiers()); 540 } else { 541 // Strictly, this doesn't necessarily indicate a hidden 'this' in the case of 542 // static initializer. But there seems no way to tell in that case. :( 543 // This may cause issues when an anonymous class is created inside a static initializer, 544 // and the class's constructor's first parameter happens to be the enclosing class. 545 // In such case, we may mistakenly think that the class is within a non-static context 546 // and the first parameter is the hidden 'this'. 547 return declaringClass.getEnclosingClass() != null 548 && !Modifier.isStatic(declaringClass.getModifiers()); 549 } 550 } 551 } 552 553 private static final boolean ANNOTATED_TYPE_EXISTS = initAnnotatedTypeExists(); 554 555 private static boolean initAnnotatedTypeExists() { 556 try { 557 Class.forName("java.lang.reflect.AnnotatedType"); 558 } catch (ClassNotFoundException e) { 559 return false; 560 } 561 return true; 562 } 563}