17dd252788645e940eada959bdde927426e2531c9Paul Duffin/* 27dd252788645e940eada959bdde927426e2531c9Paul Duffin * Copyright (C) 2012 The Guava Authors 37dd252788645e940eada959bdde927426e2531c9Paul Duffin * 47dd252788645e940eada959bdde927426e2531c9Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License"); 57dd252788645e940eada959bdde927426e2531c9Paul Duffin * you may not use this file except in compliance with the License. 67dd252788645e940eada959bdde927426e2531c9Paul Duffin * You may obtain a copy of the License at 77dd252788645e940eada959bdde927426e2531c9Paul Duffin * 87dd252788645e940eada959bdde927426e2531c9Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0 97dd252788645e940eada959bdde927426e2531c9Paul Duffin * 107dd252788645e940eada959bdde927426e2531c9Paul Duffin * Unless required by applicable law or agreed to in writing, software 117dd252788645e940eada959bdde927426e2531c9Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS, 127dd252788645e940eada959bdde927426e2531c9Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137dd252788645e940eada959bdde927426e2531c9Paul Duffin * See the License for the specific language governing permissions and 147dd252788645e940eada959bdde927426e2531c9Paul Duffin * limitations under the License. 157dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 167dd252788645e940eada959bdde927426e2531c9Paul Duffin 177dd252788645e940eada959bdde927426e2531c9Paul Duffinpackage com.google.common.reflect; 187dd252788645e940eada959bdde927426e2531c9Paul Duffin 197dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull; 207dd252788645e940eada959bdde927426e2531c9Paul Duffin 217dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.annotations.Beta; 227dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.ImmutableList; 237dd252788645e940eada959bdde927426e2531c9Paul Duffin 247dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.annotation.Annotation; 257dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.AccessibleObject; 267dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Constructor; 277dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.GenericDeclaration; 287dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.InvocationTargetException; 297dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Member; 307dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Method; 317dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Modifier; 327dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Type; 337dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.TypeVariable; 340888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Arrays; 357dd252788645e940eada959bdde927426e2531c9Paul Duffin 367dd252788645e940eada959bdde927426e2531c9Paul Duffinimport javax.annotation.Nullable; 377dd252788645e940eada959bdde927426e2531c9Paul Duffin 387dd252788645e940eada959bdde927426e2531c9Paul Duffin/** 397dd252788645e940eada959bdde927426e2531c9Paul Duffin * Wrapper around either a {@link Method} or a {@link Constructor}. 407dd252788645e940eada959bdde927426e2531c9Paul Duffin * Convenience API is provided to make common reflective operation easier to deal with, 417dd252788645e940eada959bdde927426e2531c9Paul Duffin * such as {@link #isPublic}, {@link #getParameters} etc. 427dd252788645e940eada959bdde927426e2531c9Paul Duffin * 437dd252788645e940eada959bdde927426e2531c9Paul Duffin * <p>In addition to convenience methods, {@link TypeToken#method} and {@link 447dd252788645e940eada959bdde927426e2531c9Paul Duffin * TypeToken#constructor} will resolve the type parameters of the method or constructor in the 457dd252788645e940eada959bdde927426e2531c9Paul Duffin * context of the owner type, which may be a subtype of the declaring class. For example: 467dd252788645e940eada959bdde927426e2531c9Paul Duffin * 470888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <pre> {@code 487dd252788645e940eada959bdde927426e2531c9Paul Duffin * Method getMethod = List.class.getMethod("get", int.class); 497dd252788645e940eada959bdde927426e2531c9Paul Duffin * Invokable<List<String>, ?> invokable = new TypeToken<List<String>>() {}.method(getMethod); 507dd252788645e940eada959bdde927426e2531c9Paul Duffin * assertEquals(TypeToken.of(String.class), invokable.getReturnType()); // Not Object.class! 517dd252788645e940eada959bdde927426e2531c9Paul Duffin * assertEquals(new TypeToken<List<String>>() {}, invokable.getOwnerType());}</pre> 527dd252788645e940eada959bdde927426e2531c9Paul Duffin * 537dd252788645e940eada959bdde927426e2531c9Paul Duffin * @param <T> the type that owns this method or constructor. 547dd252788645e940eada959bdde927426e2531c9Paul Duffin * @param <R> the return type of (or supertype thereof) the method or the declaring type of the 557dd252788645e940eada959bdde927426e2531c9Paul Duffin * constructor. 567dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Ben Yu 577dd252788645e940eada959bdde927426e2531c9Paul Duffin * @since 14.0 587dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 597dd252788645e940eada959bdde927426e2531c9Paul Duffin@Beta 607dd252788645e940eada959bdde927426e2531c9Paul Duffinpublic abstract class Invokable<T, R> extends Element implements GenericDeclaration { 617dd252788645e940eada959bdde927426e2531c9Paul Duffin 627dd252788645e940eada959bdde927426e2531c9Paul Duffin <M extends AccessibleObject & Member> Invokable(M member) { 637dd252788645e940eada959bdde927426e2531c9Paul Duffin super(member); 647dd252788645e940eada959bdde927426e2531c9Paul Duffin } 657dd252788645e940eada959bdde927426e2531c9Paul Duffin 667dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Returns {@link Invokable} of {@code method}. */ 677dd252788645e940eada959bdde927426e2531c9Paul Duffin public static Invokable<?, Object> from(Method method) { 687dd252788645e940eada959bdde927426e2531c9Paul Duffin return new MethodInvokable<Object>(method); 697dd252788645e940eada959bdde927426e2531c9Paul Duffin } 707dd252788645e940eada959bdde927426e2531c9Paul Duffin 717dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Returns {@link Invokable} of {@code constructor}. */ 727dd252788645e940eada959bdde927426e2531c9Paul Duffin public static <T> Invokable<T, T> from(Constructor<T> constructor) { 737dd252788645e940eada959bdde927426e2531c9Paul Duffin return new ConstructorInvokable<T>(constructor); 747dd252788645e940eada959bdde927426e2531c9Paul Duffin } 757dd252788645e940eada959bdde927426e2531c9Paul Duffin 767dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 777dd252788645e940eada959bdde927426e2531c9Paul Duffin * Returns {@code true} if this is an overridable method. Constructors, private, static or final 787dd252788645e940eada959bdde927426e2531c9Paul Duffin * methods, or methods declared by final classes are not overridable. 797dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 807dd252788645e940eada959bdde927426e2531c9Paul Duffin public abstract boolean isOverridable(); 817dd252788645e940eada959bdde927426e2531c9Paul Duffin 827dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Returns {@code true} if this was declared to take a variable number of arguments. */ 837dd252788645e940eada959bdde927426e2531c9Paul Duffin public abstract boolean isVarArgs(); 847dd252788645e940eada959bdde927426e2531c9Paul Duffin 857dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 867dd252788645e940eada959bdde927426e2531c9Paul Duffin * Invokes with {@code receiver} as 'this' and {@code args} passed to the underlying method 877dd252788645e940eada959bdde927426e2531c9Paul Duffin * and returns the return value; or calls the underlying constructor with {@code args} and returns 887dd252788645e940eada959bdde927426e2531c9Paul Duffin * the constructed instance. 897dd252788645e940eada959bdde927426e2531c9Paul Duffin * 907dd252788645e940eada959bdde927426e2531c9Paul Duffin * @throws IllegalAccessException if this {@code Constructor} object enforces Java language 917dd252788645e940eada959bdde927426e2531c9Paul Duffin * access control and the underlying method or constructor is inaccessible. 927dd252788645e940eada959bdde927426e2531c9Paul Duffin * @throws IllegalArgumentException if the number of actual and formal parameters differ; 937dd252788645e940eada959bdde927426e2531c9Paul Duffin * if an unwrapping conversion for primitive arguments fails; or if, after possible 947dd252788645e940eada959bdde927426e2531c9Paul Duffin * unwrapping, a parameter value cannot be converted to the corresponding formal 957dd252788645e940eada959bdde927426e2531c9Paul Duffin * parameter type by a method invocation conversion. 967dd252788645e940eada959bdde927426e2531c9Paul Duffin * @throws InvocationTargetException if the underlying method or constructor throws an exception. 977dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 987dd252788645e940eada959bdde927426e2531c9Paul Duffin // All subclasses are owned by us and we'll make sure to get the R type right. 997dd252788645e940eada959bdde927426e2531c9Paul Duffin @SuppressWarnings("unchecked") 1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin public final R invoke(@Nullable T receiver, Object... args) 1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin throws InvocationTargetException, IllegalAccessException { 1027dd252788645e940eada959bdde927426e2531c9Paul Duffin return (R) invokeInternal(receiver, checkNotNull(args)); 1037dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1047dd252788645e940eada959bdde927426e2531c9Paul Duffin 1057dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Returns the return type of this {@code Invokable}. */ 1067dd252788645e940eada959bdde927426e2531c9Paul Duffin // All subclasses are owned by us and we'll make sure to get the R type right. 1077dd252788645e940eada959bdde927426e2531c9Paul Duffin @SuppressWarnings("unchecked") 1087dd252788645e940eada959bdde927426e2531c9Paul Duffin public final TypeToken<? extends R> getReturnType() { 1097dd252788645e940eada959bdde927426e2531c9Paul Duffin return (TypeToken<? extends R>) TypeToken.of(getGenericReturnType()); 1107dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1117dd252788645e940eada959bdde927426e2531c9Paul Duffin 1127dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 1137dd252788645e940eada959bdde927426e2531c9Paul Duffin * Returns all declared parameters of this {@code Invokable}. Note that if this is a constructor 1147dd252788645e940eada959bdde927426e2531c9Paul Duffin * of a non-static inner class, unlike {@link Constructor#getParameterTypes}, the hidden 1157dd252788645e940eada959bdde927426e2531c9Paul Duffin * {@code this} parameter of the enclosing class is excluded from the returned parameters. 1167dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 1177dd252788645e940eada959bdde927426e2531c9Paul Duffin public final ImmutableList<Parameter> getParameters() { 1187dd252788645e940eada959bdde927426e2531c9Paul Duffin Type[] parameterTypes = getGenericParameterTypes(); 1197dd252788645e940eada959bdde927426e2531c9Paul Duffin Annotation[][] annotations = getParameterAnnotations(); 1207dd252788645e940eada959bdde927426e2531c9Paul Duffin ImmutableList.Builder<Parameter> builder = ImmutableList.builder(); 1217dd252788645e940eada959bdde927426e2531c9Paul Duffin for (int i = 0; i < parameterTypes.length; i++) { 1220888a09821a98ac0680fad765217302858e70fa4Paul Duffin builder.add(new Parameter( 1230888a09821a98ac0680fad765217302858e70fa4Paul Duffin this, i, TypeToken.of(parameterTypes[i]), annotations[i])); 1247dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1257dd252788645e940eada959bdde927426e2531c9Paul Duffin return builder.build(); 1267dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1277dd252788645e940eada959bdde927426e2531c9Paul Duffin 1287dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Returns all declared exception types of this {@code Invokable}. */ 1297dd252788645e940eada959bdde927426e2531c9Paul Duffin public final ImmutableList<TypeToken<? extends Throwable>> getExceptionTypes() { 1307dd252788645e940eada959bdde927426e2531c9Paul Duffin ImmutableList.Builder<TypeToken<? extends Throwable>> builder = ImmutableList.builder(); 1317dd252788645e940eada959bdde927426e2531c9Paul Duffin for (Type type : getGenericExceptionTypes()) { 1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin // getGenericExceptionTypes() will never return a type that's not exception 1337dd252788645e940eada959bdde927426e2531c9Paul Duffin @SuppressWarnings("unchecked") 1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin TypeToken<? extends Throwable> exceptionType = (TypeToken<? extends Throwable>) 1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin TypeToken.of(type); 1367dd252788645e940eada959bdde927426e2531c9Paul Duffin builder.add(exceptionType); 1377dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1387dd252788645e940eada959bdde927426e2531c9Paul Duffin return builder.build(); 1397dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1407dd252788645e940eada959bdde927426e2531c9Paul Duffin 1417dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 1427dd252788645e940eada959bdde927426e2531c9Paul Duffin * Explicitly specifies the return type of this {@code Invokable}. For example: 1437dd252788645e940eada959bdde927426e2531c9Paul Duffin * <pre> {@code 1447dd252788645e940eada959bdde927426e2531c9Paul Duffin * Method factoryMethod = Person.class.getMethod("create"); 1450888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Invokable<?, Person> factory = Invokable.of(getNameMethod).returning(Person.class);}</pre> 1467dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 1477dd252788645e940eada959bdde927426e2531c9Paul Duffin public final <R1 extends R> Invokable<T, R1> returning(Class<R1> returnType) { 1487dd252788645e940eada959bdde927426e2531c9Paul Duffin return returning(TypeToken.of(returnType)); 1497dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1507dd252788645e940eada959bdde927426e2531c9Paul Duffin 1517dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Explicitly specifies the return type of this {@code Invokable}. */ 1527dd252788645e940eada959bdde927426e2531c9Paul Duffin public final <R1 extends R> Invokable<T, R1> returning(TypeToken<R1> returnType) { 1537dd252788645e940eada959bdde927426e2531c9Paul Duffin if (!returnType.isAssignableFrom(getReturnType())) { 1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin throw new IllegalArgumentException( 1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin "Invokable is known to return " + getReturnType() + ", not " + returnType); 1567dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1570888a09821a98ac0680fad765217302858e70fa4Paul Duffin @SuppressWarnings("unchecked") // guarded by previous check 1587dd252788645e940eada959bdde927426e2531c9Paul Duffin Invokable<T, R1> specialized = (Invokable<T, R1>) this; 1597dd252788645e940eada959bdde927426e2531c9Paul Duffin return specialized; 1607dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1617dd252788645e940eada959bdde927426e2531c9Paul Duffin 1620888a09821a98ac0680fad765217302858e70fa4Paul Duffin @SuppressWarnings("unchecked") // The declaring class is T's raw class, or one of its supertypes. 1630888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public final Class<? super T> getDeclaringClass() { 1647dd252788645e940eada959bdde927426e2531c9Paul Duffin return (Class<? super T>) super.getDeclaringClass(); 1657dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1667dd252788645e940eada959bdde927426e2531c9Paul Duffin 1677dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Returns the type of {@code T}. */ 1687dd252788645e940eada959bdde927426e2531c9Paul Duffin // Overridden in TypeToken#method() and TypeToken#constructor() 1697dd252788645e940eada959bdde927426e2531c9Paul Duffin @SuppressWarnings("unchecked") // The declaring class is T. 1700888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public TypeToken<T> getOwnerType() { 1717dd252788645e940eada959bdde927426e2531c9Paul Duffin return (TypeToken<T>) TypeToken.of(getDeclaringClass()); 1727dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1737dd252788645e940eada959bdde927426e2531c9Paul Duffin 1747dd252788645e940eada959bdde927426e2531c9Paul Duffin abstract Object invokeInternal(@Nullable Object receiver, Object[] args) 1757dd252788645e940eada959bdde927426e2531c9Paul Duffin throws InvocationTargetException, IllegalAccessException; 1767dd252788645e940eada959bdde927426e2531c9Paul Duffin 1777dd252788645e940eada959bdde927426e2531c9Paul Duffin abstract Type[] getGenericParameterTypes(); 1787dd252788645e940eada959bdde927426e2531c9Paul Duffin 1797dd252788645e940eada959bdde927426e2531c9Paul Duffin /** This should never return a type that's not a subtype of Throwable. */ 1807dd252788645e940eada959bdde927426e2531c9Paul Duffin abstract Type[] getGenericExceptionTypes(); 1817dd252788645e940eada959bdde927426e2531c9Paul Duffin 1827dd252788645e940eada959bdde927426e2531c9Paul Duffin abstract Annotation[][] getParameterAnnotations(); 1837dd252788645e940eada959bdde927426e2531c9Paul Duffin 1847dd252788645e940eada959bdde927426e2531c9Paul Duffin abstract Type getGenericReturnType(); 1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1867dd252788645e940eada959bdde927426e2531c9Paul Duffin static class MethodInvokable<T> extends Invokable<T, Object> { 1877dd252788645e940eada959bdde927426e2531c9Paul Duffin 1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin final Method method; 1897dd252788645e940eada959bdde927426e2531c9Paul Duffin 1907dd252788645e940eada959bdde927426e2531c9Paul Duffin MethodInvokable(Method method) { 1917dd252788645e940eada959bdde927426e2531c9Paul Duffin super(method); 1927dd252788645e940eada959bdde927426e2531c9Paul Duffin this.method = method; 1937dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1947dd252788645e940eada959bdde927426e2531c9Paul Duffin 1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override final Object invokeInternal(@Nullable Object receiver, Object[] args) 1967dd252788645e940eada959bdde927426e2531c9Paul Duffin throws InvocationTargetException, IllegalAccessException { 1977dd252788645e940eada959bdde927426e2531c9Paul Duffin return method.invoke(receiver, args); 1987dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1997dd252788645e940eada959bdde927426e2531c9Paul Duffin 2000888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override Type getGenericReturnType() { 2017dd252788645e940eada959bdde927426e2531c9Paul Duffin return method.getGenericReturnType(); 2027dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2037dd252788645e940eada959bdde927426e2531c9Paul Duffin 2040888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override Type[] getGenericParameterTypes() { 2057dd252788645e940eada959bdde927426e2531c9Paul Duffin return method.getGenericParameterTypes(); 2067dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2077dd252788645e940eada959bdde927426e2531c9Paul Duffin 2080888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override Type[] getGenericExceptionTypes() { 2097dd252788645e940eada959bdde927426e2531c9Paul Duffin return method.getGenericExceptionTypes(); 2107dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2117dd252788645e940eada959bdde927426e2531c9Paul Duffin 2120888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override final Annotation[][] getParameterAnnotations() { 2137dd252788645e940eada959bdde927426e2531c9Paul Duffin return method.getParameterAnnotations(); 2147dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2157dd252788645e940eada959bdde927426e2531c9Paul Duffin 2160888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public final TypeVariable<?>[] getTypeParameters() { 2177dd252788645e940eada959bdde927426e2531c9Paul Duffin return method.getTypeParameters(); 2187dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2197dd252788645e940eada959bdde927426e2531c9Paul Duffin 2207dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public final boolean isOverridable() { 2217dd252788645e940eada959bdde927426e2531c9Paul Duffin return !(isFinal() || isPrivate() || isStatic() 2227dd252788645e940eada959bdde927426e2531c9Paul Duffin || Modifier.isFinal(getDeclaringClass().getModifiers())); 2237dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2247dd252788645e940eada959bdde927426e2531c9Paul Duffin 2257dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public final boolean isVarArgs() { 2267dd252788645e940eada959bdde927426e2531c9Paul Duffin return method.isVarArgs(); 2277dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2287dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2297dd252788645e940eada959bdde927426e2531c9Paul Duffin 2307dd252788645e940eada959bdde927426e2531c9Paul Duffin static class ConstructorInvokable<T> extends Invokable<T, T> { 2317dd252788645e940eada959bdde927426e2531c9Paul Duffin 2320888a09821a98ac0680fad765217302858e70fa4Paul Duffin final Constructor<?> constructor; 2337dd252788645e940eada959bdde927426e2531c9Paul Duffin 2347dd252788645e940eada959bdde927426e2531c9Paul Duffin ConstructorInvokable(Constructor<?> constructor) { 2357dd252788645e940eada959bdde927426e2531c9Paul Duffin super(constructor); 2367dd252788645e940eada959bdde927426e2531c9Paul Duffin this.constructor = constructor; 2377dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2387dd252788645e940eada959bdde927426e2531c9Paul Duffin 2390888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override final Object invokeInternal(@Nullable Object receiver, Object[] args) 2407dd252788645e940eada959bdde927426e2531c9Paul Duffin throws InvocationTargetException, IllegalAccessException { 2417dd252788645e940eada959bdde927426e2531c9Paul Duffin try { 2427dd252788645e940eada959bdde927426e2531c9Paul Duffin return constructor.newInstance(args); 2437dd252788645e940eada959bdde927426e2531c9Paul Duffin } catch (InstantiationException e) { 2447dd252788645e940eada959bdde927426e2531c9Paul Duffin throw new RuntimeException(constructor + " failed.", e); 2457dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2467dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2477dd252788645e940eada959bdde927426e2531c9Paul Duffin 2480888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** If the class is parameterized, such as ArrayList, this returns ArrayList<E>. */ 2490888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override Type getGenericReturnType() { 2500888a09821a98ac0680fad765217302858e70fa4Paul Duffin Class<?> declaringClass = getDeclaringClass(); 2510888a09821a98ac0680fad765217302858e70fa4Paul Duffin TypeVariable<?>[] typeParams = declaringClass.getTypeParameters(); 2520888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (typeParams.length > 0) { 2530888a09821a98ac0680fad765217302858e70fa4Paul Duffin return Types.newParameterizedType(declaringClass, typeParams); 2540888a09821a98ac0680fad765217302858e70fa4Paul Duffin } else { 2550888a09821a98ac0680fad765217302858e70fa4Paul Duffin return declaringClass; 2560888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 2577dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2587dd252788645e940eada959bdde927426e2531c9Paul Duffin 2590888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override Type[] getGenericParameterTypes() { 2607dd252788645e940eada959bdde927426e2531c9Paul Duffin Type[] types = constructor.getGenericParameterTypes(); 2610888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (types.length > 0 && mayNeedHiddenThis()) { 2620888a09821a98ac0680fad765217302858e70fa4Paul Duffin Class<?>[] rawParamTypes = constructor.getParameterTypes(); 2630888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (types.length == rawParamTypes.length 2640888a09821a98ac0680fad765217302858e70fa4Paul Duffin && rawParamTypes[0] == getDeclaringClass().getEnclosingClass()) { 2657dd252788645e940eada959bdde927426e2531c9Paul Duffin // first parameter is the hidden 'this' 2663ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffin return Arrays.copyOfRange(types, 1, types.length); 2677dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2687dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2697dd252788645e940eada959bdde927426e2531c9Paul Duffin return types; 2707dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2717dd252788645e940eada959bdde927426e2531c9Paul Duffin 2720888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override Type[] getGenericExceptionTypes() { 2737dd252788645e940eada959bdde927426e2531c9Paul Duffin return constructor.getGenericExceptionTypes(); 2747dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2757dd252788645e940eada959bdde927426e2531c9Paul Duffin 2760888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override final Annotation[][] getParameterAnnotations() { 2777dd252788645e940eada959bdde927426e2531c9Paul Duffin return constructor.getParameterAnnotations(); 2787dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2797dd252788645e940eada959bdde927426e2531c9Paul Duffin 2800888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 2810888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@inheritDoc} 2820888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 2830888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@code [<E>]} will be returned for ArrayList's constructor. When both the class and the 2840888a09821a98ac0680fad765217302858e70fa4Paul Duffin * constructor have type parameters, the class parameters are prepended before those of the 2850888a09821a98ac0680fad765217302858e70fa4Paul Duffin * constructor's. This is an arbitrary rule since no existing language spec mandates one way or 2860888a09821a98ac0680fad765217302858e70fa4Paul Duffin * the other. From the declaration syntax, the class type parameter appears first, but the 2870888a09821a98ac0680fad765217302858e70fa4Paul Duffin * call syntax may show up in opposite order such as {@code new <A>Foo<B>()}. 2880888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 2890888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public final TypeVariable<?>[] getTypeParameters() { 2900888a09821a98ac0680fad765217302858e70fa4Paul Duffin TypeVariable<?>[] declaredByClass = getDeclaringClass().getTypeParameters(); 2910888a09821a98ac0680fad765217302858e70fa4Paul Duffin TypeVariable<?>[] declaredByConstructor = constructor.getTypeParameters(); 2920888a09821a98ac0680fad765217302858e70fa4Paul Duffin TypeVariable<?>[] result = 2930888a09821a98ac0680fad765217302858e70fa4Paul Duffin new TypeVariable<?>[declaredByClass.length + declaredByConstructor.length]; 2940888a09821a98ac0680fad765217302858e70fa4Paul Duffin System.arraycopy(declaredByClass, 0, result, 0, declaredByClass.length); 2950888a09821a98ac0680fad765217302858e70fa4Paul Duffin System.arraycopy( 2960888a09821a98ac0680fad765217302858e70fa4Paul Duffin declaredByConstructor, 0, 2970888a09821a98ac0680fad765217302858e70fa4Paul Duffin result, declaredByClass.length, 2980888a09821a98ac0680fad765217302858e70fa4Paul Duffin declaredByConstructor.length); 2990888a09821a98ac0680fad765217302858e70fa4Paul Duffin return result; 3007dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3017dd252788645e940eada959bdde927426e2531c9Paul Duffin 3020888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override public final boolean isOverridable() { 3037dd252788645e940eada959bdde927426e2531c9Paul Duffin return false; 3047dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3057dd252788645e940eada959bdde927426e2531c9Paul Duffin 3067dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public final boolean isVarArgs() { 3077dd252788645e940eada959bdde927426e2531c9Paul Duffin return constructor.isVarArgs(); 3087dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3090888a09821a98ac0680fad765217302858e70fa4Paul Duffin 3100888a09821a98ac0680fad765217302858e70fa4Paul Duffin private boolean mayNeedHiddenThis() { 3110888a09821a98ac0680fad765217302858e70fa4Paul Duffin Class<?> declaringClass = constructor.getDeclaringClass(); 3120888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (declaringClass.getEnclosingConstructor() != null) { 3130888a09821a98ac0680fad765217302858e70fa4Paul Duffin // Enclosed in a constructor, needs hidden this 3140888a09821a98ac0680fad765217302858e70fa4Paul Duffin return true; 3150888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 3160888a09821a98ac0680fad765217302858e70fa4Paul Duffin Method enclosingMethod = declaringClass.getEnclosingMethod(); 3170888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (enclosingMethod != null) { 3180888a09821a98ac0680fad765217302858e70fa4Paul Duffin // Enclosed in a method, if it's not static, must need hidden this. 3190888a09821a98ac0680fad765217302858e70fa4Paul Duffin return !Modifier.isStatic(enclosingMethod.getModifiers()); 3200888a09821a98ac0680fad765217302858e70fa4Paul Duffin } else { 3210888a09821a98ac0680fad765217302858e70fa4Paul Duffin // Strictly, this doesn't necessarily indicate a hidden 'this' in the case of 3220888a09821a98ac0680fad765217302858e70fa4Paul Duffin // static initializer. But there seems no way to tell in that case. :( 3230888a09821a98ac0680fad765217302858e70fa4Paul Duffin // This may cause issues when an anonymous class is created inside a static initializer, 3240888a09821a98ac0680fad765217302858e70fa4Paul Duffin // and the class's constructor's first parameter happens to be the enclosing class. 3250888a09821a98ac0680fad765217302858e70fa4Paul Duffin // In such case, we may mistakenly think that the class is within a non-static context 3260888a09821a98ac0680fad765217302858e70fa4Paul Duffin // and the first parameter is the hidden 'this'. 3270888a09821a98ac0680fad765217302858e70fa4Paul Duffin return declaringClass.getEnclosingClass() != null 3280888a09821a98ac0680fad765217302858e70fa4Paul Duffin && !Modifier.isStatic(declaringClass.getModifiers()); 3290888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 3300888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 3317dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3327dd252788645e940eada959bdde927426e2531c9Paul Duffin} 333