Frames | No Frames |
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 "<modifiers> <returntype> 219: * <methodname>(<paramtypes>) throws <exceptions>", 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: }