Source for java.lang.reflect.Constructor

   1: /* java.lang.reflect.Constructor - reflection of Java constructors
   2:    Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   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.
  10:  
  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.
  15: 
  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.
  20: 
  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.
  25: 
  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. */
  37: 
  38: 
  39: package java.lang.reflect;
  40: 
  41: import gnu.java.lang.ClassHelper;
  42: 
  43: import gnu.java.lang.reflect.MethodSignatureParser;
  44: 
  45: import java.util.Arrays;
  46: 
  47: /**
  48:  * The Constructor class represents a constructor of a class. It also allows
  49:  * dynamic creation of an object, via reflection. Invocation on Constructor
  50:  * objects knows how to do widening conversions, but throws
  51:  * {@link IllegalArgumentException} if a narrowing conversion would be
  52:  * necessary. You can query for information on this Constructor regardless
  53:  * of location, but construction access may be limited by Java language
  54:  * access controls. If you can't do it in the compiler, you can't normally
  55:  * do it here either.<p>
  56:  *
  57:  * <B>Note:</B> This class returns and accepts types as Classes, even
  58:  * primitive types; there are Class types defined that represent each
  59:  * different primitive type.  They are <code>java.lang.Boolean.TYPE,
  60:  * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
  61:  * byte.class</code>, etc.  These are not to be confused with the
  62:  * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
  63:  * real classes.<p>
  64:  *
  65:  * Also note that this is not a serializable class.  It is entirely feasible
  66:  * to make it serializable using the Externalizable interface, but this is
  67:  * on Sun, not me.
  68:  *
  69:  * @author John Keiser
  70:  * @author Eric Blake <ebb9@email.byu.edu>
  71:  * @see Member
  72:  * @see Class
  73:  * @see java.lang.Class#getConstructor(Class[])
  74:  * @see java.lang.Class#getDeclaredConstructor(Class[])
  75:  * @see java.lang.Class#getConstructors()
  76:  * @see java.lang.Class#getDeclaredConstructors()
  77:  * @since 1.1
  78:  * @status updated to 1.4
  79:  */
  80: public final class Constructor<T>
  81:   extends AccessibleObject
  82:   implements GenericDeclaration, Member
  83: {
  84:   private Class<T> clazz;
  85:   private int slot;
  86:   
  87:   private static final int CONSTRUCTOR_MODIFIERS
  88:     = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
  89: 
  90:   /**
  91:    * This class is uninstantiable except from native code.
  92:    */
  93:   private Constructor(Class declaringClass,int slot)
  94:   {
  95:     this.clazz = declaringClass;
  96:     this.slot = slot;
  97:   }
  98: 
  99:   private Constructor()
 100:   {
 101:   }
 102: 
 103:   /**
 104:    * Gets the class that declared this constructor.
 105:    * @return the class that declared this member
 106:    */
 107:   public Class<T> getDeclaringClass()
 108:   {
 109:     return clazz;
 110:   }
 111: 
 112:   /**
 113:    * Gets the name of this constructor (the non-qualified name of the class
 114:    * it was declared in).
 115:    * @return the name of this constructor
 116:    */
 117:   public String getName()
 118:   {
 119:     return getDeclaringClass().getName();
 120:   }
 121: 
 122:   /**
 123:    * Return the raw modifiers for this constructor.  In particular
 124:    * this will include the synthetic and varargs bits.
 125:    * @return the constructor's modifiers
 126:    */
 127:   private native int getModifiersInternal();
 128: 
 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 getModifiersInternal() & CONSTRUCTOR_MODIFIERS;
 140:   }
 141: 
 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 (getModifiersInternal() & Modifier.SYNTHETIC) != 0;
 151:   }
 152: 
 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 (getModifiersInternal() & Modifier.VARARGS) != 0;
 161:   }
 162: 
 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 native Class<?>[] getParameterTypes();
 170: 
 171:   /**
 172:    * Get the exception types this constructor says it throws, in no particular
 173:    * order. If the constructor has no throws clause, returns a 0-length array
 174:    * (not null).
 175:    *
 176:    * @return a list of the types in the constructor's throws clause
 177:    */
 178:   public native Class<?>[] getExceptionTypes();
 179: 
 180:   /**
 181:    * Compare two objects to see if they are semantically equivalent.
 182:    * Two Constructors are semantically equivalent if they have the same
 183:    * declaring class and the same parameter list.  This ignores different
 184:    * exception clauses, but since you can't create a Method except through the
 185:    * VM, this is just the == relation.
 186:    *
 187:    * @param o the object to compare to
 188:    * @return <code>true</code> if they are equal; <code>false</code> if not.
 189:    */
 190:   public boolean equals(Object o)
 191:   {
 192:     if (!(o instanceof Constructor))
 193:       return false;
 194:     Constructor that = (Constructor)o; 
 195:     if (this.getDeclaringClass() != that.getDeclaringClass())
 196:       return false;
 197:     if (!Arrays.equals(this.getParameterTypes(), that.getParameterTypes()))
 198:       return false;
 199:     return true;
 200:   }
 201: 
 202:   /**
 203:    * Get the hash code for the Constructor. The Constructor hash code is the
 204:    * hash code of the declaring class's name.
 205:    *
 206:    * @return the hash code for the object
 207:    */
 208:   public int hashCode()
 209:   {
 210:     return getDeclaringClass().getName().hashCode();
 211:   }
 212: 
 213:   /**
 214:    * Get a String representation of the Constructor. A Constructor's String
 215:    * representation is "&lt;modifier&gt; &lt;classname&gt;(&lt;paramtypes&gt;)
 216:    * throws &lt;exceptions&gt;", where everything after ')' is omitted if
 217:    * there are no exceptions.<br> Example:
 218:    * <code>public java.io.FileInputStream(java.lang.Runnable)
 219:    * throws java.io.FileNotFoundException</code>
 220:    *
 221:    * @return the String representation of the Constructor
 222:    */
 223:   public String toString()
 224:   {
 225:     // 128 is a reasonable buffer initial size for constructor
 226:     StringBuilder sb = new StringBuilder(128);
 227:     Modifier.toString(getModifiers(), sb).append(' ');
 228:     sb.append(getDeclaringClass().getName()).append('(');
 229:     Class[] c = getParameterTypes();
 230:     if (c.length > 0)
 231:       {
 232:         sb.append(ClassHelper.getUserName(c[0]));
 233:         for (int i = 1; i < c.length; i++)
 234:           sb.append(',').append(ClassHelper.getUserName(c[i]));
 235:       }
 236:     sb.append(')');
 237:     c = getExceptionTypes();
 238:     if (c.length > 0)
 239:       {
 240:         sb.append(" throws ").append(c[0].getName());
 241:         for (int i = 1; i < c.length; i++)
 242:           sb.append(',').append(c[i].getName());
 243:       }
 244:     return sb.toString();
 245:   }
 246: 
 247:   static <X extends GenericDeclaration>
 248:   void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs)
 249:   {
 250:     if (typeArgs.length == 0)
 251:       return;
 252:     sb.append('<');
 253:     for (int i = 0; i < typeArgs.length; ++i)
 254:       {
 255:         if (i > 0)
 256:           sb.append(',');
 257:         sb.append(typeArgs[i]);
 258:       }
 259:     sb.append("> ");
 260:   }
 261: 
 262:   public String toGenericString()
 263:   {
 264:     StringBuilder sb = new StringBuilder(128);
 265:     Modifier.toString(getModifiers(), sb).append(' ');
 266:     addTypeParameters(sb, getTypeParameters());
 267:     sb.append(getDeclaringClass().getName()).append('(');
 268:     Type[] types = getGenericParameterTypes();
 269:     if (types.length > 0)
 270:       {
 271:         sb.append(types[0]);
 272:         for (int i = 1; i < types.length; ++i)
 273:           sb.append(',').append(types[i]);
 274:       }
 275:     sb.append(')');
 276:     types = getGenericExceptionTypes();
 277:     if (types.length > 0)
 278:       {
 279:         sb.append(" throws ").append(types[0]);
 280:         for (int i = 1; i < types.length; i++)
 281:           sb.append(',').append(types[i]);
 282:       }
 283:     return sb.toString();
 284:   }
 285: 
 286:   /**
 287:    * Create a new instance by invoking the constructor. Arguments are
 288:    * automatically unwrapped and widened, if needed.<p>
 289:    *
 290:    * If this class is abstract, you will get an
 291:    * <code>InstantiationException</code>. If the constructor takes 0
 292:    * arguments, you may use null or a 0-length array for <code>args</code>.<p>
 293:    *
 294:    * If this Constructor enforces access control, your runtime context is
 295:    * evaluated, and you may have an <code>IllegalAccessException</code> if
 296:    * you could not create this object in similar compiled code. If the class
 297:    * is uninitialized, you trigger class initialization, which may end in a
 298:    * <code>ExceptionInInitializerError</code>.<p>
 299:    *
 300:    * Then, the constructor is invoked. If it completes normally, the return
 301:    * value will be the new object. If it completes abruptly, the exception is
 302:    * wrapped in an <code>InvocationTargetException</code>.
 303:    *
 304:    * @param args the arguments to the constructor
 305:    * @return the newly created object
 306:    * @throws IllegalAccessException if the constructor could not normally be
 307:    *         called by the Java code (i.e. it is not public)
 308:    * @throws IllegalArgumentException if the number of arguments is incorrect;
 309:    *         or if the arguments types are wrong even with a widening
 310:    *         conversion
 311:    * @throws InstantiationException if the class is abstract
 312:    * @throws InvocationTargetException if the constructor throws an exception
 313:    * @throws ExceptionInInitializerError if construction triggered class
 314:    *         initialization, which then failed
 315:    */
 316:   public T newInstance(Object... args)
 317:     throws InstantiationException, IllegalAccessException,
 318:            InvocationTargetException
 319:   {
 320:     return constructNative(args, clazz, slot);
 321:   }
 322: 
 323:   private native T constructNative(Object[] args, Class declaringClass,
 324:                    int slot)
 325:     throws InstantiationException, IllegalAccessException,
 326:            InvocationTargetException;
 327: 
 328:   /**
 329:    * Returns an array of <code>TypeVariable</code> objects that represents
 330:    * the type variables declared by this constructor, in declaration order.
 331:    * An array of size zero is returned if this constructor has no type
 332:    * variables.
 333:    *
 334:    * @return the type variables associated with this constructor.
 335:    * @throws GenericSignatureFormatError if the generic signature does
 336:    *         not conform to the format specified in the Virtual Machine
 337:    *         specification, version 3.
 338:    * @since 1.5
 339:    */
 340:   public TypeVariable<Constructor<T>>[] getTypeParameters()
 341:   {
 342:     String sig = getSignature();
 343:     if (sig == null)
 344:       return new TypeVariable[0];
 345:     MethodSignatureParser p = new MethodSignatureParser(this, sig);
 346:     return p.getTypeParameters();
 347:   }
 348: 
 349:   /**
 350:    * Return the String in the Signature attribute for this constructor. If there
 351:    * is no Signature attribute, return null.
 352:    */
 353:   private native String getSignature();
 354: 
 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();
 370:     if (sig == null)
 371:       return getExceptionTypes();
 372:     MethodSignatureParser p = new MethodSignatureParser(this, sig);
 373:     return p.getGenericExceptionTypes();
 374:   }
 375: 
 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();
 391:     if (sig == null)
 392:       return getParameterTypes();
 393:     MethodSignatureParser p = new MethodSignatureParser(this, sig);
 394:     return p.getGenericParameterTypes();
 395:   }
 396: }