KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > lang > reflect > Constructor


1 /*
2  * @(#)Constructor.java 1.49 04/05/04
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.lang.reflect;
9
10 import sun.reflect.ConstructorAccessor;
11 import sun.reflect.Reflection;
12 import sun.reflect.generics.repository.ConstructorRepository;
13 import sun.reflect.generics.factory.CoreReflectionFactory;
14 import sun.reflect.generics.factory.GenericsFactory;
15 import sun.reflect.generics.scope.ConstructorScope;
16 import java.lang.annotation.Annotation JavaDoc;
17 import java.util.Map JavaDoc;
18 import sun.reflect.annotation.AnnotationParser;
19
20
21 /**
22  * <code>Constructor</code> provides information about, and access to, a single
23  * constructor for a class.
24  *
25  * <p><code>Constructor</code> permits widening conversions to occur when matching the
26  * actual parameters to newInstance() with the underlying
27  * constructor's formal parameters, but throws an
28  * <code>IllegalArgumentException</code> if a narrowing conversion would occur.
29  *
30  * @see Member
31  * @see java.lang.Class
32  * @see java.lang.Class#getConstructors()
33  * @see java.lang.Class#getConstructor(Class[])
34  * @see java.lang.Class#getDeclaredConstructors()
35  *
36  * @author Kenneth Russell
37  * @author Nakul Saraiya
38  */

