001 // Method.java - Represent method of class or interface.
002
003 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2007 Free Software Foundation
004
005 This file is part of libgcj.
006
007 This software is copyrighted work licensed under the terms of the
008 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
009 details. */
010
011 package java.lang.reflect;
012
013 import gnu.gcj.RawData;
014 import gnu.java.lang.reflect.MethodSignatureParser;
015 import java.lang.annotation.Annotation;
016
017 /**
018 * The Method class represents a member method of a class. It also allows
019 * dynamic invocation, via reflection. This works for both static and
020 * instance methods. Invocation on Method objects knows how to do
021 * widening conversions, but throws {@link IllegalArgumentException} if
022 * a narrowing conversion would be necessary. You can query for information
023 * on this Method regardless of location, but invocation access may be limited
024 * by Java language access controls. If you can't do it in the compiler, you
025 * can't normally do it here either.<p>
026 *
027 * <B>Note:</B> This class returns and accepts types as Classes, even
028 * primitive types; there are Class types defined that represent each
029 * different primitive type. They are <code>java.lang.Boolean.TYPE,
030 * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
031 * byte.class</code>, etc. These are not to be confused with the
032 * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
033 * real classes.<p>
034 *
035 * Also note that this is not a serializable class. It is entirely feasible
036 * to make it serializable using the Externalizable interface, but this is
037 * on Sun, not me.
038 *
039 * @author John Keiser
040 * @author Eric Blake <ebb9@email.byu.edu>
041 * @author Tom Tromey <tromey@redhat.com>
042 * @see Member
043 * @see Class
044 * @see java.lang.Class#getMethod(String,Class[])
045 * @see java.lang.Class#getDeclaredMethod(String,Class[])
046 * @see java.lang.Class#getMethods()
047 * @see java.lang.Class#getDeclaredMethods()
048 * @since 1.1
049 * @status updated to 1.4
050 */
051 public final class Method
052 extends AccessibleObject implements Member, GenericDeclaration
053 {
054 static final int METHOD_MODIFIERS
055 = Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE
056 | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC
057 | Modifier.STATIC | Modifier.STRICT | Modifier.SYNCHRONIZED;
058
059 /**
060 * This class is uninstantiable.
061 */
062 private Method ()
063 {
064 }
065
066 /**
067 * Gets the class that declared this method, or the class where this method
068 * is a non-inherited member.
069 * @return the class that declared this member
070 */
071 public Class<?> getDeclaringClass()
072 {
073 return declaringClass;
074 }
075
076 /**
077 * Gets the name of this method.
078 * @return the name of this method
079 */
080 public native String getName ();
081
082 /**
083 * Return the raw modifiers for this method.
084 * @return the method's modifiers
085 */
086 private native int getModifiersInternal();
087
088 /**
089 * Gets the modifiers this method uses. Use the <code>Modifier</code>
090 * class to interpret the values. A method can only have a subset of the
091 * following modifiers: public, private, protected, abstract, static,
092 * final, synchronized, native, and strictfp.
093 *
094 * @return an integer representing the modifiers to this Member
095 * @see Modifier
096 */
097 public int getModifiers()
098 {
099 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 }