GNU Classpath (0.98) | |
Frames | No Frames |
1: /* java.lang.reflect.Method - reflection of Java methods 2: Copyright (C) 1998, 2001, 2002, 2005, 2007, 2008 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: import gnu.java.lang.CPStringBuilder; 43: 44: import gnu.java.lang.reflect.MethodSignatureParser; 45: 46: import java.lang.annotation.Annotation; 47: 48: /** 49: * The Method class represents a member method of a class. It also allows 50: * dynamic invocation, via reflection. This works for both static and 51: * instance methods. Invocation on Method objects knows how to do 52: * widening conversions, but throws {@link IllegalArgumentException} if 53: * a narrowing conversion would be necessary. You can query for information 54: * on this Method regardless of location, but invocation access may be limited 55: * by Java language access controls. If you can't do it in the compiler, you 56: * can't normally do it here either.<p> 57: * 58: * <B>Note:</B> This class returns and accepts types as Classes, even 59: * primitive types; there are Class types defined that represent each 60: * different primitive type. They are <code>java.lang.Boolean.TYPE, 61: * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class, 62: * byte.class</code>, etc. These are not to be confused with the 63: * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are 64: * real classes.<p> 65: * 66: * Also note that this is not a serializable class. It is entirely feasible 67: * to make it serializable using the Externalizable interface, but this is 68: * on Sun, not me. 69: * 70: * @author John Keiser 71: * @author Eric Blake <ebb9@email.byu.edu> 72: * @see Member 73: * @see Class 74: * @see java.lang.Class#getMethod(String,Class[]) 75: * @see java.lang.Class#getDeclaredMethod(String,Class[]) 76: * @see java.lang.Class#getMethods() 77: * @see java.lang.Class#getDeclaredMethods() 78: * @since 1.1 79: * @status updated to 1.4 80: */ 81: public final class Method 82: extends AccessibleObject implements Member, GenericDeclaration 83: { 84: private static final int METHOD_MODIFIERS 85: = Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE 86: | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC 87: | Modifier.STATIC | Modifier.STRICT | Modifier.SYNCHRONIZED; 88: 89: private MethodSignatureParser p; 90: 91: VMMethod m; 92: 93: /** 94: * This class is uninstantiable outside this package. 95: */ 96: Method(VMMethod m) 97: { 98: this.m = m; 99: m.m = this; 100: } 101: 102: /** 103: * Gets the class that declared this method, or the class where this method 104: * is a non-inherited member. 105: * @return the class that declared this member 106: */ 107: public Class<?> getDeclaringClass() 108: { 109: return (Class<?>) m.getDeclaringClass(); 110: } 111: 112: /** 113: * Gets the name of this method. 114: * @return the name of this method 115: */ 116: public String getName() 117: { 118: return m.getName(); 119: } 120: 121: /** 122: * Gets the modifiers this method uses. Use the <code>Modifier</code> 123: * class to interpret the values. A method can only have a subset of the 124: * following modifiers: public, private, protected, abstract, static, 125: * final, synchronized, native, and strictfp. 126: * 127: * @return an integer representing the modifiers to this Member 128: * @see Modifier 129: */ 130: public int getModifiers() 131: { 132: return m.getModifiersInternal() & METHOD_MODIFIERS; 133: } 134: 135: /** 136: * Return true if this method is a bridge method. A bridge method 137: * is generated by the compiler in some situations involving 138: * generics and inheritance. 139: * @since 1.5 140: */ 141: public boolean isBridge() 142: { 143: return (m.getModifiersInternal() & Modifier.BRIDGE) != 0; 144: } 145: 146: /** 147: * Return true if this method is synthetic, false otherwise. 148: * @since 1.5 149: */ 150: public boolean isSynthetic() 151: { 152: return (m.getModifiersInternal() & Modifier.SYNTHETIC) != 0; 153: } 154: 155: /** 156: * Return true if this is a varargs method, that is if 157: * the method takes a variable number of arguments. 158: * @since 1.5 159: */ 160: public boolean isVarArgs() 161: { 162: return (m.getModifiersInternal() & Modifier.VARARGS) != 0; 163: } 164: 165: /** 166: * Gets the return type of this method. 167: * @return the type of this method 168: */ 169: public Class<?> getReturnType() 170: { 171: return (Class<?>) m.getReturnType(); 172: } 173: 174: /** 175: * Get the parameter list for this method, in declaration order. If the 176: * method takes no parameters, returns a 0-length array (not null). 177: * 178: * @return a list of the types of the method's parameters 179: */ 180: public Class<?>[] getParameterTypes() 181: { 182: return (Class<?>[]) m.getParameterTypes(); 183: } 184: 185: /** 186: * Get the exception types this method says it throws, in no particular 187: * order. If the method has no throws clause, returns a 0-length array 188: * (not null). 189: * 190: * @return a list of the types in the method's throws clause 191: */ 192: public Class<?>[] getExceptionTypes() 193: { 194: return (Class<?>[]) m.getExceptionTypes(); 195: } 196: 197: /** 198: * Compare two objects to see if they are semantically equivalent. 199: * Two Methods are semantically equivalent if they have the same declaring 200: * class, name, parameter list, and return type. 201: * 202: * @param o the object to compare to 203: * @return <code>true</code> if they are equal; <code>false</code> if not 204: */ 205: public boolean equals(Object o) 206: { 207: return m.equals(o); 208: } 209: 210: /** 211: * Get the hash code for the Method. The Method hash code is the hash code 212: * of its name XOR'd with the hash code of its class name. 213: * 214: * @return the hash code for the object 215: */ 216: public int hashCode() 217: { 218: return m.getDeclaringClass().getName().hashCode() ^ m.getName().hashCode(); 219: } 220: 221: /** 222: * Get a String representation of the Method. A Method's String 223: * representation is "<modifiers> <returntype> 224: * <methodname>(<paramtypes>) throws <exceptions>", where 225: * everything after ')' is omitted if there are no exceptions.<br> Example: 226: * <code>public static int run(java.lang.Runnable,int)</code> 227: * 228: * @return the String representation of the Method 229: */ 230: public String toString() 231: { 232: // 128 is a reasonable buffer initial size for constructor 233: CPStringBuilder sb = new CPStringBuilder(128); 234: Modifier.toString(getModifiers(), sb).append(' '); 235: sb.append(ClassHelper.getUserName(getReturnType())).append(' '); 236: sb.append(getDeclaringClass().getName()).append('.'); 237: sb.append(getName()).append('('); 238: Class[] c = getParameterTypes(); 239: if (c.length > 0) 240: { 241: sb.append(ClassHelper.getUserName(c[0])); 242: for (int i = 1; i < c.length; i++) 243: sb.append(',').append(ClassHelper.getUserName(c[i])); 244: } 245: sb.append(')'); 246: c = getExceptionTypes(); 247: if (c.length > 0) 248: { 249: sb.append(" throws ").append(c[0].getName()); 250: for (int i = 1; i < c.length; i++) 251: sb.append(',').append(c[i].getName()); 252: } 253: return sb.toString(); 254: } 255: 256: public String toGenericString() 257: { 258: // 128 is a reasonable buffer initial size for constructor 259: CPStringBuilder sb = new CPStringBuilder(128); 260: Modifier.toString(getModifiers(), sb).append(' '); 261: Constructor.addTypeParameters(sb, getTypeParameters()); 262: sb.append(getGenericReturnType()).append(' '); 263: sb.append(getDeclaringClass().getName()).append('.'); 264: sb.append(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: * Invoke the method. Arguments are automatically unwrapped and widened, 285: * and the result is automatically wrapped, if needed.<p> 286: * 287: * If the method is static, <code>o</code> will be ignored. Otherwise, 288: * the method uses dynamic lookup as described in JLS 15.12.4.4. You cannot 289: * mimic the behavior of nonvirtual lookup (as in super.foo()). This means 290: * you will get a <code>NullPointerException</code> if <code>o</code> is 291: * null, and an <code>IllegalArgumentException</code> if it is incompatible 292: * with the declaring class of the method. If the method takes 0 arguments, 293: * you may use null or a 0-length array for <code>args</code>.<p> 294: * 295: * Next, if this Method enforces access control, your runtime context is 296: * evaluated, and you may have an <code>IllegalAccessException</code> if 297: * you could not acces this method in similar compiled code. If the method 298: * is static, and its class is uninitialized, you trigger class 299: * initialization, which may end in a 300: * <code>ExceptionInInitializerError</code>.<p> 301: * 302: * Finally, the method is invoked. If it completes normally, the return value 303: * will be null for a void method, a wrapped object for a primitive return 304: * method, or the actual return of an Object method. If it completes 305: * abruptly, the exception is wrapped in an 306: * <code>InvocationTargetException</code>. 307: * 308: * @param o the object to invoke the method on 309: * @param args the arguments to the method 310: * @return the return value of the method, wrapped in the appropriate 311: * wrapper if it is primitive 312: * @throws IllegalAccessException if the method could not normally be called 313: * by the Java code (i.e. it is not public) 314: * @throws IllegalArgumentException if the number of arguments is incorrect; 315: * if the arguments types are wrong even with a widening conversion; 316: * or if <code>o</code> is not an instance of the class or interface 317: * declaring this method 318: * @throws InvocationTargetException if the method throws an exception 319: * @throws NullPointerException if <code>o</code> is null and this field 320: * requires an instance 321: * @throws ExceptionInInitializerError if accessing a static method triggered 322: * class initialization, which then failed 323: */ 324: public Object invoke(Object o, Object... args) 325: throws IllegalAccessException, InvocationTargetException 326: { 327: return m.invoke(o, args); 328: } 329: 330: /** 331: * Returns an array of <code>TypeVariable</code> objects that represents 332: * the type variables declared by this constructor, in declaration order. 333: * An array of size zero is returned if this class has no type 334: * variables. 335: * 336: * @return the type variables associated with this class. 337: * @throws GenericSignatureFormatError if the generic signature does 338: * not conform to the format specified in the Virtual Machine 339: * specification, version 3. 340: * @since 1.5 341: */ 342: public TypeVariable<Method>[] getTypeParameters() 343: { 344: if (p == null) 345: { 346: String sig = m.getSignature(); 347: if (sig == null) 348: return (TypeVariable<Method>[]) new TypeVariable[0]; 349: p = new MethodSignatureParser(this, sig); 350: } 351: return p.getTypeParameters(); 352: } 353: 354: /** 355: * Returns an array of <code>Type</code> objects that represents 356: * the exception types declared by this method, in declaration order. 357: * An array of size zero is returned if this method declares no 358: * exceptions. 359: * 360: * @return the exception types declared by this method. 361: * @throws GenericSignatureFormatError if the generic signature does 362: * not conform to the format specified in the Virtual Machine 363: * specification, version 3. 364: * @since 1.5 365: */ 366: public Type[] getGenericExceptionTypes() 367: { 368: if (p == null) 369: { 370: String sig = m.getSignature(); 371: if (sig == null) 372: return getExceptionTypes(); 373: p = new MethodSignatureParser(this, sig); 374: } 375: return p.getGenericExceptionTypes(); 376: } 377: 378: /** 379: * Returns an array of <code>Type</code> objects that represents 380: * the parameter list for this method, in declaration order. 381: * An array of size zero is returned if this method takes no 382: * parameters. 383: * 384: * @return a list of the types of the method's parameters 385: * @throws GenericSignatureFormatError if the generic signature does 386: * not conform to the format specified in the Virtual Machine 387: * specification, version 3. 388: * @since 1.5 389: */ 390: public Type[] getGenericParameterTypes() 391: { 392: if (p == null) 393: { 394: String sig = m.getSignature(); 395: if (sig == null) 396: return getParameterTypes(); 397: p = new MethodSignatureParser(this, sig); 398: } 399: return p.getGenericParameterTypes(); 400: } 401: 402: /** 403: * Returns the return type of this method. 404: * 405: * @return the return type of this method 406: * @throws GenericSignatureFormatError if the generic signature does 407: * not conform to the format specified in the Virtual Machine 408: * specification, version 3. 409: * @since 1.5 410: */ 411: public Type getGenericReturnType() 412: { 413: if (p == null) 414: { 415: String sig = m.getSignature(); 416: if (sig == null) 417: return getReturnType(); 418: p = new MethodSignatureParser(this, sig); 419: } 420: return p.getGenericReturnType(); 421: } 422: 423: /** 424: * If this method is an annotation method, returns the default 425: * value for the method. If there is no default value, or if the 426: * method is not a member of an annotation type, returns null. 427: * Primitive types are wrapped. 428: * 429: * @throws TypeNotPresentException if the method returns a Class, 430: * and the class cannot be found 431: * 432: * @since 1.5 433: */ 434: public Object getDefaultValue() 435: { 436: return m.getDefaultValue(); 437: } 438: 439: /** 440: * <p> 441: * Return an array of arrays representing the annotations on each 442: * of the method's parameters. The outer array is aligned against 443: * the parameters of the method and is thus equal in length to 444: * the number of parameters (thus having a length zero if there are none). 445: * Each array element in the outer array contains an inner array which 446: * holds the annotations. This array has a length of zero if the parameter 447: * has no annotations. 448: * </p> 449: * <p> 450: * The returned annotations are serialized. Changing the annotations has 451: * no affect on the return value of future calls to this method. 452: * </p> 453: * 454: * @return an array of arrays which represents the annotations used on the 455: * parameters of this method. The order of the array elements 456: * matches the declaration order of the parameters. 457: * @since 1.5 458: */ 459: public Annotation[][] getParameterAnnotations() 460: { 461: return m.getParameterAnnotations(); 462: } 463: 464: /** 465: * Returns the element's annotation for the specified annotation type, 466: * or <code>null</code> if no such annotation exists. 467: * 468: * @param annotationClass the type of annotation to look for. 469: * @return this element's annotation for the specified type, or 470: * <code>null</code> if no such annotation exists. 471: * @throws NullPointerException if the annotation class is <code>null</code>. 472: */ 473: public <T extends Annotation> T getAnnotation(Class<T> annotationClass) 474: { 475: // Inescapable as the VM layer is 1.4 based. T will erase to Annotation anyway. 476: @SuppressWarnings("unchecked") 477: T ann = (T) m.getAnnotation(annotationClass); 478: return ann; 479: } 480: 481: /** 482: * Returns all annotations directly defined by the element. If there are 483: * no annotations directly associated with the element, then a zero-length 484: * array will be returned. The returned array may be modified by the client 485: * code, but this will have no effect on the annotation content of this 486: * class, and hence no effect on the return value of this method for 487: * future callers. 488: * 489: * @return the annotations directly defined by the element. 490: * @since 1.5 491: */ 492: public Annotation[] getDeclaredAnnotations() 493: { 494: return m.getDeclaredAnnotations(); 495: } 496: 497: }
GNU Classpath (0.98) |