39 public final
40     class Constructor<T> extends AccessibleObject JavaDoc implements
41                                                     GenericDeclaration JavaDoc,
42                                                     Member JavaDoc {
43
44     private Class JavaDoc<T> clazz;
45     private int slot;
46     private Class JavaDoc[] parameterTypes;
47     private Class JavaDoc[] exceptionTypes;
48     private int modifiers;
49     // Generics and annotations support
50
private transient String JavaDoc signature;
51     // generic info repository; lazily initialized
52
private transient ConstructorRepository genericInfo;
53     private byte[] annotations;
54     private byte[] parameterAnnotations;
55
56
57     // Generics infrastructure
58
// Accessor for factory
59
private GenericsFactory getFactory() {
60     // create scope and factory
61
return CoreReflectionFactory.make(this, ConstructorScope.make(this));
62     }
63
64     // Accessor for generic info repository
65
private ConstructorRepository getGenericInfo() {
66     // lazily initialize repository if necessary
67
if (genericInfo == null) {
68         // create and cache generic info repository
69
genericInfo =
70         ConstructorRepository.make(getSignature(),
71                        getFactory());
72     }
73     return genericInfo; //return cached repository
74
}
75
76     private volatile ConstructorAccessor constructorAccessor;
77     // For sharing of ConstructorAccessors. This branching structure
78
// is currently only two levels deep (i.e., one root Constructor
79
// and potentially many Constructor objects pointing to it.)
80
private Constructor JavaDoc<T> root;
81
82     /**
83      * Package-private constructor used by ReflectAccess to enable
84      * instantiation of these objects in Java code from the java.lang
85      * package via sun.reflect.LangReflectAccess.
86      */

87     Constructor(Class JavaDoc<T> declaringClass,
88                 Class JavaDoc[] parameterTypes,
89                 Class JavaDoc[] checkedExceptions,
90                 int modifiers,
91                 int slot,
92                 String JavaDoc signature,
93                 byte[] annotations,
94                 byte[] parameterAnnotations)
95     {
96         this.clazz = declaringClass;
97         this.parameterTypes = parameterTypes;
98         this.exceptionTypes = checkedExceptions;
99         this.modifiers = modifiers;
100         this.slot = slot;
101         this.signature = signature;
102         this.annotations = annotations;
103         this.parameterAnnotations = parameterAnnotations;
104     }
105
106     /**
107      * Package-private routine (exposed to java.lang.Class via
108      * ReflectAccess) which returns a copy of this Constructor. The copy's
109      * "root" field points to this Constructor.
110      */

111     Constructor JavaDoc<T> copy() {
112         // This routine enables sharing of ConstructorAccessor objects
113
// among Constructor objects which refer to the same underlying
114
// method in the VM. (All of this contortion is only necessary
115
// because of the "accessibility" bit in AccessibleObject,
116
// which implicitly requires that new java.lang.reflect
117
// objects be fabricated for each reflective call on Class
118
// objects.)
119
Constructor JavaDoc<T> res = new Constructor JavaDoc<T>(clazz,
120                         parameterTypes,
121                         exceptionTypes, modifiers, slot,
122                                                 signature,
123                                                 annotations,
124                                                 parameterAnnotations);
125         res.root = this;
126         // Might as well eagerly propagate this if already present
127
res.constructorAccessor = constructorAccessor;
128         return res;
129     }
130
131     /**
132      * Returns the <code>Class</code> object representing the class that declares
133      * the constructor represented by this <code>Constructor</code> object.
134      */

135     public Class JavaDoc<T> getDeclaringClass() {
136     return clazz;
137     }
138
139     /**
140      * Returns the name of this constructor, as a string. This is
141      * always the same as the simple name of the constructor's declaring
142      * class.
143      */

144     public String JavaDoc getName() {
145     return getDeclaringClass().getName();
146     }
147
148     /**
149      * Returns the Java language modifiers for the constructor
150      * represented by this <code>Constructor</code> object, as an integer. The
151      * <code>Modifier</code> class should be used to decode the modifiers.
152      *
153      * @see Modifier
154      */

155     public int getModifiers() {
156     return modifiers;
157     }
158
159     /**
160      * Returns an array of <tt>TypeVariable</tt> objects that represent the
161      * type variables declared by the generic declaration represented by this
162      * <tt>GenericDeclaration</tt> object, in declaration order. Returns an
163      * array of length 0 if the underlying generic declaration declares no type
164      * variables.
165      *
166      * @return an array of <tt>TypeVariable</tt> objects that represent
167      * the type variables declared by this generic declaration
168      * @throws GenericSignatureFormatError if the generic
169      * signature of this generic declaration does not conform to
170      * the format specified in the Java Virtual Machine Specification,
171      * 3rd edition
172      * @since 1.5
173      */

174     public TypeVariable JavaDoc<Constructor JavaDoc<T>>[] getTypeParameters() {
175       if (getSignature() != null) {
176     return (TypeVariable JavaDoc<Constructor JavaDoc<T>>[])getGenericInfo().getTypeParameters();
177       } else
178           return (TypeVariable JavaDoc<Constructor JavaDoc<T>>[])new TypeVariable JavaDoc[0];
179     }
180
181
182     /**
183      * Returns an array of <code>Class</code> objects that represent the formal
184      * parameter types, in declaration order, of the constructor
185      * represented by this <code>Constructor</code> object. Returns an array of
186      * length 0 if the underlying constructor takes no parameters.
187      *
188      * @return the parameter types for the constructor this object
189      * represents
190      */

191     public Class JavaDoc<?>[] getParameterTypes() {
192     return (Class JavaDoc<?>[]) parameterTypes.clone();
193     }
194
195
196     /**
197      * Returns an array of <tt>Type</tt> objects that represent the formal
198      * parameter types, in declaration order, of the method represented by
199      * this <tt>Constructor</tt> object. Returns an array of length 0 if the
200      * underlying method takes no parameters.
201      *
202      * <p>If a formal parameter type is a parameterized type,
203      * the <tt>Type</tt> object returned for it must accurately reflect
204      * the actual type parameters used in the source code.
205      *
206      * <p>If a formal parameter type is a type variable or a parameterized
207      * type, it is created. Otherwise, it is resolved.
208      *
209      * @return an array of <tt>Type</tt>s that represent the formal
210      * parameter types of the underlying method, in declaration order
211      * @throws GenericSignatureFormatError
212      * if the generic method signature does not conform to the format
213      * specified in the Java Virtual Machine Specification, 3rd edition
214      * @throws TypeNotPresentException if any of the parameter
215      * types of the underlying method refers to a non-existent type
216      * declaration
217      * @throws MalformedParameterizedTypeException if any of
218      * the underlying method's parameter types refer to a parameterized
219      * type that cannot be instantiated for any reason
220      * @since 1.5
221      */

222     public Type JavaDoc[] getGenericParameterTypes() {
223     if (getSignature() != null)
224         return getGenericInfo().getParameterTypes();
225     else
226         return getParameterTypes();
227     }
228
229
230     /**
231      * Returns an array of <code>Class</code> objects that represent the types
232      * of exceptions declared to be thrown by the underlying constructor
233      * represented by this <code>Constructor</code> object. Returns an array of
234      * length 0 if the constructor declares no exceptions in its <code>throws</code> clause.
235      *
236      * @return the exception types declared as being thrown by the
237      * constructor this object represents
238      */

239     public Class JavaDoc<?>[] getExceptionTypes() {
240     return (Class JavaDoc<?>[])exceptionTypes.clone();
241     }
242
243
244     /**
245      * Returns an array of <tt>Type</tt> objects that represent the
246      * exceptions declared to be thrown by this <tt>Constructor</tt> object.
247      * Returns an array of length 0 if the underlying method declares
248      * no exceptions in its <tt>throws</tt> clause.
249      *
250      * <p>If an exception type is a parameterized type, the <tt>Type</tt>
251      * object returned for it must accurately reflect the actual type
252      * parameters used in the source code.
253      *
254      * <p>If an exception type is a type variable or a parameterized
255      * type, it is created. Otherwise, it is resolved.
256      *
257      * @return an array of Types that represent the exception types
258      * thrown by the underlying method
259      * @throws GenericSignatureFormatError
260      * if the generic method signature does not conform to the format
261      * specified in the Java Virtual Machine Specification, 3rd edition
262      * @throws TypeNotPresentException if the underlying method's
263      * <tt>throws</tt> clause refers to a non-existent type declaration
264      * @throws MalformedParameterizedTypeException if
265      * the underlying method's <tt>throws</tt> clause refers to a
266      * parameterized type that cannot be instantiated for any reason
267      * @since 1.5
268      */

269       public Type JavaDoc[] getGenericExceptionTypes() {
270       Type JavaDoc[] result;
271       if (getSignature() != null &&
272           ( (result = getGenericInfo().getExceptionTypes()).length > 0 ))
273           return result;
274       else
275           return getExceptionTypes();
276       }
277
278     /**
279      * Compares this <code>Constructor</code> against the specified object.
280      * Returns true if the objects are the same. Two <code>Constructor</code> objects are
281      * the same if they were declared by the same class and have the
282      * same formal parameter types.
283      */

284     public boolean equals(Object JavaDoc obj) {
285     if (obj != null && obj instanceof Constructor JavaDoc) {
286         Constructor JavaDoc other = (Constructor JavaDoc)obj;
287         if (getDeclaringClass() == other.getDeclaringClass()) {
288         /* Avoid unnecessary cloning */
289         Class JavaDoc[] params1 = parameterTypes;
290         Class JavaDoc[] params2 = other.parameterTypes;
291         if (params1.length == params2.length) {
292             for (int i = 0; i < params1.length; i++) {
293             if (params1[i] != params2[i])
294                 return false;
295             }
296             return true;
297         }
298         }
299     }
300     return false;
301     }
302
303     /**
304      * Returns a hashcode for this <code>Constructor</code>. The hashcode is
305      * the same as the hashcode for the underlying constructor's
306      * declaring class name.
307      */

308     public int hashCode() {
309     return getDeclaringClass().getName().hashCode();
310     }
311
312     /**
313      * Returns a string describing this <code>Constructor</code>. The string is
314      * formatted as the constructor access modifiers, if any,
315      * followed by the fully-qualified name of the declaring class,
316      * followed by a parenthesized, comma-separated list of the
317      * constructor's formal parameter types. For example:
318      * <pre>
319      * public java.util.Hashtable(int,float)
320      * </pre>
321      *
322      * <p>The only possible modifiers for constructors are the access
323      * modifiers <tt>public</tt>, <tt>protected</tt> or
324      * <tt>private</tt>. Only one of these may appear, or none if the
325      * constructor has default (package) access.
326      */

327     public String JavaDoc toString() {
328     try {
329         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
330         int mod = getModifiers();
331         if (mod != 0) {
332         sb.append(Modifier.toString(mod) + " ");
333         }
334         sb.append(Field.getTypeName(getDeclaringClass()));
335         sb.append("(");
336         Class JavaDoc[] params = parameterTypes; // avoid clone
337
for (int j = 0; j < params.length; j++) {
338         sb.append(Field.getTypeName(params[j]));
339         if (j < (params.length - 1))
340             sb.append(",");
341         }
342         sb.append(")");
343         Class JavaDoc[] exceptions = exceptionTypes; // avoid clone
344
if (exceptions.length > 0) {
345         sb.append(" throws ");
346         for (int k = 0; k < exceptions.length; k++) {
347             sb.append(exceptions[k].getName());
348             if (k < (exceptions.length - 1))
349             sb.append(",");
350         }
351         }
352         return sb.toString();
353     } catch (Exception JavaDoc e) {
354         return "<" + e + ">";
355     }
356     }
357
358     /**
359      * Returns a string describing this <code>Constructor</code>,
360      * including type parameters. The string is formatted as the
361      * constructor access modifiers, if any, followed by an
362      * angle-bracketed comma separated list of the constructor's type
363      * parameters, if any, followed by the fully-qualified name of the
364      * declaring class, followed by a parenthesized, comma-separated
365      * list of the constructor's generic formal parameter types. A
366      * space is used to separate access modifiers from one another and
367      * from the type parameters or return type. If there are no type
368      * parameters, the type parameter list is elided; if the type
369      * parameter list is present, a space separates the list from the
370      * class name. If the constructor is declared to throw
371      * exceptions, the parameter list is followed by a space, followed
372      * by the word &quot;<tt>throws</tt>&quot; followed by a
373      * comma-separated list of the thrown exception types.
374      *
375      * <p>The only possible modifiers for constructors are the access
376      * modifiers <tt>public</tt>, <tt>protected</tt> or
377      * <tt>private</tt>. Only one of these may appear, or none if the
378      * constructor has default (package) access.
379      *
380      * @return a string describing this <code>Constructor</code>,
381      * include type parameters
382      *
383      * @since 1.5
384      */

385     public String JavaDoc toGenericString() {
386     try {
387         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
388         int mod = getModifiers();
389         if (mod != 0) {
390         sb.append(Modifier.toString(mod) + " ");
391         }
392         Type JavaDoc[] typeparms = getTypeParameters();
393         if (typeparms.length > 0) {
394         boolean first = true;
395         sb.append("<");
396         for(Type JavaDoc typeparm: typeparms) {
397             if (!first)
398             sb.append(",");
399             if (typeparm instanceof Class JavaDoc)
400             sb.append(((Class JavaDoc)typeparm).getName());
401             else
402             sb.append(typeparm.toString());
403             first = false;
404         }
405         sb.append("> ");
406         }
407         sb.append(Field.getTypeName(getDeclaringClass()));
408         sb.append("(");
409         Type JavaDoc[] params = getGenericParameterTypes();
410         for (int j = 0; j < params.length; j++) {
411         sb.append((params[j] instanceof Class JavaDoc)?
412               Field.getTypeName((Class JavaDoc)params[j]):
413               (params[j].toString()) );
414         if (j < (params.length - 1))
415             sb.append(",");
416         }
417         sb.append(")");
418         Type JavaDoc[] exceptions = getGenericExceptionTypes();
419         if (exceptions.length > 0) {
420         sb.append(" throws ");
421         for (int k = 0; k < exceptions.length; k++) {
422             sb.append((exceptions[k] instanceof Class JavaDoc)?
423                   ((Class JavaDoc)exceptions[k]).getName():
424                   exceptions[k].toString());
425             if (k < (exceptions.length - 1))
426             sb.append(",");
427         }
428         }
429         return sb.toString();
430     } catch (Exception JavaDoc e) {
431         return "<" + e + ">";
432     }
433     }
434
435     /**
436      * Uses the constructor represented by this <code>Constructor</code> object to
437      * create and initialize a new instance of the constructor's
438      * declaring class, with the specified initialization parameters.
439      * Individual parameters are automatically unwrapped to match
440      * primitive formal parameters, and both primitive and reference
441      * parameters are subject to method invocation conversions as necessary.
442      *
443      * <p>If the number of formal parameters required by the underlying constructor
444      * is 0, the supplied <code>initargs</code> array may be of length 0 or null.
445      *
446      * <p>If the required access and argument checks succeed and the
447      * instantiation will proceed, the constructor's declaring class
448      * is initialized if it has not already been initialized.
449      *
450      * <p>If the constructor completes normally, returns the newly
451      * created and initialized instance.
452      *
453      * @param initargs array of objects to be passed as arguments to
454      * the constructor call; values of primitive types are wrapped in
455      * a wrapper object of the appropriate type (e.g. a <tt>float</tt>
456      * in a {@link java.lang.Float Float})
457      *
458      * @return a new object created by calling the constructor
459      * this object represents
460      *
461      * @exception IllegalAccessException if this <code>Constructor</code> object
462      * enforces Java language access control and the underlying
463      * constructor is inaccessible.
464      * @exception IllegalArgumentException if the number of actual
465      * and formal parameters differ; if an unwrapping
466      * conversion for primitive arguments fails; or if,
467      * after possible unwrapping, a parameter value
468      * cannot be converted to the corresponding formal
469      * parameter type by a method invocation conversion; if
470      * this constructor pertains to an enum type.
471      * @exception InstantiationException if the class that declares the
472      * underlying constructor represents an abstract class.
473      * @exception InvocationTargetException if the underlying constructor
474      * throws an exception.
475      * @exception ExceptionInInitializerError if the initialization provoked
476      * by this method fails.
477      */

478     public T newInstance(Object JavaDoc ... initargs)
479     throws InstantiationException JavaDoc, IllegalAccessException JavaDoc,
480                IllegalArgumentException JavaDoc, InvocationTargetException JavaDoc
481     {
482         if (!override) {
483             if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
484                 Class JavaDoc caller = Reflection.getCallerClass(2);
485                 if (securityCheckCache != caller) {
486                     Reflection.ensureMemberAccess(caller, clazz, null, modifiers);
487                     securityCheckCache = caller;
488                 }
489             }
490         }
491     if ((clazz.getModifiers() & Modifier.ENUM) != 0)
492         throw new IllegalArgumentException JavaDoc("Cannot reflectively create enum objects");
493         if (constructorAccessor == null) acquireConstructorAccessor();
494         return (T) constructorAccessor.newInstance(initargs);
495     }
496
497     /**
498      * Returns <tt>true</tt> if this constructor was declared to take
499      * a variable number of arguments; returns <tt>false</tt>
500      * otherwise.
501      *
502      * @return <tt>true</tt> if an only if this constructor was declared to
503      * take a variable number of arguments.
504      * @since 1.5
505      */

