001/* java.lang.reflect.Constructor - reflection of Java constructors
002   Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.lang.reflect;
040
041import gnu.java.lang.ClassHelper;
042import gnu.java.lang.CPStringBuilder;
043
044import gnu.java.lang.reflect.MethodSignatureParser;
045
046import java.lang.annotation.Annotation;
047
048/**
049 * The Constructor class represents a constructor of a class. It also allows
050 * dynamic creation of an object, via reflection. Invocation on Constructor
051 * objects knows how to do widening conversions, but throws
052 * {@link IllegalArgumentException} if a narrowing conversion would be
053 * necessary. You can query for information on this Constructor regardless
054 * of location, but construction access may be limited by Java language
055 * access controls. If you can't do it in the compiler, you can't normally
056 * do it here either.<p>
057 *
058 * <B>Note:</B> This class returns and accepts types as Classes, even
059 * primitive types; there are Class types defined that represent each
060 * different primitive type.  They are <code>java.lang.Boolean.TYPE,
061 * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
062 * byte.class</code>, etc.  These are not to be confused with the
063 * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
064 * real classes.<p>
065 *
066 * Also note that this is not a serializable class.  It is entirely feasible
067 * to make it serializable using the Externalizable interface, but this is
068 * on Sun, not me.
069 *
070 * @author John Keiser
071 * @author Eric Blake <ebb9@email.byu.edu>
072 * @see Member
073 * @see Class
074 * @see java.lang.Class#getConstructor(Class[])
075 * @see java.lang.Class#getDeclaredConstructor(Class[])
076 * @see java.lang.Class#getConstructors()
077 * @see java.lang.Class#getDeclaredConstructors()
078 * @since 1.1
079 * @status updated to 1.4
080 */
081public final class Constructor<T>
082  extends AccessibleObject
083  implements GenericDeclaration, Member
084{
085  private static final int CONSTRUCTOR_MODIFIERS
086    = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
087
088  private MethodSignatureParser p;
089
090  VMConstructor cons;
091
092  /**
093   * This class is uninstantiable outside this package.
094   */
095  Constructor(VMConstructor cons)
096  {
097    this.cons = cons;
098    cons.cons = this;
099  }
100
101  private Constructor()
102  {
103  }
104
105  /**
106   * Gets the class that declared this constructor.
107   * @return the class that declared this member
108   */
109  public Class<T> getDeclaringClass()
110  {
111    // Inescapable as the VM layer is 1.4 based.
112    @SuppressWarnings("unchecked")
113      Class<T> declClass = (Class<T>) cons.getDeclaringClass();
114    return declClass;
115  }
116
117  /**
118   * Gets the name of this constructor (the non-qualified name of the class
119   * it was declared in).
120   * @return the name of this constructor
121   */
122  public String getName()
123  {
124    return cons.getDeclaringClass().getName();
125  }
126
127  /**
128   * Gets the modifiers this constructor uses.  Use the <code>Modifier</code>
129   * class to interpret the values. A constructor can only have a subset of the
130   * following modifiers: public, private, protected.
131   *
132   * @return an integer representing the modifiers to this Member
133   * @see Modifier
134   */
135  public int getModifiers()
136  {
137    return cons.getModifiersInternal() & CONSTRUCTOR_MODIFIERS;
138  }
139
140  /**
141   * Return true if this constructor is synthetic, false otherwise.
142   * A synthetic member is one which is created by the compiler,
143   * and which does not appear in the user's source code.
144   * @since 1.5
145   */
146  public boolean isSynthetic()
147  {
148    return (cons.getModifiersInternal() & Modifier.SYNTHETIC) != 0;
149  }
150
151  /**
152   * Return true if this is a varargs constructor, that is if
153   * the constructor takes a variable number of arguments.
154   * @since 1.5
155   */
156  public boolean isVarArgs()
157  {
158    return (cons.getModifiersInternal() & Modifier.VARARGS) != 0;
159  }
160
161  /**
162   * Get the parameter list for this constructor, in declaration order. If the
163   * constructor takes no parameters, returns a 0-length array (not null).
164   *
165   * @return a list of the types of the constructor's parameters
166   */
167  public Class<?>[] getParameterTypes()
168  {
169    return (Class<?>[]) cons.getParameterTypes();
170  }
171
172  /**
173   * Get the exception types this constructor says it throws, in no particular
174   * order. If the constructor has no throws clause, returns a 0-length array
175   * (not null).
176   *
177   * @return a list of the types in the constructor's throws clause
178   */
179  public Class<?>[] getExceptionTypes()
180  {
181    return (Class<?>[]) cons.getExceptionTypes();
182  }
183
184  /**
185   * Compare two objects to see if they are semantically equivalent.
186   * Two Constructors are semantically equivalent if they have the same
187   * declaring class and the same parameter list.  This ignores different
188   * exception clauses, but since you can't create a Method except through the
189   * VM, this is just the == relation.
190   *
191   * @param o the object to compare to
192   * @return <code>true</code> if they are equal; <code>false</code> if not.
193   */
194  public boolean equals(Object o)
195  {
196    return cons.equals(o);
197  }
198
199  /**
200   * Get the hash code for the Constructor. The Constructor hash code is the
201   * hash code of the declaring class's name.
202   *
203   * @return the hash code for the object
204   */
205  public int hashCode()
206  {
207    return getName().hashCode();
208  }
209
210  /**
211   * Get a String representation of the Constructor. A Constructor's String
212   * representation is "&lt;modifier&gt; &lt;classname&gt;(&lt;paramtypes&gt;)
213   * throws &lt;exceptions&gt;", where everything after ')' is omitted if
214   * there are no exceptions.<br> Example:
215   * <code>public java.io.FileInputStream(java.lang.Runnable)
216   * throws java.io.FileNotFoundException</code>
217   *
218   * @return the String representation of the Constructor
219   */
220  public String toString()
221  {
222    // 128 is a reasonable buffer initial size for constructor
223    CPStringBuilder sb = new CPStringBuilder(128);
224    Modifier.toString(getModifiers(), sb).append(' ');
225    sb.append(getDeclaringClass().getName()).append('(');
226    Class[] c = getParameterTypes();
227    if (c.length > 0)
228      {
229        sb.append(ClassHelper.getUserName(c[0]));
230        for (int i = 1; i < c.length; i++)
231          sb.append(',').append(ClassHelper.getUserName(c[i]));
232      }
233    sb.append(')');
234    c = getExceptionTypes();
235    if (c.length > 0)
236      {
237        sb.append(" throws ").append(c[0].getName());
238        for (int i = 1; i < c.length; i++)
239          sb.append(',').append(c[i].getName());
240      }
241    return sb.toString();
242  }
243
244  static <X extends GenericDeclaration>
245  void addTypeParameters(CPStringBuilder sb, TypeVariable<X>[] typeArgs)
246  {
247    if (typeArgs.length == 0)
248      return;
249    sb.append('<');
250    for (int i = 0; i < typeArgs.length; ++i)
251      {
252        if (i > 0)
253          sb.append(',');
254        sb.append(typeArgs[i]);
255      }
256    sb.append("> ");
257  }
258
259  public String toGenericString()
260  {
261    CPStringBuilder sb = new CPStringBuilder(128);
262    Modifier.toString(getModifiers(), sb).append(' ');
263    addTypeParameters(sb, getTypeParameters());
264    sb.append(getDeclaringClass().getName()).append('(');
265    Type[] types = getGenericParameterTypes();
266    if (types.length > 0)
267      {
268        sb.append(types[0]);
269        for (int i = 1; i < types.length; ++i)
270          sb.append(',').append(types[i]);
271      }
272    sb.append(')');
273    types = getGenericExceptionTypes();
274    if (types.length > 0)
275      {
276        sb.append(" throws ").append(types[0]);
277        for (int i = 1; i < types.length; i++)
278          sb.append(',').append(types[i]);
279      }
280    return sb.toString();
281  }
282
283  /**
284   * Create a new instance by invoking the constructor. Arguments are
285   * automatically unwrapped and widened, if needed.<p>
286   *
287   * If this class is abstract, you will get an
288   * <code>InstantiationException</code>. If the constructor takes 0
289   * arguments, you may use null or a 0-length array for <code>args</code>.<p>
290   *
291   * If this Constructor enforces access control, your runtime context is
292   * evaluated, and you may have an <code>IllegalAccessException</code> if
293   * you could not create this object in similar compiled code. If the class
294   * is uninitialized, you trigger class initialization, which may end in a
295   * <code>ExceptionInInitializerError</code>.<p>
296   *
297   * Then, the constructor is invoked. If it completes normally, the return
298   * value will be the new object. If it completes abruptly, the exception is
299   * wrapped in an <code>InvocationTargetException</code>.
300   *
301   * @param args the arguments to the constructor
302   * @return the newly created object
303   * @throws IllegalAccessException if the constructor could not normally be
304   *         called by the Java code (i.e. it is not public)
305   * @throws IllegalArgumentException if the number of arguments is incorrect;
306   *         or if the arguments types are wrong even with a widening
307   *         conversion
308   * @throws InstantiationException if the class is abstract
309   * @throws InvocationTargetException if the constructor throws an exception
310   * @throws ExceptionInInitializerError if construction triggered class
311   *         initialization, which then failed
312   */
313  public T newInstance(Object... args)
314    throws InstantiationException, IllegalAccessException,
315           InvocationTargetException
316  {
317    // Inescapable as the VM layer is 1.4 based.
318    @SuppressWarnings("unchecked")
319      T ins = (T) cons.construct(args);
320    return ins;
321  }
322
323  /**
324   * Returns an array of <code>TypeVariable</code> objects that represents
325   * the type variables declared by this constructor, in declaration order.
326   * An array of size zero is returned if this constructor has no type
327   * variables.
328   *
329   * @return the type variables associated with this constructor.
330   * @throws GenericSignatureFormatError if the generic signature does
331   *         not conform to the format specified in the Virtual Machine
332   *         specification, version 3.
333   * @since 1.5
334   */
335  public TypeVariable<Constructor<T>>[] getTypeParameters()
336  {
337    if (p == null)
338      {
339        String sig = cons.getSignature();
340        if (sig == null)
341          return new TypeVariable[0];
342        p = new MethodSignatureParser(this, sig);
343      }
344    return p.getTypeParameters();
345  }
346
347  /**
348   * Returns an array of <code>Type</code> objects that represents
349   * the exception types declared by this constructor, in declaration order.
350   * An array of size zero is returned if this constructor declares no
351   * exceptions.
352   *
353   * @return the exception types declared by this constructor.
354   * @throws GenericSignatureFormatError if the generic signature does
355   *         not conform to the format specified in the Virtual Machine
356   *         specification, version 3.
357   * @since 1.5
358   */
359  public Type[] getGenericExceptionTypes()
360  {
361    if (p == null)
362      {
363        String sig = cons.getSignature();
364        if (sig == null)
365          return getExceptionTypes();
366        p = new MethodSignatureParser(this, sig);
367      }
368    return p.getGenericExceptionTypes();
369  }
370
371  /**
372   * Returns an array of <code>Type</code> objects that represents
373   * the parameter list for this constructor, in declaration order.
374   * An array of size zero is returned if this constructor takes no
375   * parameters.
376   *
377   * @return a list of the types of the constructor's parameters
378   * @throws GenericSignatureFormatError if the generic signature does
379   *         not conform to the format specified in the Virtual Machine
380   *         specification, version 3.
381   * @since 1.5
382   */
383  public Type[] getGenericParameterTypes()
384  {
385    if (p == null)
386      {
387        String sig = cons.getSignature();
388        if (sig == null)
389          return getParameterTypes();
390        p = new MethodSignatureParser(this, sig);
391      }
392    return p.getGenericParameterTypes();
393  }
394
395  /**
396   * <p>
397   * Return an array of arrays representing the annotations on each
398   * of the constructor's parameters.  The outer array is aligned against
399   * the parameters of the constructors and is thus equal in length to
400   * the number of parameters (thus having a length zero if there are none).
401   * Each array element in the outer array contains an inner array which
402   * holds the annotations.  This array has a length of zero if the parameter
403   * has no annotations.
404   * </p>
405   * <p>
406   * The returned annotations are serialized.  Changing the annotations has
407   * no affect on the return value of future calls to this method.
408   * </p>
409   *
410   * @return an array of arrays which represents the annotations used on the
411   *         parameters of this constructor.  The order of the array elements
412   *         matches the declaration order of the parameters.
413   * @since 1.5
414   */
415  public Annotation[][] getParameterAnnotations()
416  {
417    return cons.getParameterAnnotations();
418  }
419
420  /**
421   * Returns the element's annotation for the specified annotation type,
422   * or <code>null</code> if no such annotation exists.
423   *
424   * @param annotationClass the type of annotation to look for.
425   * @return this element's annotation for the specified type, or
426   *         <code>null</code> if no such annotation exists.
427   * @throws NullPointerException if the annotation class is <code>null</code>.
428   */
429  public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
430  {
431    // Inescapable as the VM layer is 1.4 based.
432    @SuppressWarnings("unchecked")
433      T ann = (T) cons.getAnnotation(annotationClass);
434    return ann;
435  }
436
437  /**
438   * Returns all annotations directly defined by the element.  If there are
439   * no annotations directly associated with the element, then a zero-length
440   * array will be returned.  The returned array may be modified by the client
441   * code, but this will have no effect on the annotation content of this
442   * class, and hence no effect on the return value of this method for
443   * future callers.
444   *
445   * @return the annotations directly defined by the element.
446   * @since 1.5
447   */
448  public Annotation[] getDeclaredAnnotations()
449  {
450    return cons.getDeclaredAnnotations();
451  }
452
453}