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