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