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