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