--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/Constructor.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,696 @@
+/*
+ * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.lang.reflect;
+
+import sun.reflect.ConstructorAccessor;
+import sun.reflect.Reflection;
+import sun.reflect.generics.repository.ConstructorRepository;
+import sun.reflect.generics.factory.CoreReflectionFactory;
+import sun.reflect.generics.factory.GenericsFactory;
+import sun.reflect.generics.scope.ConstructorScope;
+import java.lang.annotation.Annotation;
+import java.util.Map;
+import sun.reflect.annotation.AnnotationParser;
+import java.lang.annotation.AnnotationFormatError;
+import java.lang.reflect.Modifier;
+
+/**
+ * {@code Constructor} provides information about, and access to, a single
+ * constructor for a class.
+ *
+ * <p>{@code Constructor} permits widening conversions to occur when matching the
+ * actual parameters to newInstance() with the underlying
+ * constructor's formal parameters, but throws an
+ * {@code IllegalArgumentException} if a narrowing conversion would occur.
+ *
+ * @param <T> the class in which the constructor is declared
+ *
+ * @see Member
+ * @see java.lang.Class
+ * @see java.lang.Class#getConstructors()
+ * @see java.lang.Class#getConstructor(Class[])
+ * @see java.lang.Class#getDeclaredConstructors()
+ *
+ * @author Kenneth Russell
+ * @author Nakul Saraiya
+ */
+public final
+ class Constructor<T> extends AccessibleObject implements
+ GenericDeclaration,
+ Member {
+
+ private Class<T> clazz;
+ private int slot;
+ private Class[] parameterTypes;
+ private Class[] exceptionTypes;
+ private int modifiers;
+ // Generics and annotations support
+ private transient String signature;
+ // generic info repository; lazily initialized
+ private transient ConstructorRepository genericInfo;
+ private byte[] annotations;
+ private byte[] parameterAnnotations;
+
+ // For non-public members or members in package-private classes,
+ // it is necessary to perform somewhat expensive security checks.
+ // If the security check succeeds for a given class, it will
+ // always succeed (it is not affected by the granting or revoking
+ // of permissions); we speed up the check in the common case by
+ // remembering the last Class for which the check succeeded.
+ private volatile Class securityCheckCache;
+
+ // Modifiers that can be applied to a constructor in source code
+ private static final int LANGUAGE_MODIFIERS =
+ Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE;
+
+ // Generics infrastructure
+ // Accessor for factory
+ private GenericsFactory getFactory() {
+ // create scope and factory
+ return CoreReflectionFactory.make(this, ConstructorScope.make(this));
+ }
+
+ // Accessor for generic info repository
+ private ConstructorRepository getGenericInfo() {
+ // lazily initialize repository if necessary
+ if (genericInfo == null) {
+ // create and cache generic info repository
+ genericInfo =
+ ConstructorRepository.make(getSignature(),
+ getFactory());
+ }
+ return genericInfo; //return cached repository
+ }
+
+ private volatile ConstructorAccessor constructorAccessor;
+ // For sharing of ConstructorAccessors. This branching structure
+ // is currently only two levels deep (i.e., one root Constructor
+ // and potentially many Constructor objects pointing to it.)
+ private Constructor<T> root;
+
+ /**
+ * Package-private constructor used by ReflectAccess to enable
+ * instantiation of these objects in Java code from the java.lang
+ * package via sun.reflect.LangReflectAccess.
+ */
+ Constructor(Class<T> declaringClass,
+ Class[] parameterTypes,
+ Class[] checkedExceptions,
+ int modifiers,
+ int slot,
+ String signature,
+ byte[] annotations,
+ byte[] parameterAnnotations)
+ {
+ this.clazz = declaringClass;
+ this.parameterTypes = parameterTypes;
+ this.exceptionTypes = checkedExceptions;
+ this.modifiers = modifiers;
+ this.slot = slot;
+ this.signature = signature;
+ this.annotations = annotations;
+ this.parameterAnnotations = parameterAnnotations;
+ }
+
+ /**
+ * Package-private routine (exposed to java.lang.Class via
+ * ReflectAccess) which returns a copy of this Constructor. The copy's
+ * "root" field points to this Constructor.
+ */
+ Constructor<T> copy() {
+ // This routine enables sharing of ConstructorAccessor objects
+ // among Constructor objects which refer to the same underlying
+ // method in the VM. (All of this contortion is only necessary
+ // because of the "accessibility" bit in AccessibleObject,
+ // which implicitly requires that new java.lang.reflect
+ // objects be fabricated for each reflective call on Class
+ // objects.)
+ Constructor<T> res = new Constructor<T>(clazz,
+ parameterTypes,
+ exceptionTypes, modifiers, slot,
+ signature,
+ annotations,
+ parameterAnnotations);
+ res.root = this;
+ // Might as well eagerly propagate this if already present
+ res.constructorAccessor = constructorAccessor;
+ return res;
+ }
+
+ /**
+ * Returns the {@code Class} object representing the class that declares
+ * the constructor represented by this {@code Constructor} object.
+ */
+ public Class<T> getDeclaringClass() {
+ return clazz;
+ }
+
+ /**
+ * Returns the name of this constructor, as a string. This is
+ * always the same as the simple name of the constructor's declaring
+ * class.
+ */
+ public String getName() {
+ return getDeclaringClass().getName();
+ }
+
+ /**
+ * Returns the Java language modifiers for the constructor
+ * represented by this {@code Constructor} object, as an integer. The
+ * {@code Modifier} class should be used to decode the modifiers.
+ *
+ * @see Modifier
+ */
+ public int getModifiers() {
+ return modifiers;
+ }
+
+ /**
+ * Returns an array of {@code TypeVariable} objects that represent the
+ * type variables declared by the generic declaration represented by this
+ * {@code GenericDeclaration} object, in declaration order. Returns an
+ * array of length 0 if the underlying generic declaration declares no type
+ * variables.
+ *
+ * @return an array of {@code TypeVariable} objects that represent
+ * the type variables declared by this generic declaration
+ * @throws GenericSignatureFormatError if the generic
+ * signature of this generic declaration does not conform to
+ * the format specified in the Java Virtual Machine Specification,
+ * 3rd edition
+ * @since 1.5
+ */
+ public TypeVariable<Constructor<T>>[] getTypeParameters() {
+ if (getSignature() != null) {
+ return (TypeVariable<Constructor<T>>[])getGenericInfo().getTypeParameters();
+ } else
+ return (TypeVariable<Constructor<T>>[])new TypeVariable[0];
+ }
+
+
+ /**
+ * Returns an array of {@code Class} objects that represent the formal
+ * parameter types, in declaration order, of the constructor
+ * represented by this {@code Constructor} object. Returns an array of
+ * length 0 if the underlying constructor takes no parameters.
+ *
+ * @return the parameter types for the constructor this object
+ * represents
+ */
+ public Class<?>[] getParameterTypes() {
+ return (Class<?>[]) parameterTypes.clone();
+ }
+
+
+ /**
+ * Returns an array of {@code Type} objects that represent the formal
+ * parameter types, in declaration order, of the method represented by
+ * this {@code Constructor} object. Returns an array of length 0 if the
+ * underlying method takes no parameters.
+ *
+ * <p>If a formal parameter type is a parameterized type,
+ * the {@code Type} object returned for it must accurately reflect
+ * the actual type parameters used in the source code.
+ *
+ * <p>If a formal parameter type is a type variable or a parameterized
+ * type, it is created. Otherwise, it is resolved.
+ *
+ * @return an array of {@code Type}s that represent the formal
+ * parameter types of the underlying method, in declaration order
+ * @throws GenericSignatureFormatError
+ * if the generic method signature does not conform to the format
+ * specified in the Java Virtual Machine Specification, 3rd edition
+ * @throws TypeNotPresentException if any of the parameter
+ * types of the underlying method refers to a non-existent type
+ * declaration
+ * @throws MalformedParameterizedTypeException if any of
+ * the underlying method's parameter types refer to a parameterized
+ * type that cannot be instantiated for any reason
+ * @since 1.5
+ */
+ public Type[] getGenericParameterTypes() {
+ if (getSignature() != null)
+ return getGenericInfo().getParameterTypes();
+ else
+ return getParameterTypes();
+ }
+
+
+ /**
+ * Returns an array of {@code Class} objects that represent the types
+ * of exceptions declared to be thrown by the underlying constructor
+ * represented by this {@code Constructor} object. Returns an array of
+ * length 0 if the constructor declares no exceptions in its {@code throws} clause.
+ *
+ * @return the exception types declared as being thrown by the
+ * constructor this object represents
+ */
+ public Class<?>[] getExceptionTypes() {
+ return (Class<?>[])exceptionTypes.clone();
+ }
+
+
+ /**
+ * Returns an array of {@code Type} objects that represent the
+ * exceptions declared to be thrown by this {@code Constructor} object.
+ * Returns an array of length 0 if the underlying method declares
+ * no exceptions in its {@code throws} clause.
+ *
+ * <p>If an exception type is a parameterized type, the {@code Type}
+ * object returned for it must accurately reflect the actual type
+ * parameters used in the source code.
+ *
+ * <p>If an exception type is a type variable or a parameterized
+ * type, it is created. Otherwise, it is resolved.
+ *
+ * @return an array of Types that represent the exception types
+ * thrown by the underlying method
+ * @throws GenericSignatureFormatError
+ * if the generic method signature does not conform to the format
+ * specified in the Java Virtual Machine Specification, 3rd edition
+ * @throws TypeNotPresentException if the underlying method's
+ * {@code throws} clause refers to a non-existent type declaration
+ * @throws MalformedParameterizedTypeException if
+ * the underlying method's {@code throws} clause refers to a
+ * parameterized type that cannot be instantiated for any reason
+ * @since 1.5
+ */
+ public Type[] getGenericExceptionTypes() {
+ Type[] result;
+ if (getSignature() != null &&
+ ( (result = getGenericInfo().getExceptionTypes()).length > 0 ))
+ return result;
+ else
+ return getExceptionTypes();
+ }
+
+ /**
+ * Compares this {@code Constructor} against the specified object.
+ * Returns true if the objects are the same. Two {@code Constructor} objects are
+ * the same if they were declared by the same class and have the
+ * same formal parameter types.
+ */
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof Constructor) {
+ Constructor other = (Constructor)obj;
+ if (getDeclaringClass() == other.getDeclaringClass()) {
+ /* Avoid unnecessary cloning */
+ Class[] params1 = parameterTypes;
+ Class[] params2 = other.parameterTypes;
+ if (params1.length == params2.length) {
+ for (int i = 0; i < params1.length; i++) {
+ if (params1[i] != params2[i])
+ return false;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hashcode for this {@code Constructor}. The hashcode is
+ * the same as the hashcode for the underlying constructor's
+ * declaring class name.
+ */
+ public int hashCode() {
+ return getDeclaringClass().getName().hashCode();
+ }
+
+ /**
+ * Returns a string describing this {@code Constructor}. The string is
+ * formatted as the constructor access modifiers, if any,
+ * followed by the fully-qualified name of the declaring class,
+ * followed by a parenthesized, comma-separated list of the
+ * constructor's formal parameter types. For example:
+ * <pre>
+ * public java.util.Hashtable(int,float)
+ * </pre>
+ *
+ * <p>The only possible modifiers for constructors are the access
+ * modifiers {@code public}, {@code protected} or
+ * {@code private}. Only one of these may appear, or none if the
+ * constructor has default (package) access.
+ */
+ public String toString() {
+ try {
+ StringBuffer sb = new StringBuffer();
+ int mod = getModifiers() & LANGUAGE_MODIFIERS;
+ if (mod != 0) {
+ sb.append(Modifier.toString(mod) + " ");
+ }
+ sb.append(Field.getTypeName(getDeclaringClass()));
+ sb.append("(");
+ Class[] params = parameterTypes; // avoid clone
+ for (int j = 0; j < params.length; j++) {
+ sb.append(Field.getTypeName(params[j]));
+ if (j < (params.length - 1))
+ sb.append(",");
+ }
+ sb.append(")");
+ Class[] exceptions = exceptionTypes; // avoid clone
+ if (exceptions.length > 0) {
+ sb.append(" throws ");
+ for (int k = 0; k < exceptions.length; k++) {
+ sb.append(exceptions[k].getName());
+ if (k < (exceptions.length - 1))
+ sb.append(",");
+ }
+ }
+ return sb.toString();
+ } catch (Exception e) {
+ return "<" + e + ">";
+ }
+ }
+
+ /**
+ * Returns a string describing this {@code Constructor},
+ * including type parameters. The string is formatted as the
+ * constructor access modifiers, if any, followed by an
+ * angle-bracketed comma separated list of the constructor's type
+ * parameters, if any, followed by the fully-qualified name of the
+ * declaring class, followed by a parenthesized, comma-separated
+ * list of the constructor's generic formal parameter types.
+ *
+ * If this constructor was declared to take a variable number of
+ * arguments, instead of denoting the last parameter as
+ * "<tt><i>Type</i>[]</tt>", it is denoted as
+ * "<tt><i>Type</i>...</tt>".
+ *
+ * A space is used to separate access modifiers from one another
+ * and from the type parameters or return type. If there are no
+ * type parameters, the type parameter list is elided; if the type
+ * parameter list is present, a space separates the list from the
+ * class name. If the constructor is declared to throw
+ * exceptions, the parameter list is followed by a space, followed
+ * by the word "{@code throws}" followed by a
+ * comma-separated list of the thrown exception types.
+ *
+ * <p>The only possible modifiers for constructors are the access
+ * modifiers {@code public}, {@code protected} or
+ * {@code private}. Only one of these may appear, or none if the
+ * constructor has default (package) access.
+ *
+ * @return a string describing this {@code Constructor},
+ * include type parameters
+ *
+ * @since 1.5
+ */
+ public String toGenericString() {
+ try {
+ StringBuilder sb = new StringBuilder();
+ int mod = getModifiers() & LANGUAGE_MODIFIERS;
+ if (mod != 0) {
+ sb.append(Modifier.toString(mod) + " ");
+ }
+ TypeVariable<?>[] typeparms = getTypeParameters();
+ if (typeparms.length > 0) {
+ boolean first = true;
+ sb.append("<");
+ for(TypeVariable<?> typeparm: typeparms) {
+ if (!first)
+ sb.append(",");
+ // Class objects can't occur here; no need to test
+ // and call Class.getName().
+ sb.append(typeparm.toString());
+ first = false;
+ }
+ sb.append("> ");
+ }
+ sb.append(Field.getTypeName(getDeclaringClass()));
+ sb.append("(");
+ Type[] params = getGenericParameterTypes();
+ for (int j = 0; j < params.length; j++) {
+ String param = (params[j] instanceof Class<?>)?
+ Field.getTypeName((Class<?>)params[j]):
+ (params[j].toString());
+ if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
+ param = param.replaceFirst("\\[\\]$", "...");
+ sb.append(param);
+ if (j < (params.length - 1))
+ sb.append(",");
+ }
+ sb.append(")");
+ Type[] exceptions = getGenericExceptionTypes();
+ if (exceptions.length > 0) {
+ sb.append(" throws ");
+ for (int k = 0; k < exceptions.length; k++) {
+ sb.append((exceptions[k] instanceof Class)?
+ ((Class)exceptions[k]).getName():
+ exceptions[k].toString());
+ if (k < (exceptions.length - 1))
+ sb.append(",");
+ }
+ }
+ return sb.toString();
+ } catch (Exception e) {
+ return "<" + e + ">";
+ }
+ }
+
+ /**
+ * Uses the constructor represented by this {@code Constructor} object to
+ * create and initialize a new instance of the constructor's
+ * declaring class, with the specified initialization parameters.
+ * Individual parameters are automatically unwrapped to match
+ * primitive formal parameters, and both primitive and reference
+ * parameters are subject to method invocation conversions as necessary.
+ *
+ * <p>If the number of formal parameters required by the underlying constructor
+ * is 0, the supplied {@code initargs} array may be of length 0 or null.
+ *
+ * <p>If the constructor's declaring class is an inner class in a
+ * non-static context, the first argument to the constructor needs
+ * to be the enclosing instance; see <i>The Java Language
+ * Specification</i>, section 15.9.3.
+ *
+ * <p>If the required access and argument checks succeed and the
+ * instantiation will proceed, the constructor's declaring class
+ * is initialized if it has not already been initialized.
+ *
+ * <p>If the constructor completes normally, returns the newly
+ * created and initialized instance.
+ *
+ * @param initargs array of objects to be passed as arguments to
+ * the constructor call; values of primitive types are wrapped in
+ * a wrapper object of the appropriate type (e.g. a {@code float}
+ * in a {@link java.lang.Float Float})
+ *
+ * @return a new object created by calling the constructor
+ * this object represents
+ *
+ * @exception IllegalAccessException if this {@code Constructor} object
+ * enforces Java language access control and the underlying
+ * constructor is inaccessible.
+ * @exception IllegalArgumentException if the number of actual
+ * and formal parameters differ; if an unwrapping
+ * conversion for primitive arguments fails; or if,
+ * after possible unwrapping, a parameter value
+ * cannot be converted to the corresponding formal
+ * parameter type by a method invocation conversion; if
+ * this constructor pertains to an enum type.
+ * @exception InstantiationException if the class that declares the
+ * underlying constructor represents an abstract class.
+ * @exception InvocationTargetException if the underlying constructor
+ * throws an exception.
+ * @exception ExceptionInInitializerError if the initialization provoked
+ * by this method fails.
+ */
+ public T newInstance(Object ... initargs)
+ throws InstantiationException, IllegalAccessException,
+ IllegalArgumentException, InvocationTargetException
+ {
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ Class caller = Reflection.getCallerClass(2);
+ if (securityCheckCache != caller) {
+ Reflection.ensureMemberAccess(caller, clazz, null, modifiers);
+ securityCheckCache = caller;
+ }
+ }
+ }
+ if ((clazz.getModifiers() & Modifier.ENUM) != 0)
+ throw new IllegalArgumentException("Cannot reflectively create enum objects");
+ if (constructorAccessor == null) acquireConstructorAccessor();
+ return (T) constructorAccessor.newInstance(initargs);
+ }
+
+ /**
+ * Returns {@code true} if this constructor was declared to take
+ * a variable number of arguments; returns {@code false}
+ * otherwise.
+ *
+ * @return {@code true} if an only if this constructor was declared to
+ * take a variable number of arguments.
+ * @since 1.5
+ */
+ public boolean isVarArgs() {
+ return (getModifiers() & Modifier.VARARGS) != 0;
+ }
+
+ /**
+ * Returns {@code true} if this constructor is a synthetic
+ * constructor; returns {@code false} otherwise.
+ *
+ * @return true if and only if this constructor is a synthetic
+ * constructor as defined by the Java Language Specification.
+ * @since 1.5
+ */
+ public boolean isSynthetic() {
+ return Modifier.isSynthetic(getModifiers());
+ }
+
+ // NOTE that there is no synchronization used here. It is correct
+ // (though not efficient) to generate more than one
+ // ConstructorAccessor for a given Constructor. However, avoiding
+ // synchronization will probably make the implementation more
+ // scalable.
+ private void acquireConstructorAccessor() {
+ // First check to see if one has been created yet, and take it
+ // if so.
+ ConstructorAccessor tmp = null;
+ if (root != null) tmp = root.getConstructorAccessor();
+ if (tmp != null) {
+ constructorAccessor = tmp;
+ return;
+ }
+ // Otherwise fabricate one and propagate it up to the root
+ tmp = reflectionFactory.newConstructorAccessor(this);
+ setConstructorAccessor(tmp);
+ }
+
+ // Returns ConstructorAccessor for this Constructor object, not
+ // looking up the chain to the root
+ ConstructorAccessor getConstructorAccessor() {
+ return constructorAccessor;
+ }
+
+ // Sets the ConstructorAccessor for this Constructor object and
+ // (recursively) its root
+ void setConstructorAccessor(ConstructorAccessor accessor) {
+ constructorAccessor = accessor;
+ // Propagate up
+ if (root != null) {
+ root.setConstructorAccessor(accessor);
+ }
+ }
+
+ int getSlot() {
+ return slot;
+ }
+
+ String getSignature() {
+ return signature;
+ }
+
+ byte[] getRawAnnotations() {
+ return annotations;
+ }
+
+ byte[] getRawParameterAnnotations() {
+ return parameterAnnotations;
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.5
+ */
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ if (annotationClass == null)
+ throw new NullPointerException();
+
+ return (T) declaredAnnotations().get(annotationClass);
+ }
+
+ private static final Annotation[] EMPTY_ANNOTATION_ARRAY=new Annotation[0];
+
+ /**
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations() {
+ return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY);
+ }
+
+ private transient Map<Class, Annotation> declaredAnnotations;
+
+ private synchronized Map<Class, Annotation> declaredAnnotations() {
+ if (declaredAnnotations == null) {
+ declaredAnnotations = AnnotationParser.parseAnnotations(
+ annotations, sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ getDeclaringClass());
+ }
+ return declaredAnnotations;
+ }
+
+ /**
+ * Returns an array of arrays that represent the annotations on the formal
+ * parameters, in declaration order, of the method represented by
+ * this {@code Constructor} object. (Returns an array of length zero if the
+ * underlying method is parameterless. If the method has one or more
+ * parameters, a nested array of length zero is returned for each parameter
+ * with no annotations.) The annotation objects contained in the returned
+ * arrays are serializable. The caller of this method is free to modify
+ * the returned arrays; it will have no effect on the arrays returned to
+ * other callers.
+ *
+ * @return an array of arrays that represent the annotations on the formal
+ * parameters, in declaration order, of the method represented by this
+ * Constructor object
+ * @since 1.5
+ */
+ public Annotation[][] getParameterAnnotations() {
+ int numParameters = parameterTypes.length;
+ if (parameterAnnotations == null)
+ return new Annotation[numParameters][0];
+
+ Annotation[][] result = AnnotationParser.parseParameterAnnotations(
+ parameterAnnotations,
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ getDeclaringClass());
+ if (result.length != numParameters) {
+ Class<?> declaringClass = getDeclaringClass();
+ if (declaringClass.isEnum() ||
+ declaringClass.isAnonymousClass() ||
+ declaringClass.isLocalClass() )
+ ; // Can't do reliable parameter counting
+ else {
+ if (!declaringClass.isMemberClass() || // top-level
+ // Check for the enclosing instance parameter for
+ // non-static member classes
+ (declaringClass.isMemberClass() &&
+ ((declaringClass.getModifiers() & Modifier.STATIC) == 0) &&
+ result.length + 1 != numParameters) ) {
+ throw new AnnotationFormatError(
+ "Parameter annotations don't match number of parameters");
+ }
+ }
+ }
+ return result;
+ }
+}