506     public boolean isVarArgs() {
507         return (getModifiers() & Modifier.VARARGS) != 0;
508     }
509
510     /**
511      * Returns <tt>true</tt> if this constructor is a synthetic
512      * constructor; returns <tt>false</tt> otherwise.
513      *
514      * @return true if and only if this constructor is a synthetic
515      * constructor as defined by the Java Language Specification.
516      * @since 1.5
517      */

518     public boolean isSynthetic() {
519         return Modifier.isSynthetic(getModifiers());
520     }
521
522     // NOTE that there is no synchronization used here. It is correct
523
// (though not efficient) to generate more than one
524
// ConstructorAccessor for a given Constructor. However, avoiding
525
// synchronization will probably make the implementation more
526
// scalable.
527
private void acquireConstructorAccessor() {
528         // First check to see if one has been created yet, and take it
529
// if so.
530
ConstructorAccessor tmp = null;
531         if (root != null) tmp = root.getConstructorAccessor();
532         if (tmp != null) {
533             constructorAccessor = tmp;
534             return;
535         }
536         // Otherwise fabricate one and propagate it up to the root
537
tmp = reflectionFactory.newConstructorAccessor(this);
538         setConstructorAccessor(tmp);
539     }
540
541     // Returns ConstructorAccessor for this Constructor object, not
542
// looking up the chain to the root
543
ConstructorAccessor getConstructorAccessor() {
544         return constructorAccessor;
545     }
546
547     // Sets the ConstructorAccessor for this Constructor object and
548
// (recursively) its root
549
void setConstructorAccessor(ConstructorAccessor accessor) {
550         constructorAccessor = accessor;
551         // Propagate up
552
if (root != null) {
553             root.setConstructorAccessor(accessor);
554         }
555     }
556
557     int getSlot() {
558         return slot;
559     }
560
561    String JavaDoc getSignature() {
562         return signature;
563    }
564
565     byte[] getRawAnnotations() {
566         return annotations;
567     }
568
569     byte[] getRawParameterAnnotations() {
570         return parameterAnnotations;
571     }
572
573     public <T extends Annotation JavaDoc> T getAnnotation(Class JavaDoc<T> annotationClass) {
574         if (annotationClass == null)
575             throw new NullPointerException JavaDoc();
576
577         return (T) declaredAnnotations().get(annotationClass);
578     }
579
580     private static final Annotation JavaDoc[] EMPTY_ANNOTATION_ARRAY=new Annotation JavaDoc[0];
581
582     public Annotation JavaDoc[] getDeclaredAnnotations() {
583         return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY);
584     }
585
586     private transient Map JavaDoc<Class JavaDoc, Annotation JavaDoc> declaredAnnotations;
587
588     private synchronized Map JavaDoc<Class JavaDoc, Annotation JavaDoc> declaredAnnotations() {
589         if (declaredAnnotations == null) {
590             declaredAnnotations = AnnotationParser.parseAnnotations(
591                 annotations, sun.misc.SharedSecrets.getJavaLangAccess().
592                 getConstantPool(getDeclaringClass()),
593                 getDeclaringClass());
594         }
595         return declaredAnnotations;
596     }
597
598     /**
599      * Returns an array of arrays that represent the annotations on the formal
600      * parameters, in declaration order, of the method represented by
601      * this <tt>Method</tt> object. (Returns an array of length zero if the
602      * underlying method is parameterless. If the method has one or more
603      * parameters, a nested array of length zero is returned for each parameter
604      * with no annotations.) The annotation objects contained in the returned
605      * arrays are serializable. The caller of this method is free to modify
606      * the returned arrays; it will have no effect on the arrays returned to
607      * other callers.
608      *
609      * @return an array of arrays that represent the annotations on the formal
610      * parameters, in declaration order, of the method represented by this
611      * Method object
612      * @since 1.5
613      */

614     public Annotation JavaDoc[][] getParameterAnnotations() {
615         int numParameters = parameterTypes.length;
616         if (parameterAnnotations == null)
617             return new Annotation JavaDoc[numParameters][0];
618
619         Annotation JavaDoc[][] result = AnnotationParser.parseParameterAnnotations(
620             parameterAnnotations,
621             sun.misc.SharedSecrets.getJavaLangAccess().
622                 getConstantPool(getDeclaringClass()),
623             getDeclaringClass());
624         if (result.length != numParameters)
625             throw new java.lang.annotation.AnnotationFormatError JavaDoc(
626                 "Parameter annotations don't match number of parameters");
627         return result;
628     }
629 }
630
Popular Tags