GNU Classpath (0.20) | |
Frames | No Frames |
1: /* java.lang.reflect.Method - reflection of Java methods 2: Copyright (C) 1998, 2001, 2002 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 java.util.Arrays; 42: 43: /** 44: * The Method class represents a member method of a class. It also allows 45: * dynamic invocation, via reflection. This works for both static and 46: * instance methods. Invocation on Method objects knows how to do 47: * widening conversions, but throws {@link IllegalArgumentException} if 48: * a narrowing conversion would be necessary. You can query for information 49: * on this Method regardless of location, but invocation access may be limited 50: * by Java language access controls. If you can't do it in the compiler, you 51: * can't normally do it here either.<p> 52: * 53: * <B>Note:</B> This class returns and accepts types as Classes, even 54: * primitive types; there are Class types defined that represent each 55: * different primitive type. They are <code>java.lang.Boolean.TYPE, 56: * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class, 57: * byte.class</code>, etc. These are not to be confused with the 58: * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are 59: * real classes.<p> 60: * 61: * Also note that this is not a serializable class. It is entirely feasible 62: * to make it serializable using the Externalizable interface, but this is 63: * on Sun, not me. 64: * 65: * @author John Keiser 66: * @author Eric Blake <ebb9@email.byu.edu> 67: * @see Member 68: * @see Class 69: * @see java.lang.Class#getMethod(String,Object[]) 70: * @see java.lang.Class#getDeclaredMethod(String,Object[]) 71: * @see java.lang.Class#getMethods() 72: * @see java.lang.Class#getDeclaredMethods() 73: * @since 1.1 74: * @status updated to 1.4 75: */ 76: public final class Method 77: extends AccessibleObject implements Member 78: { 79: Class declaringClass; 80: String name; 81: int slot; 82: 83: /** 84: * This class is uninstantiable. 85: */ 86: private Method(Class declaringClass, String name, int slot) 87: { 88: this.declaringClass = declaringClass; 89: this.name = name; 90: this.slot = slot; 91: } 92: 93: /** 94: * Gets the class that declared this method, or the class where this method 95: * is a non-inherited member. 96: * @return the class that declared this member 97: */ 98: public Class getDeclaringClass() 99: { 100: return declaringClass; 101: } 102: 103: /** 104: * Gets the name of this method. 105: * @return the name of this method 106: */ 107: public String getName() 108: { 109: return name; 110: } 111: 112: /** 113: * Gets the modifiers this method uses. Use the <code>Modifier</code> 114: * class to interpret the values. A method can only have a subset of the 115: * following modifiers: public, private, protected, abstract, static, 116: * final, synchronized, native, and strictfp. 117: * 118: * @return an integer representing the modifiers to this Member 119: * @see Modifier 120: */ 121: public native int getModifiers(); 122: 123: /** 124: * Gets the return type of this method. 125: * @return the type of this method 126: */ 127: public native Class getReturnType(); 128: 129: /** 130: * Get the parameter list for this method, in declaration order. If the 131: * method takes no parameters, returns a 0-length array (not null). 132: * 133: * @return a list of the types of the method's parameters 134: */ 135: public native Class[] getParameterTypes(); 136: 137: /** 138: * Get the exception types this method says it throws, in no particular 139: * order. If the method has no throws clause, returns a 0-length array 140: * (not null). 141: * 142: * @return a list of the types in the method's throws clause 143: */ 144: public native Class[] getExceptionTypes(); 145: 146: /** 147: * Compare two objects to see if they are semantically equivalent. 148: * Two Methods are semantically equivalent if they have the same declaring 149: * class, name, parameter list, and return type. 150: * 151: * @param o the object to compare to 152: * @return <code>true</code> if they are equal; <code>false</code> if not 153: */ 154: public boolean equals(Object o) 155: { 156: // Implementation note: 157: // The following is a correct but possibly slow implementation. 158: // 159: // This class has a private field 'slot' that could be used by 160: // the VM implementation to "link" a particular method to a Class. 161: // In that case equals could be simply implemented as: 162: // 163: // if (o instanceof Method) 164: // { 165: // Method m = (Method)o; 166: // return m.declaringClass == this.declaringClass 167: // && m.slot == this.slot; 168: // } 169: // return false; 170: // 171: // If a VM uses the Method class as their native/internal representation 172: // then just using the following would be optimal: 173: // 174: // return this == o; 175: // 176: if (!(o instanceof Method)) 177: return false; 178: Method that = (Method)o; 179: if (this.getDeclaringClass() != that.getDeclaringClass()) 180: return false; 181: if (!this.getName().equals(that.getName())) 182: return false; 183: if (this.getReturnType() != that.getReturnType()) 184: return false; 185: if (!Arrays.equals(this.getParameterTypes(), that.getParameterTypes())) 186: return false; 187: return true; 188: } 189: 190: /** 191: * Get the hash code for the Method. The Method hash code is the hash code 192: * of its name XOR'd with the hash code of its class name. 193: * 194: * @return the hash code for the object 195: */ 196: public int hashCode() 197: { 198: return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); 199: } 200: 201: /** 202: * Get a String representation of the Method. A Method's String 203: * representation is "<modifiers> <returntype> 204: * <methodname>(<paramtypes>) throws <exceptions>", where 205: * everything after ')' is omitted if there are no exceptions.<br> Example: 206: * <code>public static int run(java.lang.Runnable,int)</code> 207: * 208: * @return the String representation of the Method 209: */ 210: public String toString() 211: { 212: // 128 is a reasonable buffer initial size for constructor 213: StringBuffer sb = new StringBuffer(128); 214: Modifier.toString(getModifiers(), sb).append(' '); 215: sb.append(getUserTypeName(getReturnType().getName())).append(' '); 216: sb.append(getDeclaringClass().getName()).append('.'); 217: sb.append(getName()).append('('); 218: Class[] c = getParameterTypes(); 219: if (c.length > 0) 220: { 221: sb.append(getUserTypeName(c[0].getName())); 222: for (int i = 1; i < c.length; i++) 223: sb.append(',').append(getUserTypeName(c[i].getName())); 224: } 225: sb.append(')'); 226: c = getExceptionTypes(); 227: if (c.length > 0) 228: { 229: sb.append(" throws ").append(c[0].getName()); 230: for (int i = 1; i < c.length; i++) 231: sb.append(',').append(c[i].getName()); 232: } 233: return sb.toString(); 234: } 235: 236: private static String getUserTypeName(String typeSpec) 237: { 238: int pos = 0; 239: String typeName = ""; 240: String arrayPart = ""; 241: 242: while (typeSpec.charAt(pos) == '[') 243: { 244: arrayPart += "[]"; 245: ++pos; 246: } 247: 248: switch (typeSpec.charAt(pos)) 249: { 250: case 'Z': 251: typeName = "boolean"; 252: break; 253: case 'B': 254: typeName = "byte"; 255: break; 256: case 'C': 257: typeName = "char"; 258: break; 259: case 'D': 260: typeName = "double"; 261: break; 262: case 'F': 263: typeName = "float"; 264: break; 265: case 'I': 266: typeName = "int"; 267: break; 268: case 'J': 269: typeName = "long"; 270: break; 271: case 'S': 272: typeName = "short"; 273: break; 274: case 'L': 275: typeName = typeSpec.substring(pos + 1, typeSpec.length() - 1); 276: break; 277: default: 278: typeName = typeSpec; 279: break; 280: } 281: 282: return typeName + arrayPart; 283: } 284: 285: /** 286: * Invoke the method. Arguments are automatically unwrapped and widened, 287: * and the result is automatically wrapped, if needed.<p> 288: * 289: * If the method is static, <code>o</code> will be ignored. Otherwise, 290: * the method uses dynamic lookup as described in JLS 15.12.4.4. You cannot 291: * mimic the behavior of nonvirtual lookup (as in super.foo()). This means 292: * you will get a <code>NullPointerException</code> if <code>o</code> is 293: * null, and an <code>IllegalArgumentException</code> if it is incompatible 294: * with the declaring class of the method. If the method takes 0 arguments, 295: * you may use null or a 0-length array for <code>args</code>.<p> 296: * 297: * Next, if this Method enforces access control, your runtime context is 298: * evaluated, and you may have an <code>IllegalAccessException</code> if 299: * you could not acces this method in similar compiled code. If the method 300: * is static, and its class is uninitialized, you trigger class 301: * initialization, which may end in a 302: * <code>ExceptionInInitializerError</code>.<p> 303: * 304: * Finally, the method is invoked. If it completes normally, the return value 305: * will be null for a void method, a wrapped object for a primitive return 306: * method, or the actual return of an Object method. If it completes 307: * abruptly, the exception is wrapped in an 308: * <code>InvocationTargetException</code>. 309: * 310: * @param o the object to invoke the method on 311: * @param args the arguments to the method 312: * @return the return value of the method, wrapped in the appropriate 313: * wrapper if it is primitive 314: * @throws IllegalAccessException if the method could not normally be called 315: * by the Java code (i.e. it is not public) 316: * @throws IllegalArgumentException if the number of arguments is incorrect; 317: * if the arguments types are wrong even with a widening conversion; 318: * or if <code>o</code> is not an instance of the class or interface 319: * declaring this method 320: * @throws InvocationTargetException if the method throws an exception 321: * @throws NullPointerException if <code>o</code> is null and this field 322: * requires an instance 323: * @throws ExceptionInInitializerError if accessing a static method triggered 324: * class initialization, which then failed 325: */ 326: public Object invoke(Object o, Object[] args) 327: throws IllegalAccessException, InvocationTargetException 328: { 329: return invokeNative(o, args, declaringClass, slot); 330: } 331: 332: /* 333: * NATIVE HELPERS 334: */ 335: 336: private native Object invokeNative(Object o, Object[] args, 337: Class declaringClass, int slot) 338: throws IllegalAccessException, InvocationTargetException; 339: }
GNU Classpath (0.20) |