/* * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.lang.reflect; import sun.reflect.CallerSensitive; import sun.reflect.ConstructorAccessor; import sun.reflect.Reflection; import sun.reflect.annotation.TypeAnnotation; import sun.reflect.annotation.TypeAnnotationParser; 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.lang.annotation.AnnotationFormatError; /** * {@code Constructor} provides information about, and access to, a single * constructor for a class. * *

{@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 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 extends Executable { private Class 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; // Generics infrastructure // Accessor for factory private GenericsFactory getFactory() { // create scope and factory return CoreReflectionFactory.make(this, ConstructorScope.make(this)); } // Accessor for generic info repository @Override 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.) // // If this branching structure would ever contain cycles, deadlocks can // occur in annotation code. private Constructor root; /** * Used by Excecutable for annotation sharing. */ @Override Executable getRoot() { return 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 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 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.) if (this.root != null) throw new IllegalArgumentException("Can not copy a non-root Constructor"); Constructor res = new Constructor<>(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; } @Override boolean hasGenericInformation() { return (getSignature() != null); } @Override byte[] getAnnotationBytes() { return annotations; } /** * {@inheritDoc} */ @Override public Class getDeclaringClass() { return clazz; } /** * Returns the name of this constructor, as a string. This is * the binary name of the constructor's declaring class. */ @Override public String getName() { return getDeclaringClass().getName(); } /** * {@inheritDoc} */ @Override public int getModifiers() { return modifiers; } /** * {@inheritDoc} * @throws GenericSignatureFormatError {@inheritDoc} * @since 1.5 */ @Override @SuppressWarnings({"rawtypes", "unchecked"}) public TypeVariable>[] getTypeParameters() { if (getSignature() != null) { return (TypeVariable>[])getGenericInfo().getTypeParameters(); } else return (TypeVariable>[])new TypeVariable[0]; } /** * {@inheritDoc} */ @Override public Class[] getParameterTypes() { return parameterTypes.clone(); } /** * {@inheritDoc} * @since 1.8 */ public int getParameterCount() { return parameterTypes.length; } /** * {@inheritDoc} * @throws GenericSignatureFormatError {@inheritDoc} * @throws TypeNotPresentException {@inheritDoc} * @throws MalformedParameterizedTypeException {@inheritDoc} * @since 1.5 */ @Override public Type[] getGenericParameterTypes() { return super.getGenericParameterTypes(); } /** * {@inheritDoc} */ @Override public Class[] getExceptionTypes() { return exceptionTypes.clone(); } /** * {@inheritDoc} * @throws GenericSignatureFormatError {@inheritDoc} * @throws TypeNotPresentException {@inheritDoc} * @throws MalformedParameterizedTypeException {@inheritDoc} * @since 1.5 */ @Override public Type[] getGenericExceptionTypes() { return super.getGenericExceptionTypes(); } /** * 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()) { return equalParamTypes(parameterTypes, other.parameterTypes); } } 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: *

     *    public java.util.Hashtable(int,float)
     * 
* *

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} * @jls 8.8.3. Constructor Modifiers */ public String toString() { return sharedToString(Modifier.constructorModifiers(), false, parameterTypes, exceptionTypes); } @Override void specificToStringHeader(StringBuilder sb) { sb.append(getDeclaringClass().getTypeName()); } /** * 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 * "Type[]", it is denoted as * "Type...". * * 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. * *

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 * @jls 8.8.3. Constructor Modifiers */ @Override public String toGenericString() { return sharedToGenericString(Modifier.constructorModifiers(), false); } @Override void specificToGenericStringHeader(StringBuilder sb) { specificToStringHeader(sb); } /** * 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. * *

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. * *

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 section 15.9.3 of * The Java™ Language Specification. * *

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. * *

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 * is enforcing 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. */ @CallerSensitive public T newInstance(Object ... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class caller = Reflection.getCallerClass(); checkAccess(caller, clazz, null, modifiers); } } if ((clazz.getModifiers() & Modifier.ENUM) != 0) throw new IllegalArgumentException("Cannot reflectively create enum objects"); ConstructorAccessor ca = constructorAccessor; // read volatile if (ca == null) { ca = acquireConstructorAccessor(); } @SuppressWarnings("unchecked") T inst = (T) ca.newInstance(initargs); return inst; } /** * {@inheritDoc} * @since 1.5 */ @Override public boolean isVarArgs() { return super.isVarArgs(); } /** * {@inheritDoc} * @jls 13.1 The Form of a Binary * @since 1.5 */ @Override public boolean isSynthetic() { return super.isSynthetic(); } // 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 ConstructorAccessor 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; } else { // Otherwise fabricate one and propagate it up to the root tmp = reflectionFactory.newConstructorAccessor(this); setConstructorAccessor(tmp); } return 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; } /** * {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @since 1.5 */ public T getAnnotation(Class annotationClass) { return super.getAnnotation(annotationClass); } /** * {@inheritDoc} * @since 1.5 */ public Annotation[] getDeclaredAnnotations() { return super.getDeclaredAnnotations(); } /** * {@inheritDoc} * @since 1.5 */ @Override public Annotation[][] getParameterAnnotations() { return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations); } @Override void handleParameterNumberMismatch(int resultLength, int numParameters) { Class declaringClass = getDeclaringClass(); if (declaringClass.isEnum() || declaringClass.isAnonymousClass() || declaringClass.isLocalClass() ) return ; // 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) && resultLength + 1 != numParameters) ) { throw new AnnotationFormatError( "Parameter annotations don't match number of parameters"); } } } /** * {@inheritDoc} * @since 1.8 */ @Override public AnnotatedType getAnnotatedReturnType() { return getAnnotatedReturnType0(getDeclaringClass()); } /** * {@inheritDoc} * @since 1.8 */ @Override public AnnotatedType getAnnotatedReceiverType() { Class thisDeclClass = getDeclaringClass(); Class enclosingClass = thisDeclClass.getEnclosingClass(); if (enclosingClass == null) { // A Constructor for a top-level class return null; } Class outerDeclaringClass = thisDeclClass.getDeclaringClass(); if (outerDeclaringClass == null) { // A constructor for a local or anonymous class return null; } // Either static nested or inner class if (Modifier.isStatic(thisDeclClass.getModifiers())) { // static nested return null; } // A Constructor for an inner class return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), sun.misc.SharedSecrets.getJavaLangAccess(). getConstantPool(thisDeclClass), this, thisDeclClass, enclosingClass, TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); } }