A {@code Method} provides information about, and access to, a single method
on a class or interface. The reflected method may be a class method
or an instance method (including an abstract method).
A {@code Method} permits widening conversions to occur when matching the
actual parameters to invoke with the underlying method's formal
parameters, but it throws an {@code IllegalArgumentException} if a
narrowing conversion would occur.
Method from java.lang.reflect.Method Detail: |
Method copy() {
// This routine enables sharing of MethodAccessor objects
// among Method objects which refer to the same underlying
// method in the VM. (All of this contortion is only necessary
// because of the "accessibility" bit in AccessibleObject,
// which implicitly requires that new java.lang.reflect
// objects be fabricated for each reflective call on Class
// objects.)
Method res = new Method(clazz, name, parameterTypes, returnType,
exceptionTypes, modifiers, slot, signature,
annotations, parameterAnnotations, annotationDefault);
res.root = this;
// Might as well eagerly propagate this if already present
res.methodAccessor = methodAccessor;
return res;
}
Package-private routine (exposed to java.lang.Class via
ReflectAccess) which returns a copy of this Method. The copy's
"root" field points to this Method. |
public boolean equals(Object obj) {
if (obj != null && obj instanceof Method) {
Method other = (Method)obj;
if ((getDeclaringClass() == other.getDeclaringClass())
&& (getName() == other.getName())) {
if (!returnType.equals(other.getReturnType()))
return false;
/* Avoid unnecessary cloning */
Class< ? >[] params1 = parameterTypes;
Class< ? >[] params2 = other.parameterTypes;
if (params1.length == params2.length) {
for (int i = 0; i < params1.length; i++) {
if (params1[i] != params2[i])
return false;
}
return true;
}
}
}
return false;
}
Compares this {@code Method} against the specified object. Returns
true if the objects are the same. Two {@code Methods} are the same if
they were declared by the same class and have the same name
and formal parameter types and return type. |
public T getAnnotation(Class<T> annotationClass) {
if (annotationClass == null)
throw new NullPointerException();
return (T) declaredAnnotations().get(annotationClass);
}
|
public Annotation[] getDeclaredAnnotations() {
return AnnotationParser.toArray(declaredAnnotations());
}
|
public Class<?> getDeclaringClass() {
return clazz;
}
Returns the {@code Class} object representing the class or interface
that declares the method represented by this {@code Method} object. |
public Object getDefaultValue() {
if (annotationDefault == null)
return null;
Class< ? > memberType = AnnotationType.invocationHandlerReturnType(
getReturnType());
Object result = AnnotationParser.parseMemberValue(
memberType, ByteBuffer.wrap(annotationDefault),
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
getDeclaringClass());
if (result instanceof sun.reflect.annotation.ExceptionProxy)
throw new AnnotationFormatError("Invalid default: " + this);
return result;
}
Returns the default value for the annotation member represented by
this {@code Method} instance. If the member is of a primitive type,
an instance of the corresponding wrapper type is returned. Returns
null if no default is associated with the member, or if the method
instance does not represent a declared member of an annotation type. |
public Class<?>[] getExceptionTypes() {
return (Class< ? >[]) exceptionTypes.clone();
}
Returns an array of {@code Class} objects that represent
the types of the exceptions declared to be thrown
by the underlying method
represented by this {@code Method} object. Returns an array of length
0 if the method declares no exceptions in its {@code throws} clause. |
public Type[] getGenericExceptionTypes() {
Type[] result;
if (getGenericSignature() != null &&
((result = getGenericInfo().getExceptionTypes()).length > 0))
return result;
else
return getExceptionTypes();
}
Returns an array of {@code Type} objects that represent the
exceptions declared to be thrown by this {@code Method} object.
Returns an array of length 0 if the underlying method declares
no exceptions in its {@code throws} clause.
If an exception type is a type variable or a parameterized
type, it is created. Otherwise, it is resolved. |
public Type[] getGenericParameterTypes() {
if (getGenericSignature() != null)
return getGenericInfo().getParameterTypes();
else
return getParameterTypes();
}
Returns an array of {@code Type} objects that represent the formal
parameter types, in declaration order, of the method represented by
this {@code Method} object. Returns an array of length 0 if the
underlying method takes no parameters.
If a formal parameter type is a parameterized type,
the {@code Type} object returned for it must accurately reflect
the actual type parameters used in the source code.
If a formal parameter type is a type variable or a parameterized
type, it is created. Otherwise, it is resolved. |
public Type getGenericReturnType() {
if (getGenericSignature() != null) {
return getGenericInfo().getReturnType();
} else { return getReturnType();}
}
Returns a {@code Type} object that represents the formal return
type of the method represented by this {@code Method} object.
If the return type is a parameterized type,
the {@code Type} object returned must accurately reflect
the actual type parameters used in the source code.
If the return type is a type variable or a parameterized type, it
is created. Otherwise, it is resolved. |
MethodAccessor getMethodAccessor() {
return methodAccessor;
}
|
public int getModifiers() {
return modifiers;
}
Returns the Java language modifiers for the method represented
by this {@code Method} object, as an integer. The {@code Modifier} class should
be used to decode the modifiers. |
public String getName() {
return name;
}
Returns the name of the method represented by this {@code Method}
object, as a {@code String}. |
public Annotation[][] getParameterAnnotations() {
int numParameters = parameterTypes.length;
if (parameterAnnotations == null)
return new Annotation[numParameters][0];
Annotation[][] result = AnnotationParser.parseParameterAnnotations(
parameterAnnotations,
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
getDeclaringClass());
if (result.length != numParameters)
throw new java.lang.annotation.AnnotationFormatError(
"Parameter annotations don't match number of parameters");
return result;
}
Returns an array of arrays that represent the annotations on the formal
parameters, in declaration order, of the method represented by
this {@code Method} object. (Returns an array of length zero if the
underlying method is parameterless. If the method has one or more
parameters, a nested array of length zero is returned for each parameter
with no annotations.) The annotation objects contained in the returned
arrays are serializable. The caller of this method is free to modify
the returned arrays; it will have no effect on the arrays returned to
other callers. |
public Class<?>[] getParameterTypes() {
return (Class< ? >[]) parameterTypes.clone();
}
Returns an array of {@code Class} objects that represent the formal
parameter types, in declaration order, of the method
represented by this {@code Method} object. Returns an array of length
0 if the underlying method takes no parameters. |
public Class<?> getReturnType() {
return returnType;
}
Returns a {@code Class} object that represents the formal return type
of the method represented by this {@code Method} object. |
public TypeVariable<Method>[] getTypeParameters() {
if (getGenericSignature() != null)
return (TypeVariable< Method >[])getGenericInfo().getTypeParameters();
else
return (TypeVariable< Method >[])new TypeVariable[0];
}
Returns an array of {@code TypeVariable} objects that represent the
type variables declared by the generic declaration represented by this
{@code GenericDeclaration} object, in declaration order. Returns an
array of length 0 if the underlying generic declaration declares no type
variables. |
public int hashCode() {
return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
}
Returns a hashcode for this {@code Method}. The hashcode is computed
as the exclusive-or of the hashcodes for the underlying
method's declaring class name and the method's name. |
public Object invoke(Object obj,
Object args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class< ? > caller = Reflection.getCallerClass(1);
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
Invokes the underlying method represented by this {@code Method}
object, on the specified object with the specified parameters.
Individual parameters are automatically unwrapped to match
primitive formal parameters, and both primitive and reference
parameters are subject to method invocation conversions as
necessary.
If the underlying method is static, then the specified {@code obj}
argument is ignored. It may be null.
If the number of formal parameters required by the underlying method is
0, the supplied {@code args} array may be of length 0 or null.
If the underlying method is an instance method, it is invoked
using dynamic method lookup as documented in The Java Language
Specification, Second Edition, section 15.12.4.4; in particular,
overriding based on the runtime type of the target object will occur.
If the underlying method is static, the class that declared
the method is initialized if it has not already been initialized.
If the method completes normally, the value it returns is
returned to the caller of invoke; if the value has a primitive
type, it is first appropriately wrapped in an object. However,
if the value has the type of an array of a primitive type, the
elements of the array are not wrapped in objects; in
other words, an array of primitive type is returned. If the
underlying method return type is void, the invocation returns
null. |
public boolean isBridge() {
return (getModifiers() & Modifier.BRIDGE) != 0;
}
Returns {@code true} if this method is a bridge
method; returns {@code false} otherwise. |
public boolean isSynthetic() {
return Modifier.isSynthetic(getModifiers());
}
Returns {@code true} if this method is a synthetic
method; returns {@code false} otherwise. |
public boolean isVarArgs() {
return (getModifiers() & Modifier.VARARGS) != 0;
}
Returns {@code true} if this method was declared to take
a variable number of arguments; returns {@code false}
otherwise. |
void setMethodAccessor(MethodAccessor accessor) {
methodAccessor = accessor;
// Propagate up
if (root != null) {
root.setMethodAccessor(accessor);
}
}
|
public String toGenericString() {
try {
StringBuilder sb = new StringBuilder();
int mod = getModifiers() & Modifier.methodModifiers();
if (mod != 0) {
sb.append(Modifier.toString(mod)).append(' ');
}
TypeVariable< ? >[] typeparms = getTypeParameters();
if (typeparms.length > 0) {
boolean first = true;
sb.append('< ');
for(TypeVariable< ? > typeparm: typeparms) {
if (!first)
sb.append(',');
// Class objects can't occur here; no need to test
// and call Class.getName().
sb.append(typeparm.toString());
first = false;
}
sb.append(" > ");
}
Type genRetType = getGenericReturnType();
sb.append( ((genRetType instanceof Class< ? >)?
Field.getTypeName((Class< ? >)genRetType):genRetType.toString()))
.append(' ');
sb.append(Field.getTypeName(getDeclaringClass())).append('.');
sb.append(getName()).append('(');
Type[] params = getGenericParameterTypes();
for (int j = 0; j < params.length; j++) {
String param = (params[j] instanceof Class)?
Field.getTypeName((Class)params[j]):
(params[j].toString());
if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
param = param.replaceFirst("\\[\\]$", "...");
sb.append(param);
if (j < (params.length - 1))
sb.append(',');
}
sb.append(')');
Type[] exceptions = getGenericExceptionTypes();
if (exceptions.length > 0) {
sb.append(" throws ");
for (int k = 0; k < exceptions.length; k++) {
sb.append((exceptions[k] instanceof Class)?
((Class)exceptions[k]).getName():
exceptions[k].toString());
if (k < (exceptions.length - 1))
sb.append(',');
}
}
return sb.toString();
} catch (Exception e) {
return "< " + e + " >";
}
}
Returns a string describing this {@code Method}, including
type parameters. The string is formatted as the method access
modifiers, if any, followed by an angle-bracketed
comma-separated list of the method's type parameters, if any,
followed by the method's generic return type, followed by a
space, followed by the class declaring the method, followed by
a period, followed by the method name, followed by a
parenthesized, comma-separated list of the method's generic
formal parameter types.
If this method was declared to take a variable number of
arguments, instead of denoting the last parameter as
"Type[]", it is denoted as
"Type...".
A space is used to separate access modifiers from one another
and from the type parameters or return type. If there are no
type parameters, the type parameter list is elided; if the type
parameter list is present, a space separates the list from the
class name. If the method is declared to throw exceptions, the
parameter list is followed by a space, followed by the word
throws followed by a comma-separated list of the generic thrown
exception types. If there are no type parameters, the type
parameter list is elided.
The access modifiers are placed in canonical order as
specified by "The Java Language Specification". This is
{@code public}, {@code protected} or {@code private} first,
and then other modifiers in the following order:
{@code abstract}, {@code static}, {@code final},
{@code synchronized}, {@code native}, {@code strictfp}. |
public String toString() {
try {
StringBuilder sb = new StringBuilder();
int mod = getModifiers() & Modifier.methodModifiers();
if (mod != 0) {
sb.append(Modifier.toString(mod)).append(' ');
}
sb.append(Field.getTypeName(getReturnType())).append(' ');
sb.append(Field.getTypeName(getDeclaringClass())).append('.');
sb.append(getName()).append('(');
Class< ? >[] params = parameterTypes; // avoid clone
for (int j = 0; j < params.length; j++) {
sb.append(Field.getTypeName(params[j]));
if (j < (params.length - 1))
sb.append(',');
}
sb.append(')');
Class< ? >[] exceptions = exceptionTypes; // avoid clone
if (exceptions.length > 0) {
sb.append(" throws ");
for (int k = 0; k < exceptions.length; k++) {
sb.append(exceptions[k].getName());
if (k < (exceptions.length - 1))
sb.append(',');
}
}
return sb.toString();
} catch (Exception e) {
return "< " + e + " >";
}
}
Returns a string describing this {@code Method}. The string is
formatted as the method access modifiers, if any, followed by
the method return type, followed by a space, followed by the
class declaring the method, followed by a period, followed by
the method name, followed by a parenthesized, comma-separated
list of the method's formal parameter types. If the method
throws checked exceptions, the parameter list is followed by a
space, followed by the word throws followed by a
comma-separated list of the thrown exception types.
For example:
public boolean java.lang.Object.equals(java.lang.Object)
The access modifiers are placed in canonical order as
specified by "The Java Language Specification". This is
{@code public}, {@code protected} or {@code private} first,
and then other modifiers in the following order:
{@code abstract}, {@code static}, {@code final},
{@code synchronized}, {@code native}, {@code strictfp}. |