jamvm
view lib/java/lang/reflect/Constructor.java @ 395:387051b26a50
Make compatible with changes in GNU Classpath (CVS).
| author | rlougher |
|---|---|
| date | Wed Jun 04 02:46:32 2008 +0100 (2008-06-04) |
| parents | 768ab36fd30e |
| children |
line source
1 /* java.lang.reflect.Constructor - reflection of Java constructors
2 Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 /*
39 Robert Lougher 17/11/2003.
40 This Classpath reference implementation has been modified to work with JamVM.
41 */
43 package java.lang.reflect;
45 import gnu.java.lang.ClassHelper;
46 import gnu.java.lang.CPStringBuilder;
48 import gnu.java.lang.reflect.MethodSignatureParser;
49 import java.util.Arrays;
50 import java.lang.annotation.Annotation;
52 /**
53 * The Constructor class represents a constructor of a class. It also allows
54 * dynamic creation of an object, via reflection. Invocation on Constructor
55 * objects knows how to do widening conversions, but throws
56 * {@link IllegalArgumentException} if a narrowing conversion would be
57 * necessary. You can query for information on this Constructor regardless
58 * of location, but construction access may be limited by Java language
59 * access controls. If you can't do it in the compiler, you can't normally
60 * do it here either.<p>
61 *
62 * <B>Note:</B> This class returns and accepts types as Classes, even
63 * primitive types; there are Class types defined that represent each
64 * different primitive type. They are <code>java.lang.Boolean.TYPE,
65 * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
66 * byte.class</code>, etc. These are not to be confused with the
67 * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
68 * real classes.<p>
69 *
70 * Also note that this is not a serializable class. It is entirely feasible
71 * to make it serializable using the Externalizable interface, but this is
72 * on Sun, not me.
73 *
74 * @author John Keiser
75 * @author Eric Blake <ebb9@email.byu.edu>
76 * @author Robert Lougher
77 * @see Member
78 * @see Class
79 * @see java.lang.Class#getConstructor(Class[])
80 * @see java.lang.Class#getDeclaredConstructor(Class[])
81 * @see java.lang.Class#getConstructors()
82 * @see java.lang.Class#getDeclaredConstructors()
83 * @since 1.1
84 * @status updated to 1.4
85 */
86 public final class Constructor
87 extends AccessibleObject
88 implements GenericDeclaration, Member
89 {
90 private Class declaringClass;
91 private int slot;
92 private Class[] parameterTypes;
93 private Class[] exceptionTypes;
95 /**
96 * This class is uninstantiable except from native code.
97 */
98 private Constructor(Class declaringClass, Class[] parameterTypes, Class[] exceptionTypes, int slot)
99 {
100 this.declaringClass = declaringClass;
101 this.parameterTypes = parameterTypes;
102 this.exceptionTypes = exceptionTypes;
103 this.slot = slot;
104 }
106 private Constructor()
107 {
108 }
110 /**
111 * Gets the class that declared this constructor.
112 * @return the class that declared this member
113 */
114 public Class getDeclaringClass()
115 {
116 return declaringClass;
117 }
119 /**
120 * Gets the name of this constructor (the non-qualified name of the class
121 * it was declared in).
122 * @return the name of this constructor
123 */
124 public String getName()
125 {
126 return getDeclaringClass().getName();
127 }
129 /**
130 * Gets the modifiers this constructor uses. Use the <code>Modifier</code>
131 * class to interpret the values. A constructor can only have a subset of the
132 * following modifiers: public, private, protected.
133 *
134 * @return an integer representing the modifiers to this Member
135 * @see Modifier
136 */
137 public int getModifiers()
138 {
139 return getConstructorModifiers(declaringClass, slot);
140 }
142 /**
143 * Return true if this constructor is synthetic, false otherwise.
144 * A synthetic member is one which is created by the compiler,
145 * and which does not appear in the user's source code.
146 * @since 1.5
147 */
148 public boolean isSynthetic()
149 {
150 return (getConstructorModifiers(declaringClass, slot) & Modifier.SYNTHETIC) != 0;
151 }
153 /**
154 * Return true if this is a varargs constructor, that is if
155 * the constructor takes a variable number of arguments.
156 * @since 1.5
157 */
158 public boolean isVarArgs()
159 {
160 return (getConstructorModifiers(declaringClass, slot) & Modifier.VARARGS) != 0;
161 }
163 /**
164 * Get the parameter list for this constructor, in declaration order. If the
165 * constructor takes no parameters, returns a 0-length array (not null).
166 *
167 * @return a list of the types of the constructor's parameters
168 */
169 public Class[] getParameterTypes()
170 {
171 if (parameterTypes == null)
172 return new Class[0];
173 return parameterTypes;
174 }
176 /**
177 * Get the exception types this constructor says it throws, in no particular
178 * order. If the constructor has no throws clause, returns a 0-length array
179 * (not null).
180 *
181 * @return a list of the types in the constructor's throws clause
182 */
183 public Class[] getExceptionTypes()
184 {
185 if (exceptionTypes == null)
186 return new Class[0];
187 return exceptionTypes;
188 }
190 /**
191 * Compare two objects to see if they are semantically equivalent.
192 * Two Constructors are semantically equivalent if they have the same
193 * declaring class and the same parameter list. This ignores different
194 * exception clauses, but since you can't create a Method except through the
195 * VM, this is just the == relation.
196 *
197 * @param o the object to compare to
198 * @return <code>true</code> if they are equal; <code>false</code> if not.
199 */
200 public boolean equals(Object o)
201 {
202 if (!(o instanceof Constructor))
203 return false;
204 Constructor that = (Constructor)o;
205 if (this.getDeclaringClass() != that.getDeclaringClass())
206 return false;
207 if (!Arrays.equals(this.getParameterTypes(), that.getParameterTypes()))
208 return false;
209 return true;
210 }
212 /**
213 * Get the hash code for the Constructor. The Constructor hash code is the
214 * hash code of the declaring class's name.
215 *
216 * @return the hash code for the object
217 */
218 public int hashCode()
219 {
220 return getDeclaringClass().getName().hashCode();
221 }
223 /**
224 * Get a String representation of the Constructor. A Constructor's String
225 * representation is "<modifier> <classname>(<paramtypes>)
226 * throws <exceptions>", where everything after ')' is omitted if
227 * there are no exceptions.<br> Example:
228 * <code>public java.io.FileInputStream(java.lang.Runnable)
229 * throws java.io.FileNotFoundException</code>
230 *
231 * @return the String representation of the Constructor
232 */
233 public String toString()
234 {
235 // 128 is a reasonable buffer initial size for constructor
236 CPStringBuilder sb = new CPStringBuilder(128);
237 Modifier.toString(getModifiers(), sb).append(' ');
238 sb.append(getDeclaringClass().getName()).append('(');
239 Class[] c = getParameterTypes();
240 if (c.length > 0)
241 {
242 sb.append(ClassHelper.getUserName(c[0]));
243 for (int i = 1; i < c.length; i++)
244 sb.append(',').append(ClassHelper.getUserName(c[i]));
245 }
246 sb.append(')');
247 c = getExceptionTypes();
248 if (c.length > 0)
249 {
250 sb.append(" throws ").append(c[0].getName());
251 for (int i = 1; i < c.length; i++)
252 sb.append(',').append(c[i].getName());
253 }
254 return sb.toString();
255 }
257 /* FIXME[GENERICS]: Add X extends GenericDeclaration and TypeVariable<X> */
258 static void addTypeParameters(CPStringBuilder sb, TypeVariable[] typeArgs)
259 {
260 if (typeArgs.length == 0)
261 return;
262 sb.append('<');
263 for (int i = 0; i < typeArgs.length; ++i)
264 {
265 if (i > 0)
266 sb.append(',');
267 sb.append(typeArgs[i]);
268 }
269 sb.append("> ");
270 }
272 public String toGenericString()
273 {
274 CPStringBuilder sb = new CPStringBuilder(128);
275 Modifier.toString(getModifiers(), sb).append(' ');
276 addTypeParameters(sb, getTypeParameters());
277 sb.append(getDeclaringClass().getName()).append('(');
278 Type[] types = getGenericParameterTypes();
279 if (types.length > 0)
280 {
281 sb.append(types[0]);
282 for (int i = 1; i < types.length; ++i)
283 sb.append(',').append(types[i]);
284 }
285 sb.append(')');
286 types = getGenericExceptionTypes();
287 if (types.length > 0)
288 {
289 sb.append(" throws ").append(types[0]);
290 for (int i = 1; i < types.length; i++)
291 sb.append(',').append(types[i]);
292 }
293 return sb.toString();
294 }
296 /**
297 * Create a new instance by invoking the constructor. Arguments are
298 * automatically unwrapped and widened, if needed.<p>
299 *
300 * If this class is abstract, you will get an
301 * <code>InstantiationException</code>. If the constructor takes 0
302 * arguments, you may use null or a 0-length array for <code>args</code>.<p>
303 *
304 * If this Constructor enforces access control, your runtime context is
305 * evaluated, and you may have an <code>IllegalAccessException</code> if
306 * you could not create this object in similar compiled code. If the class
307 * is uninitialized, you trigger class initialization, which may end in a
308 * <code>ExceptionInInitializerError</code>.<p>
309 *
310 * Then, the constructor is invoked. If it completes normally, the return
311 * value will be the new object. If it completes abruptly, the exception is
312 * wrapped in an <code>InvocationTargetException</code>.
313 *
314 * @param args the arguments to the constructor
315 * @return the newly created object
316 * @throws IllegalAccessException if the constructor could not normally be
317 * called by the Java code (i.e. it is not public)
318 * @throws IllegalArgumentException if the number of arguments is incorrect;
319 * or if the arguments types are wrong even with a widening
320 * conversion
321 * @throws InstantiationException if the class is abstract
322 * @throws InvocationTargetException if the constructor throws an exception
323 * @throws ExceptionInInitializerError if construction triggered class
324 * initialization, which then failed
325 */
326 public Object newInstance(Object args[])
327 throws InstantiationException, IllegalAccessException,
328 InvocationTargetException
329 {
330 return constructNative(args, declaringClass, parameterTypes, slot, flag);
331 }
333 /**
334 * Returns an array of <code>TypeVariable</code> objects that represents
335 * the type variables declared by this constructor, in declaration order.
336 * An array of size zero is returned if this constructor has no type
337 * variables.
338 *
339 * @return the type variables associated with this constructor.
340 * @throws GenericSignatureFormatError if the generic signature does
341 * not conform to the format specified in the Virtual Machine
342 * specification, version 3.
343 * @since 1.5
344 */
345 /* FIXME[GENERICS]: Add <Constructor<T>> */
346 public TypeVariable[] getTypeParameters()
347 {
348 String sig = getSignature(declaringClass, slot);
349 if (sig == null)
350 return new TypeVariable[0];
351 MethodSignatureParser p = new MethodSignatureParser(this, sig);
352 return p.getTypeParameters();
353 }
355 /**
356 * Returns an array of <code>Type</code> objects that represents
357 * the exception types declared by this constructor, in declaration order.
358 * An array of size zero is returned if this constructor declares no
359 * exceptions.
360 *
361 * @return the exception types declared by this constructor.
362 * @throws GenericSignatureFormatError if the generic signature does
363 * not conform to the format specified in the Virtual Machine
364 * specification, version 3.
365 * @since 1.5
366 */
367 public Type[] getGenericExceptionTypes()
368 {
369 String sig = getSignature(declaringClass, slot);
370 if (sig == null)
371 return getExceptionTypes();
372 MethodSignatureParser p = new MethodSignatureParser(this, sig);
373 return p.getGenericExceptionTypes();
374 }
376 /**
377 * Returns an array of <code>Type</code> objects that represents
378 * the parameter list for this constructor, in declaration order.
379 * An array of size zero is returned if this constructor takes no
380 * parameters.
381 *
382 * @return a list of the types of the constructor's parameters
383 * @throws GenericSignatureFormatError if the generic signature does
384 * not conform to the format specified in the Virtual Machine
385 * specification, version 3.
386 * @since 1.5
387 */
388 public Type[] getGenericParameterTypes()
389 {
390 String sig = getSignature(declaringClass, slot);
391 if (sig == null)
392 return getParameterTypes();
393 MethodSignatureParser p = new MethodSignatureParser(this, sig);
394 return p.getGenericParameterTypes();
395 }
397 public Annotation getAnnotation(Class annoClass)
398 {
399 Annotation[] annos = getDeclaredAnnotations();
400 for (int i = 0; i < annos.length; i++)
401 if (annos[i].annotationType() == annoClass)
402 return annos[i];
403 return null;
404 }
406 public Annotation[] getDeclaredAnnotations()
407 {
408 return getDeclaredAnnotationsNative(declaringClass, slot);
409 }
411 public Annotation[][] getParameterAnnotations()
412 {
413 return getParameterAnnotationsNative(declaringClass, slot);
414 }
416 /*
417 * NATIVE HELPERS
418 */
420 /**
421 * Return the String in the Signature attribute for this constructor. If there
422 * is no Signature attribute, return null.
423 */
424 private native String getSignature(Class declaringClass, int slot);
426 /**
427 * Return the raw modifiers for this constructor. In particular
428 * this will include the synthetic and varargs bits.
429 * @return the constructor's modifiers
430 */
431 private native int getConstructorModifiers(Class declaringClass, int slot);
433 private native Object constructNative(Object[] args, Class declaringClass,
434 Class[] parameterTypes, int slot,
435 boolean noAccessCheck)
436 throws InstantiationException, IllegalAccessException,
437 InvocationTargetException;
439 private native Annotation[] getDeclaredAnnotationsNative(Class declaringClass, int slot);
440 private native Annotation[][] getParameterAnnotationsNative(Class declaringClass, int slot);
441 }
