1. /*
  2. * @(#)Method.java 1.24 00/02/02
  3. *
  4. * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.lang.reflect;
  11. /**
  12. * A <code>Method</code> provides information about, and access to, a single method
  13. * on a class or interface. The reflected method may be a class method
  14. * or an instance method (including an abstract method).
  15. *
  16. * <p>A <code>Method</code> permits widening conversions to occur when matching the
  17. * actual parameters to invokewith the underlying method's formal
  18. * parameters, but it throws an <code>IllegalArgumentException</code> if a
  19. * narrowing conversion would occur.
  20. *
  21. * @see Member
  22. * @see java.lang.Class
  23. * @see java.lang.Class#getMethods()
  24. * @see java.lang.Class#getMethod(String, Class[])
  25. * @see java.lang.Class#getDeclaredMethods()
  26. * @see java.lang.Class#getDeclaredMethod(String, Class[])
  27. *
  28. * @author Nakul Saraiya
  29. */
  30. public final
  31. class Method extends AccessibleObject implements Member {
  32. private Class clazz;
  33. private int slot;
  34. private String name;
  35. private Class returnType;
  36. private Class[] parameterTypes;
  37. private Class[] exceptionTypes;
  38. private int modifiers;
  39. /**
  40. * Constructor. Only the Java Virtual Machine may construct a Method.
  41. */
  42. private Method() {}
  43. /**
  44. * Returns the <code>Class</code> object representing the class or interface
  45. * that declares the method represented by this <code>Method</code> object.
  46. */
  47. public Class getDeclaringClass() {
  48. return clazz;
  49. }
  50. /**
  51. * Returns the name of the method represented by this <code>Method</code>
  52. * object, as a <code>String</code>.
  53. */
  54. public String getName() {
  55. return name;
  56. }
  57. /**
  58. * Returns the Java language modifiers for the method represented
  59. * by this <code>Method</code> object, as an integer. The <code>Modifier</code> class should
  60. * be used to decode the modifiers.
  61. *
  62. * @see Modifier
  63. */
  64. public int getModifiers() {
  65. return modifiers;
  66. }
  67. /**
  68. * Returns a <code>Class</code> object that represents the formal return type
  69. * of the method represented by this <code>Method</code> object.
  70. */
  71. public Class getReturnType() {
  72. return returnType;
  73. }
  74. /**
  75. * Returns an array of <code>Class</code> objects that represent the formal
  76. * parameter types, in declaration order, of the method
  77. * represented by this <code>Method</code> object. Returns an array of length
  78. * 0 if the underlying method takes no parameters.
  79. */
  80. public Class[] getParameterTypes() {
  81. return copy(parameterTypes);
  82. }
  83. /**
  84. * Returns an array of <code>Class</code> objects that represent
  85. * the types of the exceptions declared to be thrown
  86. * by the underlying method
  87. * represented by this <code>Method</code> object. Returns an array of length
  88. * 0 if the method declares no exceptions in its <code>throws</code> clause.
  89. */
  90. public Class[] getExceptionTypes() {
  91. return copy(exceptionTypes);
  92. }
  93. /**
  94. * Compares this <code>Method</code> against the specified object. Returns
  95. * true if the objects are the same. Two <code>Methods</code> are the same if
  96. * they were declared by the same class and have the same name
  97. * and formal parameter types and return type.
  98. */
  99. public boolean equals(Object obj) {
  100. if (obj != null && obj instanceof Method) {
  101. Method other = (Method)obj;
  102. if ((getDeclaringClass() == other.getDeclaringClass())
  103. && (getName().equals(other.getName()))) {
  104. /* Avoid unnecessary cloning */
  105. Class[] params1 = parameterTypes;
  106. Class[] params2 = other.parameterTypes;
  107. if (params1.length == params2.length) {
  108. for (int i = 0; i < params1.length; i++) {
  109. if (params1[i] != params2[i])
  110. return false;
  111. }
  112. return true;
  113. }
  114. }
  115. }
  116. return false;
  117. }
  118. /**
  119. * Returns a hashcode for this <code>Method</code>. The hashcode is computed
  120. * as the exclusive-or of the hashcodes for the underlying
  121. * method's declaring class name and the method's name.
  122. */
  123. public int hashCode() {
  124. return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
  125. }
  126. /**
  127. * Returns a string describing this <code>Method</code>. The string is
  128. * formatted as the method access modifiers, if any, followed by
  129. * the method return type, followed by a space, followed by the
  130. * class declaring the method, followed by a period, followed by
  131. * the method name, followed by a parenthesized, comma-separated
  132. * list of the method's formal parameter types. If the method
  133. * throws checked exceptions, the parameter list is followed by a
  134. * space, followed by the word throws followed by a
  135. * comma-separated list of the thrown exception types.
  136. * For example:
  137. * <pre>
  138. * public boolean java.lang.Object.equals(java.lang.Object)
  139. * </pre>
  140. *
  141. * <p>The access modifiers are placed in canonical order as
  142. * specified by "The Java Language Specification". This is
  143. * <tt>public</tt>, <tt>protected</tt> or <tt>private</tt> first,
  144. * and then other modifiers in the following order:
  145. * <tt>abstract</tt>, <tt>static</tt>, <tt>final</tt>,
  146. * <tt>synchronized</tt> <tt>native</tt>.
  147. */
  148. public String toString() {
  149. try {
  150. StringBuffer sb = new StringBuffer();
  151. int mod = getModifiers();
  152. if (mod != 0) {
  153. sb.append(Modifier.toString(mod) + " ");
  154. }
  155. sb.append(Field.getTypeName(getReturnType()) + " ");
  156. sb.append(Field.getTypeName(getDeclaringClass()) + ".");
  157. sb.append(getName() + "(");
  158. Class[] params = parameterTypes; // avoid clone
  159. for (int j = 0; j < params.length; j++) {
  160. sb.append(Field.getTypeName(params[j]));
  161. if (j < (params.length - 1))
  162. sb.append(",");
  163. }
  164. sb.append(")");
  165. Class[] exceptions = exceptionTypes; // avoid clone
  166. if (exceptions.length > 0) {
  167. sb.append(" throws ");
  168. for (int k = 0; k < exceptions.length; k++) {
  169. sb.append(exceptions[k].getName());
  170. if (k < (exceptions.length - 1))
  171. sb.append(",");
  172. }
  173. }
  174. return sb.toString();
  175. } catch (Exception e) {
  176. return "<" + e + ">";
  177. }
  178. }
  179. /**
  180. * Invokes the underlying method represented by this <code>Method</code>
  181. * object, on the specified object with the specified parameters.
  182. * Individual parameters are automatically unwrapped to match
  183. * primitive formal parameters, and both primitive and reference
  184. * parameters are subject to widening conversions as
  185. * necessary. The value returned by the underlying method is
  186. * automatically wrapped in an object if it has a primitive type.
  187. *
  188. * <p>Method invocation proceeds with the following steps, in order:
  189. *
  190. * <p>If the underlying method is static, then the specified <code>obj</code>
  191. * argument is ignored. It may be null.
  192. *
  193. * <p>Otherwise, the method is an instance method. If the specified
  194. * object argument is null, the invocation throws a
  195. * <code>NullPointerException</code>. Otherwise, if the specified object
  196. * argument is not an instance of the class or interface declaring
  197. * the underlying method (or of a subclass or implementor
  198. * thereof) the invocation throws an
  199. * <code>IllegalArgumentException</code>.
  200. *
  201. * <p>If this <code>Method</code> object enforces Java language access control and
  202. * the underlying method is inaccessible, the invocation throws an
  203. * <code>IllegalAccessException</code>.
  204. *
  205. * <p>If the number of actual parameters supplied via <code>args</code> is
  206. * different from the number of formal parameters required by the
  207. * underlying method, the invocation throws an
  208. * <code>IllegalArgumentException</code>.
  209. *
  210. * <p>For each actual parameter in the supplied <code>args</code> array:
  211. *
  212. * <p>If the corresponding formal parameter has a primitive type, an
  213. * unwrapping conversion is attempted to convert the object value
  214. * to a value of a primitive type. If this attempt fails, the
  215. * invocation throws an <code>IllegalArgumentException</code>.
  216. *
  217. * <p>If, after possible unwrapping, the parameter value cannot be
  218. * converted to the corresponding formal parameter type by a
  219. * method invocation conversion, the invocation throws an
  220. * <code>IllegalArgumentException</code>.
  221. *
  222. * <p>If the underlying method is an instance method, it is invoked
  223. * using dynamic method lookup as documented in The Java Language
  224. * Specification, section 15.11.4.4; in particular, overriding
  225. * based on the runtime type of the target object will occur.
  226. *
  227. * <p>If the underlying method is static, the class that declared
  228. * the method is initialized if it has not already been initialized.
  229. * The underlying method is invoked directly.
  230. *
  231. * <p>Control transfers to the invoked method. If the method
  232. * completes abruptly by throwing an exception, the exception is
  233. * placed in an <code>InvocationTargetException</code> and thrown in turn to
  234. * the caller of invoke.
  235. *
  236. * <p>If the method completes normally, the value it returns is
  237. * returned to the caller of invoke; if the value has a primitive
  238. * type, it is first appropriately wrapped in an object. If the
  239. * underlying method return type is void, the invocation returns
  240. * null.
  241. *
  242. * @exception IllegalAccessException if the underlying method
  243. * is inaccessible.
  244. * @exception IllegalArgumentException if the number of actual and formal
  245. * parameters differ, or if an unwrapping conversion fails.
  246. * @exception InvocationTargetException if the underlying method
  247. * throws an exception.
  248. * @exception NullPointerException if the specified object is null
  249. * and the method is an instance method.
  250. * @exception ExceptionInInitializerError if the initialization
  251. * provoked by this method fails.
  252. */
  253. public native Object invoke(Object obj, Object[] args)
  254. throws IllegalAccessException, IllegalArgumentException,
  255. InvocationTargetException;
  256. /*
  257. * Avoid clone()
  258. */
  259. static Class[] copy(Class[] in) {
  260. int l = in.length;
  261. if (l == 0)
  262. return in;
  263. Class[] out = new Class[l];
  264. for (int i = 0; i < l; i++)
  265. out[i] = in[i];
  266. return out;
  267. }
  268. }