Source for java.lang.reflect.Method

   1: // Method.java - Represent method of class or interface.
   2: 
   3: /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2007  Free Software Foundation
   4: 
   5:    This file is part of libgcj.
   6: 
   7: This software is copyrighted work licensed under the terms of the
   8: Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
   9: details.  */
  10:  
  11: package java.lang.reflect;
  12: 
  13: import gnu.gcj.RawData;
  14: import gnu.java.lang.reflect.MethodSignatureParser;
  15: import java.lang.annotation.Annotation;
  16: 
  17: /**
  18:  * The Method class represents a member method of a class. It also allows
  19:  * dynamic invocation, via reflection. This works for both static and
  20:  * instance methods. Invocation on Method objects knows how to do
  21:  * widening conversions, but throws {@link IllegalArgumentException} if
  22:  * a narrowing conversion would be necessary. You can query for information
  23:  * on this Method regardless of location, but invocation access may be limited
  24:  * by Java language access controls. If you can't do it in the compiler, you
  25:  * can't normally do it here either.<p>
  26:  *
  27:  * <B>Note:</B> This class returns and accepts types as Classes, even
  28:  * primitive types; there are Class types defined that represent each
  29:  * different primitive type.  They are <code>java.lang.Boolean.TYPE,
  30:  * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
  31:  * byte.class</code>, etc.  These are not to be confused with the
  32:  * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
  33:  * real classes.<p>
  34:  *
  35:  * Also note that this is not a serializable class.  It is entirely feasible
  36:  * to make it serializable using the Externalizable interface, but this is
  37:  * on Sun, not me.
  38:  *
  39:  * @author John Keiser
  40:  * @author Eric Blake <ebb9@email.byu.edu>
  41:  * @author Tom Tromey <tromey@redhat.com>
  42:  * @see Member
  43:  * @see Class
  44:  * @see java.lang.Class#getMethod(String,Class[])
  45:  * @see java.lang.Class#getDeclaredMethod(String,Class[])
  46:  * @see java.lang.Class#getMethods()
  47:  * @see java.lang.Class#getDeclaredMethods()
  48:  * @since 1.1
  49:  * @status updated to 1.4
  50:  */
  51: public final class Method
  52:   extends AccessibleObject implements Member, GenericDeclaration
  53: {
  54:   static final int METHOD_MODIFIERS
  55:     = Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE
  56:       | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC
  57:       | Modifier.STATIC | Modifier.STRICT | Modifier.SYNCHRONIZED;
  58: 
  59:   /**
  60:    * This class is uninstantiable.
  61:    */
  62:   private Method ()
  63:   {
  64:   }
  65: 
  66:   /**
  67:    * Gets the class that declared this method, or the class where this method
  68:    * is a non-inherited member.
  69:    * @return the class that declared this member
  70:    */
  71:   public Class<?> getDeclaringClass()
  72:   {
  73:     return declaringClass;
  74:   }
  75: 
  76:   /**
  77:    * Gets the name of this method.
  78:    * @return the name of this method
  79:    */
  80:   public native String getName ();
  81: 
  82:   /**
  83:    * Return the raw modifiers for this method.
  84:    * @return the method's modifiers
  85:    */
  86:   private native int getModifiersInternal();
  87: 
  88:   /**
  89:    * Gets the modifiers this method uses.  Use the <code>Modifier</code>
  90:    * class to interpret the values.  A method can only have a subset of the
  91:    * following modifiers: public, private, protected, abstract, static,
  92:    * final, synchronized, native, and strictfp.
  93:    *
  94:    * @return an integer representing the modifiers to this Member
  95:    * @see Modifier
  96:    */
  97:   public int getModifiers()
  98:   {
  99:     return getModifiersInternal() & METHOD_MODIFIERS;
 100:   }
 101: 
 102:   /**
 103:    * Return true if this method is a bridge method.  A bridge method
 104:    * is generated by the compiler in some situations involving
 105:    * generics and inheritance.
 106:    * @since 1.5
 107:    */
 108:   public boolean isBridge()
 109:   {
 110:     return (getModifiersInternal() & Modifier.BRIDGE) != 0;
 111:   }
 112: 
 113:   /**
 114:    * Return true if this method is synthetic, false otherwise.
 115:    * @since 1.5
 116:    */
 117:   public boolean isSynthetic()
 118:   {
 119:     return (getModifiersInternal() & Modifier.SYNTHETIC) != 0;
 120:   }
 121: 
 122:   /**
 123:    * Return true if this is a varargs method, that is if
 124:    * the method takes a variable number of arguments.
 125:    * @since 1.5
 126:    */
 127:   public boolean isVarArgs()
 128:   {
 129:     return (getModifiersInternal() & Modifier.VARARGS) != 0;
 130:   }
 131: 
 132:   /**
 133:    * Gets the return type of this method.
 134:    * @return the type of this method
 135:    */
 136:   public Class<?> getReturnType ()
 137:   {
 138:     if (return_type == null)
 139:       getType();
 140:     return return_type;
 141:   }
 142: 
 143:   /**
 144:    * Get the parameter list for this method, in declaration order. If the
 145:    * method takes no parameters, returns a 0-length array (not null).
 146:    *
 147:    * @return a list of the types of the method's parameters
 148:    */
 149:   public Class<?>[] getParameterTypes ()
 150:   {
 151:     if (parameter_types == null)
 152:       getType();
 153:     return (Class<?>[]) parameter_types.clone();
 154:   }
 155: 
 156:   // Just like getParameterTypes, but don't clone the array.
 157:   // Package private for use by VMProxy.
 158:   final Class<?>[] internalGetParameterTypes ()
 159:   {
 160:     if (parameter_types == null)
 161:       getType();
 162:     return (Class<?>[]) parameter_types;
 163:   }
 164: 
 165:   /**
 166:    * Get the exception types this method says it throws, in no particular
 167:    * order. If the method has no throws clause, returns a 0-length array
 168:    * (not null).
 169:    *
 170:    * @return a list of the types in the method's throws clause
 171:    */
 172:   public Class<?>[] getExceptionTypes ()
 173:   {
 174:     if (exception_types == null)
 175:       getType();
 176:     return (Class<?>[]) exception_types.clone();
 177:   }
 178: 
 179:   // Just like getExceptionTypes, but don't clone the array.
 180:   // Package private for use by VMProxy.
 181:   final Class<?>[] internalGetExceptionTypes ()
 182:   {
 183:     if (exception_types == null)
 184:       getType();
 185:     return (Class<?>[]) exception_types;
 186:   }
 187: 
 188:   /**
 189:    * Compare two objects to see if they are semantically equivalent.
 190:    * Two Methods are semantically equivalent if they have the same declaring
 191:    * class, name, and parameter list.  This ignores different exception
 192:    * clauses or return types.
 193:    *
 194:    * @param o the object to compare to
 195:    * @return <code>true</code> if they are equal; <code>false</code> if not
 196:    */
 197:   public boolean equals (Object obj)
 198:   {
 199:     if (! (obj instanceof Method))
 200:       return false;
 201:     Method m = (Method) obj;
 202:     return declaringClass == m.declaringClass && offset == m.offset;
 203:   }
 204: 
 205:   /**
 206:    * Get the hash code for the Method. The Method hash code is the hash code
 207:    * of its name XOR'd with the hash code of its class name.
 208:    *
 209:    * @return the hash code for the object
 210:    */
 211:   public int hashCode()
 212:   {
 213:     return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
 214:   }
 215: 
 216:   /**
 217:    * Get a String representation of the Method. A Method's String
 218:    * representation is "&lt;modifiers&gt; &lt;returntype&gt;
 219:    * &lt;methodname&gt;(&lt;paramtypes&gt;) throws &lt;exceptions&gt;", where
 220:    * everything after ')' is omitted if there are no exceptions.<br> Example:
 221:    * <code>public static int run(java.lang.Runnable,int)</code>
 222:    *
 223:    * @return the String representation of the Method
 224:    */
 225:   public String toString()
 226:   {
 227:     if (parameter_types == null)
 228:       getType ();
 229: 
 230:     StringBuffer b = new StringBuffer ();
 231:     int mods = getModifiers();
 232:     if (mods != 0)
 233:       {
 234:     Modifier.toString(mods, b);
 235:     b.append(" ");
 236:       }
 237:     appendClassName (b, return_type);
 238:     b.append(" ");
 239:     appendClassName (b, declaringClass);
 240:     b.append(".");
 241:     b.append(getName());
 242:     b.append("(");
 243:     for (int i = 0; i < parameter_types.length; ++i)
 244:       {
 245:     appendClassName (b, parameter_types[i]);
 246:     if (i < parameter_types.length - 1)
 247:       b.append(",");
 248:       }
 249:     b.append(")");
 250:     if (exception_types.length > 0)
 251:       {
 252:     b.append(" throws ");
 253:     for (int i = 0; i < exception_types.length; ++i)
 254:       {
 255:         appendClassName (b, exception_types[i]);
 256:         if (i < exception_types.length - 1)
 257:           b.append(",");
 258:       }
 259:       }
 260:     return b.toString();
 261:   }
 262: 
 263:   public String toGenericString()
 264:   {
 265:     // 128 is a reasonable buffer initial size for constructor
 266:     StringBuilder sb = new StringBuilder(128);
 267:     Modifier.toString(getModifiers(), sb).append(' ');
 268:     Constructor.addTypeParameters(sb, getTypeParameters());
 269:     sb.append(getGenericReturnType()).append(' ');
 270:     sb.append(getDeclaringClass().getName()).append('.');
 271:     sb.append(getName()).append('(');
 272:     Type[] types = getGenericParameterTypes();
 273:     if (types.length > 0)
 274:       {
 275:         sb.append(types[0]);
 276:         for (int i = 1; i < types.length; i++)
 277:           sb.append(',').append(types[i]);
 278:       }
 279:     sb.append(')');
 280:     types = getGenericExceptionTypes();
 281:     if (types.length > 0)
 282:       {
 283:         sb.append(" throws ").append(types[0]);
 284:         for (int i = 1; i < types.length; i++)
 285:           sb.append(',').append(types[i]);
 286:       }
 287:     return sb.toString();
 288:   }
 289: 
 290:   /**
 291:    * Invoke the method. Arguments are automatically unwrapped and widened,
 292:    * and the result is automatically wrapped, if needed.<p>
 293:    *
 294:    * If the method is static, <code>o</code> will be ignored. Otherwise,
 295:    * the method uses dynamic lookup as described in JLS 15.12.4.4. You cannot
 296:    * mimic the behavior of nonvirtual lookup (as in super.foo()). This means
 297:    * you will get a <code>NullPointerException</code> if <code>o</code> is
 298:    * null, and an <code>IllegalArgumentException</code> if it is incompatible
 299:    * with the declaring class of the method. If the method takes 0 arguments,
 300:    * you may use null or a 0-length array for <code>args</code>.<p>
 301:    *
 302:    * Next, if this Method enforces access control, your runtime context is
 303:    * evaluated, and you may have an <code>IllegalAccessException</code> if
 304:    * you could not acces this method in similar compiled code. If the method
 305:    * is static, and its class is uninitialized, you trigger class
 306:    * initialization, which may end in a
 307:    * <code>ExceptionInInitializerError</code>.<p>
 308:    *
 309:    * Finally, the method is invoked. If it completes normally, the return value
 310:    * will be null for a void method, a wrapped object for a primitive return
 311:    * method, or the actual return of an Object method. If it completes
 312:    * abruptly, the exception is wrapped in an
 313:    * <code>InvocationTargetException</code>.
 314:    *
 315:    * @param o the object to invoke the method on
 316:    * @param args the arguments to the method
 317:    * @return the return value of the method, wrapped in the appropriate
 318:    *         wrapper if it is primitive
 319:    * @throws IllegalAccessException if the method could not normally be called
 320:    *         by the Java code (i.e. it is not public)
 321:    * @throws IllegalArgumentException if the number of arguments is incorrect;
 322:    *         if the arguments types are wrong even with a widening conversion;
 323:    *         or if <code>o</code> is not an instance of the class or interface
 324:    *         declaring this method
 325:    * @throws InvocationTargetException if the method throws an exception
 326:    * @throws NullPointerException if <code>o</code> is null and this field
 327:    *         requires an instance
 328:    * @throws ExceptionInInitializerError if accessing a static method triggered
 329:    *         class initialization, which then failed
 330:    */
 331:   public native Object invoke (Object obj, Object... args)
 332:     throws IllegalAccessException, IllegalArgumentException,
 333:     InvocationTargetException;
 334: 
 335:   /**
 336:    * Returns an array of <code>TypeVariable</code> objects that represents
 337:    * the type variables declared by this constructor, in declaration order.
 338:    * An array of size zero is returned if this class has no type
 339:    * variables.
 340:    *
 341:    * @return the type variables associated with this class. 
 342:    * @throws GenericSignatureFormatError if the generic signature does
 343:    *         not conform to the format specified in the Virtual Machine
 344:    *         specification, version 3.
 345:    * @since 1.5
 346:    */
 347:   public TypeVariable<Method>[] getTypeParameters()
 348:   {
 349:     String sig = getSignature();
 350:     if (sig == null)
 351:       return new TypeVariable[0];
 352:     MethodSignatureParser p = new MethodSignatureParser(this, sig);
 353:     return p.getTypeParameters();
 354:   }
 355: 
 356:   /**
 357:    * Return the String in the Signature attribute for this method. If there
 358:    * is no Signature attribute, return null.
 359:    */
 360:   private native String getSignature();
 361: 
 362:   /**
 363:    * Returns an array of <code>Type</code> objects that represents
 364:    * the exception types declared by this method, in declaration order.
 365:    * An array of size zero is returned if this method declares no
 366:    * exceptions.
 367:    *
 368:    * @return the exception types declared by this method. 
 369:    * @throws GenericSignatureFormatError if the generic signature does
 370:    *         not conform to the format specified in the Virtual Machine
 371:    *         specification, version 3.
 372:    * @since 1.5
 373:    */
 374:   public Type[] getGenericExceptionTypes()
 375:   {
 376:     String sig = getSignature();
 377:     if (sig == null)
 378:       return getExceptionTypes();
 379:     MethodSignatureParser p = new MethodSignatureParser(this, sig);
 380:     return p.getGenericExceptionTypes();
 381:   }
 382: 
 383:   /**
 384:    * Returns an array of <code>Type</code> objects that represents
 385:    * the parameter list for this method, in declaration order.
 386:    * An array of size zero is returned if this method takes no
 387:    * parameters.
 388:    *
 389:    * @return a list of the types of the method's parameters
 390:    * @throws GenericSignatureFormatError if the generic signature does
 391:    *         not conform to the format specified in the Virtual Machine
 392:    *         specification, version 3.
 393:    * @since 1.5
 394:    */
 395:   public Type[] getGenericParameterTypes()
 396:   {
 397:     String sig = getSignature();
 398:     if (sig == null)
 399:       return getParameterTypes();
 400:     MethodSignatureParser p = new MethodSignatureParser(this, sig);
 401:     return p.getGenericParameterTypes();
 402:   }
 403: 
 404:   /**
 405:    * Returns the return type of this method.
 406:    *
 407:    * @return the return type of this method
 408:    * @throws GenericSignatureFormatError if the generic signature does
 409:    *         not conform to the format specified in the Virtual Machine
 410:    *         specification, version 3.
 411:    * @since 1.5
 412:    */
 413:   public Type getGenericReturnType()
 414:   {
 415:     String sig = getSignature();
 416:     if (sig == null)
 417:       return getReturnType();
 418:     MethodSignatureParser p = new MethodSignatureParser(this, sig);
 419:     return p.getGenericReturnType();
 420:   }
 421: 
 422:   /**
 423:    * If this method is an annotation method, returns the default
 424:    * value for the method.  If there is no default value, or if the
 425:    * method is not a member of an annotation type, returns null.
 426:    * Primitive types are wrapped.
 427:    *
 428:    * @throws TypeNotPresentException if the method returns a Class,
 429:    * and the class cannot be found
 430:    *
 431:    * @since 1.5
 432:    */
 433:   public native Object getDefaultValue();
 434: 
 435:   public <T extends Annotation> T getAnnotation(Class<T> annoClass)
 436:   {
 437:     Annotation[] annos = getDeclaredAnnotations();
 438:     for (int i = 0; i < annos.length; ++i)
 439:       if (annos[i].annotationType() == annoClass)
 440:     return (T) annos[i];
 441:     return null;
 442:   }
 443: 
 444:   public Annotation[] getDeclaredAnnotations()
 445:   {
 446:     Annotation[] result = getDeclaredAnnotationsInternal();
 447:     if (result == null)
 448:       result = new Annotation[0];
 449:     return result;
 450:   }
 451: 
 452:   public Annotation[][] getParameterAnnotations()
 453:   {
 454:     // FIXME: should check that we have the right number
 455:     // of parameters ...?
 456:     Annotation[][] result = getParameterAnnotationsInternal();
 457:     if (result == null)
 458:       result = new Annotation[0][0];
 459:     return result;
 460:   }
 461: 
 462:   private native Annotation[] getDeclaredAnnotationsInternal();
 463:   private native Annotation[][] getParameterAnnotationsInternal();
 464: 
 465:   private native void getType ();
 466: 
 467:   // Append a class name to a string buffer.  We try to print the
 468:   // fully-qualified name, the way that a Java programmer would expect
 469:   // it to be written.  Weirdly, Class has no appropriate method for
 470:   // this.
 471:   static void appendClassName (StringBuffer buf, Class k)
 472:   {
 473:     if (k.isArray ())
 474:       {
 475:     appendClassName (buf, k.getComponentType ());
 476:     buf.append ("[]");
 477:       }
 478:     else
 479:       {
 480:     // This is correct for primitive and reference types.  Really
 481:     // we'd like `Main$Inner' to be printed as `Main.Inner', I
 482:     // think, but that is a pain.
 483:     buf.append (k.getName ());
 484:       }
 485:   }
 486: 
 487:   // Declaring class.
 488:   private Class declaringClass;
 489: 
 490:   // Exception types.
 491:   Class[] exception_types;
 492:   // Name cache.  (Initially null.)
 493:   private String name;
 494:   // Parameter types.
 495:   Class[] parameter_types;
 496:   // Return type.
 497:   Class return_type;
 498: 
 499:   // Offset in bytes from the start of declaringClass's methods array.
 500:   private int offset;
 501: }