rt/emul/mini/src/main/java/java/lang/reflect/Constructor.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 28 Sep 2013 12:03:59 +0200
branchjavac
changeset 1321 7a78a84ab583
parent 772 d382dacfd73f
child 1377 5e8f58b48380
permissions -rw-r--r--
Can use Constructor.newInstance with parameters
     1 /*
     2  * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.lang.reflect;
    27 
    28 import java.lang.annotation.Annotation;
    29 import static java.lang.reflect.Method.fromPrimitive;
    30 import static java.lang.reflect.Method.getAccess;
    31 import static java.lang.reflect.Method.getParameterTypes;
    32 import org.apidesign.bck2brwsr.core.JavaScriptBody;
    33 import org.apidesign.bck2brwsr.emul.reflect.TypeProvider;
    34 
    35 /**
    36  * {@code Constructor} provides information about, and access to, a single
    37  * constructor for a class.
    38  *
    39  * <p>{@code Constructor} permits widening conversions to occur when matching the
    40  * actual parameters to newInstance() with the underlying
    41  * constructor's formal parameters, but throws an
    42  * {@code IllegalArgumentException} if a narrowing conversion would occur.
    43  *
    44  * @param <T> the class in which the constructor is declared
    45  *
    46  * @see Member
    47  * @see java.lang.Class
    48  * @see java.lang.Class#getConstructors()
    49  * @see java.lang.Class#getConstructor(Class[])
    50  * @see java.lang.Class#getDeclaredConstructors()
    51  *
    52  * @author      Kenneth Russell
    53  * @author      Nakul Saraiya
    54  */
    55 public final
    56     class Constructor<T> extends AccessibleObject implements
    57                                                     GenericDeclaration,
    58                                                     Member {
    59 
    60     private final Class<T> clazz;
    61     private final Object data;
    62     private final String sig;
    63 
    64     /**
    65      * Package-private constructor used by ReflectAccess to enable
    66      * instantiation of these objects in Java code from the java.lang
    67      * package via sun.reflect.LangReflectAccess.
    68      */
    69     Constructor(Class<T> declaringClass, Object data, String sig)
    70     {
    71         this.clazz = declaringClass;
    72         this.data = data;
    73         this.sig = sig;
    74     }
    75 
    76     /**
    77      * Package-private routine (exposed to java.lang.Class via
    78      * ReflectAccess) which returns a copy of this Constructor. The copy's
    79      * "root" field points to this Constructor.
    80      */
    81     Constructor<T> copy() {
    82         return this;
    83     }
    84 
    85     /**
    86      * Returns the {@code Class} object representing the class that declares
    87      * the constructor represented by this {@code Constructor} object.
    88      */
    89     public Class<T> getDeclaringClass() {
    90         return clazz;
    91     }
    92 
    93     /**
    94      * Returns the name of this constructor, as a string.  This is
    95      * the binary name of the constructor's declaring class.
    96      */
    97     public String getName() {
    98         return getDeclaringClass().getName();
    99     }
   100 
   101     /**
   102      * Returns the Java language modifiers for the constructor
   103      * represented by this {@code Constructor} object, as an integer. The
   104      * {@code Modifier} class should be used to decode the modifiers.
   105      *
   106      * @see Modifier
   107      */
   108     public int getModifiers() {
   109         return getAccess(data);
   110     }
   111 
   112     /**
   113      * Returns an array of {@code TypeVariable} objects that represent the
   114      * type variables declared by the generic declaration represented by this
   115      * {@code GenericDeclaration} object, in declaration order.  Returns an
   116      * array of length 0 if the underlying generic declaration declares no type
   117      * variables.
   118      *
   119      * @return an array of {@code TypeVariable} objects that represent
   120      *     the type variables declared by this generic declaration
   121      * @throws GenericSignatureFormatError if the generic
   122      *     signature of this generic declaration does not conform to
   123      *     the format specified in
   124      *     <cite>The Java&trade; Virtual Machine Specification</cite>
   125      * @since 1.5
   126      */
   127     public TypeVariable<Constructor<T>>[] getTypeParameters() {
   128         return TypeProvider.getDefault().getTypeParameters(this);
   129     }
   130 
   131 
   132     /**
   133      * Returns an array of {@code Class} objects that represent the formal
   134      * parameter types, in declaration order, of the constructor
   135      * represented by this {@code Constructor} object.  Returns an array of
   136      * length 0 if the underlying constructor takes no parameters.
   137      *
   138      * @return the parameter types for the constructor this object
   139      * represents
   140      */
   141     public Class<?>[] getParameterTypes() {
   142         return Method.getParameterTypes(sig);
   143     }
   144 
   145 
   146     /**
   147      * Returns an array of {@code Type} objects that represent the formal
   148      * parameter types, in declaration order, of the method represented by
   149      * this {@code Constructor} object. Returns an array of length 0 if the
   150      * underlying method takes no parameters.
   151      *
   152      * <p>If a formal parameter type is a parameterized type,
   153      * the {@code Type} object returned for it must accurately reflect
   154      * the actual type parameters used in the source code.
   155      *
   156      * <p>If a formal parameter type is a type variable or a parameterized
   157      * type, it is created. Otherwise, it is resolved.
   158      *
   159      * @return an array of {@code Type}s that represent the formal
   160      *     parameter types of the underlying method, in declaration order
   161      * @throws GenericSignatureFormatError
   162      *     if the generic method signature does not conform to the format
   163      *     specified in
   164      *     <cite>The Java&trade; Virtual Machine Specification</cite>
   165      * @throws TypeNotPresentException if any of the parameter
   166      *     types of the underlying method refers to a non-existent type
   167      *     declaration
   168      * @throws MalformedParameterizedTypeException if any of
   169      *     the underlying method's parameter types refer to a parameterized
   170      *     type that cannot be instantiated for any reason
   171      * @since 1.5
   172      */
   173     public Type[] getGenericParameterTypes() {
   174         return TypeProvider.getDefault().getGenericParameterTypes(this);
   175     }
   176 
   177 
   178     /**
   179      * Returns an array of {@code Class} objects that represent the types
   180      * of exceptions declared to be thrown by the underlying constructor
   181      * represented by this {@code Constructor} object.  Returns an array of
   182      * length 0 if the constructor declares no exceptions in its {@code throws} clause.
   183      *
   184      * @return the exception types declared as being thrown by the
   185      * constructor this object represents
   186      */
   187     public Class<?>[] getExceptionTypes() {
   188         throw new UnsupportedOperationException();
   189     }
   190 
   191 
   192     /**
   193      * Returns an array of {@code Type} objects that represent the
   194      * exceptions declared to be thrown by this {@code Constructor} object.
   195      * Returns an array of length 0 if the underlying method declares
   196      * no exceptions in its {@code throws} clause.
   197      *
   198      * <p>If an exception type is a type variable or a parameterized
   199      * type, it is created. Otherwise, it is resolved.
   200      *
   201      * @return an array of Types that represent the exception types
   202      *     thrown by the underlying method
   203      * @throws GenericSignatureFormatError
   204      *     if the generic method signature does not conform to the format
   205      *     specified in
   206      *     <cite>The Java&trade; Virtual Machine Specification</cite>
   207      * @throws TypeNotPresentException if the underlying method's
   208      *     {@code throws} clause refers to a non-existent type declaration
   209      * @throws MalformedParameterizedTypeException if
   210      *     the underlying method's {@code throws} clause refers to a
   211      *     parameterized type that cannot be instantiated for any reason
   212      * @since 1.5
   213      */
   214       public Type[] getGenericExceptionTypes() {
   215           return TypeProvider.getDefault().getGenericExceptionTypes(this);
   216       }
   217 
   218     /**
   219      * Compares this {@code Constructor} against the specified object.
   220      * Returns true if the objects are the same.  Two {@code Constructor} objects are
   221      * the same if they were declared by the same class and have the
   222      * same formal parameter types.
   223      */
   224     public boolean equals(Object obj) {
   225         if (obj instanceof Constructor) {
   226             Constructor other = (Constructor)obj;
   227             return data == other.data;
   228         }
   229         return false;
   230     }
   231 
   232     /**
   233      * Returns a hashcode for this {@code Constructor}. The hashcode is
   234      * the same as the hashcode for the underlying constructor's
   235      * declaring class name.
   236      */
   237     public int hashCode() {
   238         return getDeclaringClass().getName().hashCode();
   239     }
   240 
   241     /**
   242      * Returns a string describing this {@code Constructor}.  The string is
   243      * formatted as the constructor access modifiers, if any,
   244      * followed by the fully-qualified name of the declaring class,
   245      * followed by a parenthesized, comma-separated list of the
   246      * constructor's formal parameter types.  For example:
   247      * <pre>
   248      *    public java.util.Hashtable(int,float)
   249      * </pre>
   250      *
   251      * <p>The only possible modifiers for constructors are the access
   252      * modifiers {@code public}, {@code protected} or
   253      * {@code private}.  Only one of these may appear, or none if the
   254      * constructor has default (package) access.
   255      */
   256     public String toString() {
   257         try {
   258             StringBuffer sb = new StringBuffer();
   259             int mod = getModifiers() & Modifier.constructorModifiers();
   260             if (mod != 0) {
   261                 sb.append(Modifier.toString(mod) + " ");
   262             }
   263             sb.append(Field.getTypeName(getDeclaringClass()));
   264             sb.append("(");
   265             Class<?>[] params = getParameterTypes(); // avoid clone
   266             for (int j = 0; j < params.length; j++) {
   267                 sb.append(Field.getTypeName(params[j]));
   268                 if (j < (params.length - 1))
   269                     sb.append(",");
   270             }
   271             sb.append(")");
   272             /*
   273             Class<?>[] exceptions = exceptionTypes; // avoid clone
   274             if (exceptions.length > 0) {
   275                 sb.append(" throws ");
   276                 for (int k = 0; k < exceptions.length; k++) {
   277                     sb.append(exceptions[k].getName());
   278                     if (k < (exceptions.length - 1))
   279                         sb.append(",");
   280                 }
   281             }
   282             */
   283             return sb.toString();
   284         } catch (Exception e) {
   285             return "<" + e + ">";
   286         }
   287     }
   288 
   289     /**
   290      * Returns a string describing this {@code Constructor},
   291      * including type parameters.  The string is formatted as the
   292      * constructor access modifiers, if any, followed by an
   293      * angle-bracketed comma separated list of the constructor's type
   294      * parameters, if any, followed by the fully-qualified name of the
   295      * declaring class, followed by a parenthesized, comma-separated
   296      * list of the constructor's generic formal parameter types.
   297      *
   298      * If this constructor was declared to take a variable number of
   299      * arguments, instead of denoting the last parameter as
   300      * "<tt><i>Type</i>[]</tt>", it is denoted as
   301      * "<tt><i>Type</i>...</tt>".
   302      *
   303      * A space is used to separate access modifiers from one another
   304      * and from the type parameters or return type.  If there are no
   305      * type parameters, the type parameter list is elided; if the type
   306      * parameter list is present, a space separates the list from the
   307      * class name.  If the constructor is declared to throw
   308      * exceptions, the parameter list is followed by a space, followed
   309      * by the word "{@code throws}" followed by a
   310      * comma-separated list of the thrown exception types.
   311      *
   312      * <p>The only possible modifiers for constructors are the access
   313      * modifiers {@code public}, {@code protected} or
   314      * {@code private}.  Only one of these may appear, or none if the
   315      * constructor has default (package) access.
   316      *
   317      * @return a string describing this {@code Constructor},
   318      * include type parameters
   319      *
   320      * @since 1.5
   321      */
   322     public String toGenericString() {
   323         try {
   324             StringBuilder sb = new StringBuilder();
   325             int mod = getModifiers() & Modifier.constructorModifiers();
   326             if (mod != 0) {
   327                 sb.append(Modifier.toString(mod) + " ");
   328             }
   329             TypeVariable<?>[] typeparms = getTypeParameters();
   330             if (typeparms.length > 0) {
   331                 boolean first = true;
   332                 sb.append("<");
   333                 for(TypeVariable<?> typeparm: typeparms) {
   334                     if (!first)
   335                         sb.append(",");
   336                     // Class objects can't occur here; no need to test
   337                     // and call Class.getName().
   338                     sb.append(typeparm.toString());
   339                     first = false;
   340                 }
   341                 sb.append("> ");
   342             }
   343             sb.append(Field.getTypeName(getDeclaringClass()));
   344             sb.append("(");
   345             Type[] params = getGenericParameterTypes();
   346             for (int j = 0; j < params.length; j++) {
   347                 String param = (params[j] instanceof Class<?>)?
   348                     Field.getTypeName((Class<?>)params[j]):
   349                     (params[j].toString());
   350                 if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
   351                     param = param.replaceFirst("\\[\\]$", "...");
   352                 sb.append(param);
   353                 if (j < (params.length - 1))
   354                     sb.append(",");
   355             }
   356             sb.append(")");
   357             Type[] exceptions = getGenericExceptionTypes();
   358             if (exceptions.length > 0) {
   359                 sb.append(" throws ");
   360                 for (int k = 0; k < exceptions.length; k++) {
   361                     sb.append((exceptions[k] instanceof Class)?
   362                               ((Class<?>)exceptions[k]).getName():
   363                               exceptions[k].toString());
   364                     if (k < (exceptions.length - 1))
   365                         sb.append(",");
   366                 }
   367             }
   368             return sb.toString();
   369         } catch (Exception e) {
   370             return "<" + e + ">";
   371         }
   372     }
   373 
   374     /**
   375      * Uses the constructor represented by this {@code Constructor} object to
   376      * create and initialize a new instance of the constructor's
   377      * declaring class, with the specified initialization parameters.
   378      * Individual parameters are automatically unwrapped to match
   379      * primitive formal parameters, and both primitive and reference
   380      * parameters are subject to method invocation conversions as necessary.
   381      *
   382      * <p>If the number of formal parameters required by the underlying constructor
   383      * is 0, the supplied {@code initargs} array may be of length 0 or null.
   384      *
   385      * <p>If the constructor's declaring class is an inner class in a
   386      * non-static context, the first argument to the constructor needs
   387      * to be the enclosing instance; see section 15.9.3 of
   388      * <cite>The Java&trade; Language Specification</cite>.
   389      *
   390      * <p>If the required access and argument checks succeed and the
   391      * instantiation will proceed, the constructor's declaring class
   392      * is initialized if it has not already been initialized.
   393      *
   394      * <p>If the constructor completes normally, returns the newly
   395      * created and initialized instance.
   396      *
   397      * @param initargs array of objects to be passed as arguments to
   398      * the constructor call; values of primitive types are wrapped in
   399      * a wrapper object of the appropriate type (e.g. a {@code float}
   400      * in a {@link java.lang.Float Float})
   401      *
   402      * @return a new object created by calling the constructor
   403      * this object represents
   404      *
   405      * @exception IllegalAccessException    if this {@code Constructor} object
   406      *              is enforcing Java language access control and the underlying
   407      *              constructor is inaccessible.
   408      * @exception IllegalArgumentException  if the number of actual
   409      *              and formal parameters differ; if an unwrapping
   410      *              conversion for primitive arguments fails; or if,
   411      *              after possible unwrapping, a parameter value
   412      *              cannot be converted to the corresponding formal
   413      *              parameter type by a method invocation conversion; if
   414      *              this constructor pertains to an enum type.
   415      * @exception InstantiationException    if the class that declares the
   416      *              underlying constructor represents an abstract class.
   417      * @exception InvocationTargetException if the underlying constructor
   418      *              throws an exception.
   419      * @exception ExceptionInInitializerError if the initialization provoked
   420      *              by this method fails.
   421      */
   422     public T newInstance(Object ... initargs)
   423         throws InstantiationException, IllegalAccessException,
   424                IllegalArgumentException, InvocationTargetException
   425     {
   426         Class[] types = getParameterTypes();
   427         if (types.length != initargs.length) {
   428             throw new IllegalArgumentException("Types len " + types.length + " args: " + initargs.length);
   429         } else {
   430             initargs = initargs.clone();
   431             for (int i = 0; i < types.length; i++) {
   432                 Class c = types[i];
   433                 if (c.isPrimitive() && initargs[i] != null) {
   434                     initargs[i] = Method.toPrimitive(initargs[i]);
   435                 }
   436             }
   437         }
   438         return (T) newInstance0(this.getDeclaringClass(), "cons__" + sig, initargs);
   439     }
   440 
   441     @JavaScriptBody(args = { "self", "sig", "args" }, body =
   442           "\nvar c = self.cnstr;"
   443         + "\nvar inst = c();"
   444         + "\nc[sig].apply(inst, args);"
   445         + "\nreturn inst;"
   446     )
   447     private static native Object newInstance0(Class<?> self, String sig, Object[] args);
   448     
   449     /**
   450      * Returns {@code true} if this constructor was declared to take
   451      * a variable number of arguments; returns {@code false}
   452      * otherwise.
   453      *
   454      * @return {@code true} if an only if this constructor was declared to
   455      * take a variable number of arguments.
   456      * @since 1.5
   457      */
   458     public boolean isVarArgs() {
   459         return (getModifiers() & Modifier.VARARGS) != 0;
   460     }
   461 
   462     /**
   463      * Returns {@code true} if this constructor is a synthetic
   464      * constructor; returns {@code false} otherwise.
   465      *
   466      * @return true if and only if this constructor is a synthetic
   467      * constructor as defined by
   468      * <cite>The Java&trade; Language Specification</cite>.
   469      * @since 1.5
   470      */
   471     public boolean isSynthetic() {
   472         return Modifier.isSynthetic(getModifiers());
   473     }
   474 
   475     /**
   476      * @throws NullPointerException {@inheritDoc}
   477      * @since 1.5
   478      */
   479     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
   480         if (annotationClass == null)
   481             throw new NullPointerException();
   482 
   483         return null; // XXX (T) declaredAnnotations().get(annotationClass);
   484     }
   485 
   486     /**
   487      * @since 1.5
   488      */
   489     public Annotation[] getDeclaredAnnotations()  {
   490         return new Annotation[0]; // XXX AnnotationParser.toArray(declaredAnnotations());
   491     }
   492 
   493     /**
   494      * Returns an array of arrays that represent the annotations on the formal
   495      * parameters, in declaration order, of the method represented by
   496      * this {@code Constructor} object. (Returns an array of length zero if the
   497      * underlying method is parameterless.  If the method has one or more
   498      * parameters, a nested array of length zero is returned for each parameter
   499      * with no annotations.) The annotation objects contained in the returned
   500      * arrays are serializable.  The caller of this method is free to modify
   501      * the returned arrays; it will have no effect on the arrays returned to
   502      * other callers.
   503      *
   504      * @return an array of arrays that represent the annotations on the formal
   505      *    parameters, in declaration order, of the method represented by this
   506      *    Constructor object
   507      * @since 1.5
   508      */
   509     public Annotation[][] getParameterAnnotations() {
   510 //        int numParameters = parameterTypes.length;
   511 //        if (parameterAnnotations == null)
   512 //            return new Annotation[numParameters][0];
   513         
   514         return new Annotation[0][0]; // XXX
   515 /*
   516         Annotation[][] result = AnnotationParser.parseParameterAnnotations(
   517             parameterAnnotations,
   518             sun.misc.SharedSecrets.getJavaLangAccess().
   519                 getConstantPool(getDeclaringClass()),
   520             getDeclaringClass());
   521         if (result.length != numParameters) {
   522             Class<?> declaringClass = getDeclaringClass();
   523             if (declaringClass.isEnum() ||
   524                 declaringClass.isAnonymousClass() ||
   525                 declaringClass.isLocalClass() )
   526                 ; // Can't do reliable parameter counting
   527             else {
   528                 if (!declaringClass.isMemberClass() || // top-level
   529                     // Check for the enclosing instance parameter for
   530                     // non-static member classes
   531                     (declaringClass.isMemberClass() &&
   532                      ((declaringClass.getModifiers() & Modifier.STATIC) == 0)  &&
   533                      result.length + 1 != numParameters) ) {
   534                     throw new AnnotationFormatError(
   535                               "Parameter annotations don't match number of parameters");
   536                 }
   537             }
   538         }
   539         return result;
   540         */
   541     }
   542 }