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 "<modifier> <classname>(<paramtypes>) 213 * throws <exceptions>", 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}