1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 /* 18 * Copyright (C) 2008 The Android Open Source Project 19 * 20 * Licensed under the Apache License, Version 2.0 (the "License"); 21 * you may not use this file except in compliance with the License. 22 * You may obtain a copy of the License at 23 * 24 * http://www.apache.org/licenses/LICENSE-2.0 25 * 26 * Unless required by applicable law or agreed to in writing, software 27 * distributed under the License is distributed on an "AS IS" BASIS, 28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 * See the License for the specific language governing permissions and 30 * limitations under the License. 31 */ 32 33 package java.lang.reflect; 34 35 import com.android.dex.Dex; 36 import java.lang.annotation.Annotation; 37 import java.util.Comparator; 38 import java.util.List; 39 import libcore.reflect.AnnotationAccess; 40 import libcore.reflect.Types; 41 42 /** 43 * This class represents a method. Information about the method can be accessed, 44 * and the method can be invoked dynamically. 45 */ 46 public final class Method extends AbstractMethod implements GenericDeclaration, Member { 47 48 /** 49 * Orders methods by their name, parameters and return type. 50 * 51 * @hide 52 */ 53 public static final Comparator<Method> ORDER_BY_SIGNATURE = new Comparator<Method>() { 54 @Override public int compare(Method a, Method b) { 55 if (a == b) { 56 return 0; 57 } 58 int comparison = a.getName().compareTo(b.getName()); 59 if (comparison == 0) { 60 comparison = a.artMethod.findOverriddenMethodIfProxy().compareParameters( 61 b.getParameterTypes()); 62 if (comparison == 0) { 63 // This is necessary for methods that have covariant return types. 64 Class<?> aReturnType = a.getReturnType(); 65 Class<?> bReturnType = b.getReturnType(); 66 if (aReturnType == bReturnType) { 67 comparison = 0; 68 } else { 69 comparison = aReturnType.getName().compareTo(bReturnType.getName()); 70 } 71 } 72 } 73 return comparison; 74 } 75 }; 76 77 /** 78 * @hide 79 */ 80 public Method(ArtMethod artMethod) { 81 super(artMethod); 82 } 83 84 ArtMethod getArtMethod() { 85 return artMethod; 86 } 87 88 public Annotation[] getAnnotations() { 89 return super.getAnnotations(); 90 } 91 92 /** 93 * Returns the modifiers for this method. The {@link Modifier} class should 94 * be used to decode the result. 95 * 96 * @return the modifiers for this method 97 * 98 * @see Modifier 99 */ 100 @Override public int getModifiers() { 101 return super.getModifiers(); 102 } 103 104 /** 105 * Indicates whether or not this method takes a variable number argument. 106 * 107 * @return {@code true} if a vararg is declared, {@code false} otherwise 108 */ 109 public boolean isVarArgs() { 110 return super.isVarArgs(); 111 } 112 113 /** 114 * Indicates whether or not this method is a bridge. 115 * 116 * @return {@code true} if this method is a bridge, {@code false} otherwise 117 */ 118 public boolean isBridge() { 119 return super.isBridge(); 120 121 } 122 123 /** 124 * Indicates whether or not this method is synthetic. 125 * 126 * @return {@code true} if this method is synthetic, {@code false} otherwise 127 */ 128 @Override public boolean isSynthetic() { 129 return super.isSynthetic(); 130 } 131 132 /** 133 * Returns the name of the method represented by this {@code Method} 134 * instance. 135 * 136 * @return the name of this method 137 */ 138 @Override public String getName() { 139 return ArtMethod.getMethodName(artMethod); 140 } 141 142 /** 143 * Returns the class that declares this method. 144 */ 145 @Override public Class<?> getDeclaringClass() { 146 return super.getDeclaringClass(); 147 } 148 149 /** 150 * Returns the exception types as an array of {@code Class} instances. If 151 * this method has no declared exceptions, an empty array is returned. 152 * 153 * @return the declared exception classes 154 */ 155 public Class<?>[] getExceptionTypes() { 156 if (getDeclaringClass().isProxy()) { 157 return getExceptionTypesNative(); 158 } else { 159 // TODO: use dex cache to speed looking up class 160 return AnnotationAccess.getExceptions(this); 161 } 162 } 163 164 private native Class<?>[] getExceptionTypesNative(); 165 166 /** 167 * Returns an array of {@code Class} objects associated with the parameter 168 * types of this method. If the method was declared with no parameters, an 169 * empty array will be returned. 170 * 171 * @return the parameter types 172 */ 173 @Override public Class<?>[] getParameterTypes() { 174 return artMethod.findOverriddenMethodIfProxy().getParameterTypes(); 175 } 176 177 /** 178 * Returns the {@code Class} associated with the return type of this 179 * method. 180 * 181 * @return the return type 182 */ 183 public Class<?> getReturnType() { 184 return artMethod.findOverriddenMethodIfProxy().getReturnType(); 185 } 186 187 /** 188 * {@inheritDoc} 189 * 190 * <p>Equivalent to {@code getDeclaringClass().getName().hashCode() ^ getName().hashCode()}. 191 */ 192 @Override public int hashCode() { 193 return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); 194 } 195 196 /** 197 * Returns true if {@code other} has the same declaring class, name, 198 * parameters and return type as this method. 199 */ 200 @Override public boolean equals(Object other) { 201 return super.equals(other); 202 } 203 204 /** 205 * Returns true if this and {@code method} have the same name and the same 206 * parameters in the same order. Such methods can share implementation if 207 * one method's return types is assignable to the other. 208 * 209 * @hide needed by Proxy 210 */ 211 boolean equalNameAndParameters(Method m) { 212 return getName().equals(m.getName()) && 213 ArtMethod.equalMethodParameters(artMethod,m.getParameterTypes()); 214 } 215 216 /** 217 * Returns the string representation of the method's declaration, including 218 * the type parameters. 219 * 220 * @return the string representation of this method 221 */ 222 public String toGenericString() { 223 return super.toGenericString(); 224 } 225 226 @Override public TypeVariable<Method>[] getTypeParameters() { 227 GenericInfo info = getMethodOrConstructorGenericInfo(); 228 return (TypeVariable<Method>[]) info.formalTypeParameters.clone(); 229 } 230 231 /** 232 * Returns the parameter types as an array of {@code Type} instances, in 233 * declaration order. If this method has no parameters, an empty array is 234 * returned. 235 * 236 * @return the parameter types 237 * 238 * @throws GenericSignatureFormatError 239 * if the generic method signature is invalid 240 * @throws TypeNotPresentException 241 * if any parameter type points to a missing type 242 * @throws MalformedParameterizedTypeException 243 * if any parameter type points to a type that cannot be 244 * instantiated for some reason 245 */ 246 public Type[] getGenericParameterTypes() { 247 return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false); 248 } 249 250 @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { 251 if (annotationType == null) { 252 throw new NullPointerException("annotationType == null"); 253 } 254 return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType); 255 } 256 257 /** 258 * Returns the exception types as an array of {@code Type} instances. If 259 * this method has no declared exceptions, an empty array will be returned. 260 * 261 * @return an array of generic exception types 262 * 263 * @throws GenericSignatureFormatError 264 * if the generic method signature is invalid 265 * @throws TypeNotPresentException 266 * if any exception type points to a missing type 267 * @throws MalformedParameterizedTypeException 268 * if any exception type points to a type that cannot be 269 * instantiated for some reason 270 */ 271 public Type[] getGenericExceptionTypes() { 272 return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false); 273 } 274 275 /** 276 * Returns the return type of this method as a {@code Type} instance. 277 * 278 * @return the return type of this method 279 * 280 * @throws GenericSignatureFormatError 281 * if the generic method signature is invalid 282 * @throws TypeNotPresentException 283 * if the return type points to a missing type 284 * @throws MalformedParameterizedTypeException 285 * if the return type points to a type that cannot be 286 * instantiated for some reason 287 */ 288 public Type getGenericReturnType() { 289 return Types.getType(getMethodOrConstructorGenericInfo().genericReturnType); 290 } 291 292 @Override public Annotation[] getDeclaredAnnotations() { 293 List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this); 294 return result.toArray(new Annotation[result.size()]); 295 } 296 297 @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) { 298 if (annotationType == null) { 299 throw new NullPointerException("annotationType == null"); 300 } 301 return AnnotationAccess.getDeclaredAnnotation(this, annotationType); 302 } 303 304 /** 305 * Returns an array of arrays that represent the annotations of the formal 306 * parameters of this method. If there are no parameters on this method, 307 * then an empty array is returned. If there are no annotations set, then 308 * and array of empty arrays is returned. 309 * 310 * @return an array of arrays of {@code Annotation} instances 311 */ 312 public Annotation[][] getParameterAnnotations() { 313 return artMethod.findOverriddenMethodIfProxy().getParameterAnnotations(); 314 } 315 316 /** 317 * Returns the default value for the annotation member represented by this 318 * method. 319 * 320 * @return the default value, or {@code null} if none 321 * 322 * @throws TypeNotPresentException 323 * if this annotation member is of type {@code Class} and no 324 * definition can be found 325 */ 326 public Object getDefaultValue() { 327 return AnnotationAccess.getDefaultValue(this); 328 } 329 330 /** 331 * Returns the result of dynamically invoking this method. Equivalent to 332 * {@code receiver.methodName(arg1, arg2, ... , argN)}. 333 * 334 * <p>If the method is static, the receiver argument is ignored (and may be null). 335 * 336 * <p>If the method takes no arguments, you can pass {@code (Object[]) null} instead of 337 * allocating an empty array. 338 * 339 * <p>If you're calling a varargs method, you need to pass an {@code Object[]} for the 340 * varargs parameter: that conversion is usually done in {@code javac}, not the VM, and 341 * the reflection machinery does not do this for you. (It couldn't, because it would be 342 * ambiguous.) 343 * 344 * <p>Reflective method invocation follows the usual process for method lookup. 345 * 346 * <p>If an exception is thrown during the invocation it is caught and 347 * wrapped in an InvocationTargetException. This exception is then thrown. 348 * 349 * <p>If the invocation completes normally, the return value itself is 350 * returned. If the method is declared to return a primitive type, the 351 * return value is boxed. If the return type is void, null is returned. 352 * 353 * @param receiver 354 * the object on which to call this method (or null for static methods) 355 * @param args 356 * the arguments to the method 357 * @return the result 358 * 359 * @throws NullPointerException 360 * if {@code receiver == null} for a non-static method 361 * @throws IllegalAccessException 362 * if this method is not accessible (see {@link AccessibleObject}) 363 * @throws IllegalArgumentException 364 * if the number of arguments doesn't match the number of parameters, the receiver 365 * is incompatible with the declaring class, or an argument could not be unboxed 366 * or converted by a widening conversion to the corresponding parameter type 367 * @throws InvocationTargetException 368 * if an exception was thrown by the invoked method 369 */ 370 public Object invoke(Object receiver, Object... args) 371 throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 372 return invoke(receiver, args, isAccessible()); 373 } 374 375 private native Object invoke(Object receiver, Object[] args, boolean accessible) 376 throws IllegalAccessException, IllegalArgumentException, InvocationTargetException; 377 378 /** 379 * Returns a string containing a concise, human-readable description of this 380 * method. The format of the string is: 381 * 382 * <ol> 383 * <li>modifiers (if any) 384 * <li>return type or 'void' 385 * <li>declaring class name 386 * <li>'(' 387 * <li>parameter types, separated by ',' (if any) 388 * <li>')' 389 * <li>'throws' plus exception types, separated by ',' (if any) 390 * </ol> 391 * 392 * For example: {@code public native Object 393 * java.lang.Method.invoke(Object,Object) throws 394 * IllegalAccessException,IllegalArgumentException 395 * ,InvocationTargetException} 396 * 397 * @return a printable representation for this method 398 */ 399 @Override 400 public String toString() { 401 StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); 402 403 if (result.length() != 0) { 404 result.append(' '); 405 } 406 result.append(getReturnType().getName()); 407 result.append(' '); 408 result.append(getDeclaringClass().getName()); 409 result.append('.'); 410 result.append(getName()); 411 result.append("("); 412 Class<?>[] parameterTypes = getParameterTypes(); 413 result.append(Types.toString(parameterTypes)); 414 result.append(")"); 415 Class<?>[] exceptionTypes = getExceptionTypes(); 416 if (exceptionTypes.length != 0) { 417 result.append(" throws "); 418 result.append(Types.toString(exceptionTypes)); 419 } 420 return result.toString(); 421 } 422 423 /** 424 * Returns the constructor's signature in non-printable form. This is called 425 * (only) from IO native code and needed for deriving the serialVersionUID 426 * of the class 427 * 428 * @return The constructor's signature. 429 */ 430 @SuppressWarnings("unused") 431 String getSignature() { 432 StringBuilder result = new StringBuilder(); 433 434 result.append('('); 435 Class<?>[] parameterTypes = getParameterTypes(); 436 for (Class<?> parameterType : parameterTypes) { 437 result.append(Types.getSignature(parameterType)); 438 } 439 result.append(')'); 440 result.append(Types.getSignature(getReturnType())); 441 442 return result.toString(); 443 } 444 } 445