Package java.lang.reflect

Source Code of java.lang.reflect.Constructor

/*
* @(#)Constructor.java  1.57 09/04/01
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/

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</code> provides information about, and access to, a single
* constructor for a class.
*
* <p><code>Constructor</code> permits widening conversions to occur when matching the
* actual parameters to newInstance() with the underlying
* constructor's formal parameters, but throws an
* <code>IllegalArgumentException</code> 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</code> object representing the class that declares
     * the constructor represented by this <code>Constructor</code> 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</code> object, as an integer. The
     * <code>Modifier</code> class should be used to decode the modifiers.
     *
     * @see Modifier
     */
    public int getModifiers() {
  return modifiers;
    }

    /**
     * Returns an array of <tt>TypeVariable</tt> objects that represent the
     * type variables declared by the generic declaration represented by this
     * <tt>GenericDeclaration</tt> object, in declaration order.  Returns an
     * array of length 0 if the underlying generic declaration declares no type
     * variables.
     *
     * @return an array of <tt>TypeVariable</tt> 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</code> objects that represent the formal
     * parameter types, in declaration order, of the constructor
     * represented by this <code>Constructor</code> 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 <tt>Type</tt> objects that represent the formal
     * parameter types, in declaration order, of the method represented by
     * this <tt>Constructor</tt> 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 <tt>Type</tt> 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 <tt>Type</tt>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</code> objects that represent the types
     * of exceptions declared to be thrown by the underlying constructor
     * represented by this <code>Constructor</code> object.  Returns an array of
     * length 0 if the constructor declares no exceptions in its <code>throws</code> 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 <tt>Type</tt> objects that represent the
     * exceptions declared to be thrown by this <tt>Constructor</tt> object.
     * Returns an array of length 0 if the underlying method declares
     * no exceptions in its <tt>throws</tt> clause. 
     *
     * <p>If an exception type is a parameterized type, the <tt>Type</tt>
     * 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
     *     <tt>throws</tt> clause refers to a non-existent type declaration
     * @throws MalformedParameterizedTypeException if
     *     the underlying method's <tt>throws</tt> 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 > ))
        return result;
    else
        return getExceptionTypes();
      }

    /**
     * Compares this <code>Constructor</code> against the specified object.
     * Returns true if the objects are the same.  Two <code>Constructor</code> 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</code>. 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</code>.  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 <tt>public</tt>, <tt>protected</tt> or
     * <tt>private</tt>.  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</code>,
     * 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.  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 &quot;<tt>throws</tt>&quot; followed by a
     * comma-separated list of the thrown exception types.
     *
     * <p>The only possible modifiers for constructors are the access
     * modifiers <tt>public</tt>, <tt>protected</tt> or
     * <tt>private</tt>.  Only one of these may appear, or none if the
     * constructor has default (package) access.
     *
     * @return a string describing this <code>Constructor</code>,
     * 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) + " ");
      }
      Type[] typeparms = getTypeParameters();
      if (typeparms.length > 0) {
    boolean first = true;
    sb.append("<");
    for(Type typeparm: typeparms) {
        if (!first)
      sb.append(",");
        if (typeparm instanceof Class)
      sb.append(((Class)typeparm).getName());
        else
      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++) {
    sb.append((params[j] instanceof Class)?
        Field.getTypeName((Class)params[j]):
        (params[j].toString()) );
    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</code> 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</code> 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 <tt>float</tt>
     * 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</code> 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 <tt>true</tt> if this constructor was declared to take
     * a variable number of arguments; returns <tt>false</tt>
     * otherwise.
     *
     * @return <tt>true</tt> 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 <tt>true</tt> if this constructor is a synthetic
     * constructor; returns <tt>false</tt> 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);
    }

    /**
     * @since 1.5
     */
    public Annotation[] getDeclaredAnnotations()  {
        return AnnotationParser.toArray(declaredAnnotations());
    }

    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 <tt>Constructor</tt> 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;
    }
}
TOP

Related Classes of java.lang.reflect.Constructor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.