1 /* 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.lang.reflect; 26 27 import dalvik.annotation.optimization.FastNative; 28 import java.lang.annotation.*; 29 import java.util.HashMap; 30 import java.util.Map; 31 import java.util.Objects; 32 import libcore.reflect.AnnotatedElements; 33 34 /** 35 * Information about method parameters. 36 * 37 * A {@code Parameter} provides information about method parameters, 38 * including its name and modifiers. It also provides an alternate 39 * means of obtaining attributes for the parameter. 40 * 41 * @since 1.8 42 */ 43 public final class Parameter implements AnnotatedElement { 44 // Android-changed: Extensive modifications made throughout the class for ART. 45 // Android-removed: Type annotations runtime code. Not supported on Android. 46 // Android-removed: Annotation retrieval is implemented natively in ART. 47 48 private final String name; 49 private final int modifiers; 50 private final Executable executable; 51 private final int index; 52 53 /** 54 * Package-private constructor for {@code Parameter}. 55 * 56 * If method parameter data is present in the classfile, then the 57 * JVM creates {@code Parameter} objects directly. If it is 58 * absent, however, then {@code Executable} uses this constructor 59 * to synthesize them. 60 * 61 * @param name The name of the parameter. 62 * @param modifiers The modifier flags for the parameter. 63 * @param executable The executable which defines this parameter. 64 * @param index The index of the parameter. 65 */ Parameter(String name, int modifiers, Executable executable, int index)66 Parameter(String name, 67 int modifiers, 68 Executable executable, 69 int index) { 70 this.name = name; 71 this.modifiers = modifiers; 72 this.executable = executable; 73 this.index = index; 74 } 75 76 /** 77 * Compares based on the executable and the index. 78 * 79 * @param obj The object to compare. 80 * @return Whether or not this is equal to the argument. 81 */ equals(Object obj)82 public boolean equals(Object obj) { 83 if(obj instanceof Parameter) { 84 Parameter other = (Parameter)obj; 85 return (other.executable.equals(executable) && 86 other.index == index); 87 } 88 return false; 89 } 90 91 /** 92 * Returns a hash code based on the executable's hash code and the 93 * index. 94 * 95 * @return A hash code based on the executable's hash code. 96 */ hashCode()97 public int hashCode() { 98 return executable.hashCode() ^ index; 99 } 100 101 // Android-changed: Removed references in javadoc to the class file format. 102 /** 103 * Returns true if the parameter has a name; returns false otherwise. 104 * Whether a parameter has a name is determined by compiler options 105 * and whether the parameter is synthesized. 106 * 107 * @return true if and only if the parameter has a name 108 */ isNamePresent()109 public boolean isNamePresent() { 110 return executable.hasRealParameterData() && name != null; 111 } 112 113 /** 114 * Returns a string describing this parameter. The format is the 115 * modifiers for the parameter, if any, in canonical order as 116 * recommended by <cite>The Java™ Language 117 * Specification</cite>, followed by the fully- qualified type of 118 * the parameter (excluding the last [] if the parameter is 119 * variable arity), followed by "..." if the parameter is variable 120 * arity, followed by a space, followed by the name of the 121 * parameter. 122 * 123 * @return A string representation of the parameter and associated 124 * information. 125 */ toString()126 public String toString() { 127 final StringBuilder sb = new StringBuilder(); 128 final Type type = getParameterizedType(); 129 final String typename = type.getTypeName(); 130 131 sb.append(Modifier.toString(getModifiers())); 132 133 if(0 != modifiers) 134 sb.append(' '); 135 136 if(isVarArgs()) 137 sb.append(typename.replaceFirst("\\[\\]$", "...")); 138 else 139 sb.append(typename); 140 141 sb.append(' '); 142 sb.append(getName()); 143 144 return sb.toString(); 145 } 146 147 /** 148 * Return the {@code Executable} which declares this parameter. 149 * 150 * @return The {@code Executable} declaring this parameter. 151 */ getDeclaringExecutable()152 public Executable getDeclaringExecutable() { 153 return executable; 154 } 155 156 /** 157 * Get the modifier flags for this the parameter represented by 158 * this {@code Parameter} object. 159 * 160 * @return The modifier flags for this parameter. 161 */ getModifiers()162 public int getModifiers() { 163 return modifiers; 164 } 165 166 /** 167 * Returns the name of the parameter. If the parameter's name is 168 * {@linkplain #isNamePresent() present}, then this method returns 169 * the name provided by the class file. Otherwise, this method 170 * synthesizes a name of the form argN, where N is the index of 171 * the parameter in the descriptor of the method which declares 172 * the parameter. 173 * 174 * @return The name of the parameter, either provided by the class 175 * file or synthesized if the class file does not provide 176 * a name. 177 */ getName()178 public String getName() { 179 // Note: empty strings as parameter names are now outlawed. 180 // The .equals("") is for compatibility with current JVM 181 // behavior. It may be removed at some point. 182 if(name == null || name.equals("")) 183 return "arg" + index; 184 else 185 return name; 186 } 187 188 // Package-private accessor to the real name field. getRealName()189 String getRealName() { 190 return name; 191 } 192 193 /** 194 * Returns a {@code Type} object that identifies the parameterized 195 * type for the parameter represented by this {@code Parameter} 196 * object. 197 * 198 * @return a {@code Type} object identifying the parameterized 199 * type of the parameter represented by this object 200 */ getParameterizedType()201 public Type getParameterizedType() { 202 Type tmp = parameterTypeCache; 203 if (null == tmp) { 204 tmp = executable.getAllGenericParameterTypes()[index]; 205 parameterTypeCache = tmp; 206 } 207 208 return tmp; 209 } 210 211 private transient volatile Type parameterTypeCache; 212 213 /** 214 * Returns a {@code Class} object that identifies the 215 * declared type for the parameter represented by this 216 * {@code Parameter} object. 217 * 218 * @return a {@code Class} object identifying the declared 219 * type of the parameter represented by this object 220 */ getType()221 public Class<?> getType() { 222 Class<?> tmp = parameterClassCache; 223 if (null == tmp) { 224 tmp = executable.getParameterTypes()[index]; 225 parameterClassCache = tmp; 226 } 227 return tmp; 228 } 229 230 private transient volatile Class<?> parameterClassCache = null; 231 232 /** 233 * Returns {@code true} if this parameter is implicitly declared 234 * in source code; returns {@code false} otherwise. 235 * 236 * @return true if and only if this parameter is implicitly 237 * declared as defined by <cite>The Java™ Language 238 * Specification</cite>. 239 */ isImplicit()240 public boolean isImplicit() { 241 return Modifier.isMandated(getModifiers()); 242 } 243 244 /** 245 * Returns {@code true} if this parameter is neither implicitly 246 * nor explicitly declared in source code; returns {@code false} 247 * otherwise. 248 * 249 * @jls 13.1 The Form of a Binary 250 * @return true if and only if this parameter is a synthetic 251 * construct as defined by 252 * <cite>The Java™ Language Specification</cite>. 253 */ isSynthetic()254 public boolean isSynthetic() { 255 return Modifier.isSynthetic(getModifiers()); 256 } 257 258 /** 259 * Returns {@code true} if this parameter represents a variable 260 * argument list; returns {@code false} otherwise. 261 * 262 * @return {@code true} if an only if this parameter represents a 263 * variable argument list. 264 */ isVarArgs()265 public boolean isVarArgs() { 266 return executable.isVarArgs() && 267 index == executable.getParameterCount() - 1; 268 } 269 270 271 /** 272 * {@inheritDoc} 273 * @throws NullPointerException {@inheritDoc} 274 */ getAnnotation(Class<T> annotationClass)275 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 276 Objects.requireNonNull(annotationClass); 277 // Android-changed: getAnnotation(Class) Uses native code to obtain annotation information. 278 return getAnnotationNative(executable, index, annotationClass); 279 } 280 // Android-added: getAnnotation(Class) Uses native code to obtain annotation information. 281 @FastNative getAnnotationNative( Executable executable, int parameterIndex, Class<A> annotationType)282 private static native <A extends Annotation> A getAnnotationNative( 283 Executable executable, int parameterIndex, Class<A> annotationType); 284 285 /** 286 * {@inheritDoc} 287 * @throws NullPointerException {@inheritDoc} 288 */ 289 @Override getAnnotationsByType(Class<T> annotationClass)290 public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { 291 // Android-changed: getAnnotationsByType(Class), Android uses AnnotatedElements instead. 292 return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass); 293 } 294 295 /** 296 * {@inheritDoc} 297 */ getDeclaredAnnotations()298 public Annotation[] getDeclaredAnnotations() { 299 return executable.getParameterAnnotations()[index]; 300 } 301 302 /** 303 * @throws NullPointerException {@inheritDoc} 304 */ getDeclaredAnnotation(Class<T> annotationClass)305 public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) { 306 // Only annotations on classes are inherited, for all other 307 // objects getDeclaredAnnotation is the same as 308 // getAnnotation. 309 return getAnnotation(annotationClass); 310 } 311 312 /** 313 * @throws NullPointerException {@inheritDoc} 314 */ 315 @Override getDeclaredAnnotationsByType(Class<T> annotationClass)316 public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) { 317 // Only annotations on classes are inherited, for all other 318 // objects getDeclaredAnnotations is the same as 319 // getAnnotations. 320 return getAnnotationsByType(annotationClass); 321 } 322 323 /** 324 * {@inheritDoc} 325 */ getAnnotations()326 public Annotation[] getAnnotations() { 327 return getDeclaredAnnotations(); 328 } 329 330 } 331