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 45 private final String name; 46 private final int modifiers; 47 private final Executable executable; 48 private final int index; 49 50 /** 51 * Package-private constructor for {@code Parameter}. 52 * 53 * If method parameter data is present in the classfile, then the 54 * JVM creates {@code Parameter} objects directly. If it is 55 * absent, however, then {@code Executable} uses this constructor 56 * to synthesize them. 57 * 58 * @param name The name of the parameter. 59 * @param modifiers The modifier flags for the parameter. 60 * @param executable The executable which defines this parameter. 61 * @param index The index of the parameter. 62 */ Parameter(String name, int modifiers, Executable executable, int index)63 Parameter(String name, 64 int modifiers, 65 Executable executable, 66 int index) { 67 this.name = name; 68 this.modifiers = modifiers; 69 this.executable = executable; 70 this.index = index; 71 } 72 73 /** 74 * Compares based on the executable and the index. 75 * 76 * @param obj The object to compare. 77 * @return Whether or not this is equal to the argument. 78 */ equals(Object obj)79 public boolean equals(Object obj) { 80 if(obj instanceof Parameter) { 81 Parameter other = (Parameter)obj; 82 return (other.executable.equals(executable) && 83 other.index == index); 84 } 85 return false; 86 } 87 88 /** 89 * Returns a hash code based on the executable's hash code and the 90 * index. 91 * 92 * @return A hash code based on the executable's hash code. 93 */ hashCode()94 public int hashCode() { 95 return executable.hashCode() ^ index; 96 } 97 98 // Android-changed: Removed references to the class file format. 99 /** 100 * Returns true if the parameter has a name; returns false otherwise. 101 * Whether a parameter has a name is determined by compiler options 102 * and whether the parameter is synthesized. 103 * 104 * @return true if and only if the parameter has a name 105 */ isNamePresent()106 public boolean isNamePresent() { 107 return executable.hasRealParameterData() && name != null; 108 } 109 110 /** 111 * Returns a string describing this parameter. The format is the 112 * modifiers for the parameter, if any, in canonical order as 113 * recommended by <cite>The Java™ Language 114 * Specification</cite>, followed by the fully- qualified type of 115 * the parameter (excluding the last [] if the parameter is 116 * variable arity), followed by "..." if the parameter is variable 117 * arity, followed by a space, followed by the name of the 118 * parameter. 119 * 120 * @return A string representation of the parameter and associated 121 * information. 122 */ toString()123 public String toString() { 124 final StringBuilder sb = new StringBuilder(); 125 final Type type = getParameterizedType(); 126 final String typename = type.getTypeName(); 127 128 sb.append(Modifier.toString(getModifiers())); 129 130 if(0 != modifiers) 131 sb.append(' '); 132 133 if(isVarArgs()) 134 sb.append(typename.replaceFirst("\\[\\]$", "...")); 135 else 136 sb.append(typename); 137 138 sb.append(' '); 139 sb.append(getName()); 140 141 return sb.toString(); 142 } 143 144 /** 145 * Return the {@code Executable} which declares this parameter. 146 * 147 * @return The {@code Executable} declaring this parameter. 148 */ getDeclaringExecutable()149 public Executable getDeclaringExecutable() { 150 return executable; 151 } 152 153 /** 154 * Get the modifier flags for this the parameter represented by 155 * this {@code Parameter} object. 156 * 157 * @return The modifier flags for this parameter. 158 */ getModifiers()159 public int getModifiers() { 160 return modifiers; 161 } 162 163 /** 164 * Returns the name of the parameter. If the parameter's name is 165 * {@linkplain #isNamePresent() present}, then this method returns 166 * the name provided by the class file. Otherwise, this method 167 * synthesizes a name of the form argN, where N is the index of 168 * the parameter in the descriptor of the method which declares 169 * the parameter. 170 * 171 * @return The name of the parameter, either provided by the class 172 * file or synthesized if the class file does not provide 173 * a name. 174 */ getName()175 public String getName() { 176 // Note: empty strings as paramete names are now outlawed. 177 // The .equals("") is for compatibility with current JVM 178 // behavior. It may be removed at some point. 179 if(name == null || name.equals("")) 180 return "arg" + index; 181 else 182 return name; 183 } 184 185 // Package-private accessor to the real name field. getRealName()186 String getRealName() { 187 return name; 188 } 189 190 /** 191 * Returns a {@code Type} object that identifies the parameterized 192 * type for the parameter represented by this {@code Parameter} 193 * object. 194 * 195 * @return a {@code Type} object identifying the parameterized 196 * type of the parameter represented by this object 197 */ getParameterizedType()198 public Type getParameterizedType() { 199 Type tmp = parameterTypeCache; 200 if (null == tmp) { 201 tmp = executable.getAllGenericParameterTypes()[index]; 202 parameterTypeCache = tmp; 203 } 204 205 return tmp; 206 } 207 208 private transient volatile Type parameterTypeCache = null; 209 210 /** 211 * Returns a {@code Class} object that identifies the 212 * declared type for the parameter represented by this 213 * {@code Parameter} object. 214 * 215 * @return a {@code Class} object identifying the declared 216 * type of the parameter represented by this object 217 */ getType()218 public Class<?> getType() { 219 Class<?> tmp = parameterClassCache; 220 if (null == tmp) { 221 tmp = executable.getParameterTypes()[index]; 222 parameterClassCache = tmp; 223 } 224 return tmp; 225 } 226 227 private transient volatile Class<?> parameterClassCache = null; 228 229 /** 230 * Returns {@code true} if this parameter is implicitly declared 231 * in source code; returns {@code false} otherwise. 232 * 233 * @return true if and only if this parameter is implicitly 234 * declared as defined by <cite>The Java™ Language 235 * Specification</cite>. 236 */ isImplicit()237 public boolean isImplicit() { 238 return Modifier.isMandated(getModifiers()); 239 } 240 241 /** 242 * Returns {@code true} if this parameter is neither implicitly 243 * nor explicitly declared in source code; returns {@code false} 244 * otherwise. 245 * 246 * @jls 13.1 The Form of a Binary 247 * @return true if and only if this parameter is a synthetic 248 * construct as defined by 249 * <cite>The Java™ Language Specification</cite>. 250 */ isSynthetic()251 public boolean isSynthetic() { 252 return Modifier.isSynthetic(getModifiers()); 253 } 254 255 /** 256 * Returns {@code true} if this parameter represents a variable 257 * argument list; returns {@code false} otherwise. 258 * 259 * @return {@code true} if an only if this parameter represents a 260 * variable argument list. 261 */ isVarArgs()262 public boolean isVarArgs() { 263 return executable.isVarArgs() && 264 index == executable.getParameterCount() - 1; 265 } 266 267 268 /** 269 * {@inheritDoc} 270 * @throws NullPointerException {@inheritDoc} 271 */ getAnnotation(Class<T> annotationClass)272 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 273 Objects.requireNonNull(annotationClass); 274 // Android-changed: Uses native code to obtain annotation information. 275 return getAnnotationNative(executable, index, annotationClass); 276 } 277 @FastNative getAnnotationNative( Executable executable, int parameterIndex, Class<A> annotationType)278 private static native <A extends Annotation> A getAnnotationNative( 279 Executable executable, int parameterIndex, Class<A> annotationType); 280 281 /** 282 * {@inheritDoc} 283 * @throws NullPointerException {@inheritDoc} 284 */ 285 @Override getAnnotationsByType(Class<T> annotationClass)286 public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { 287 // Android-changed: Uses AnnotatedElements instead. 288 return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass); 289 } 290 291 /** 292 * {@inheritDoc} 293 */ getDeclaredAnnotations()294 public Annotation[] getDeclaredAnnotations() { 295 return executable.getParameterAnnotations()[index]; 296 } 297 298 /** 299 * @throws NullPointerException {@inheritDoc} 300 */ getDeclaredAnnotation(Class<T> annotationClass)301 public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) { 302 // Only annotations on classes are inherited, for all other 303 // objects getDeclaredAnnotation is the same as 304 // getAnnotation. 305 return getAnnotation(annotationClass); 306 } 307 308 /** 309 * @throws NullPointerException {@inheritDoc} 310 */ 311 @Override getDeclaredAnnotationsByType(Class<T> annotationClass)312 public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) { 313 // Only annotations on classes are inherited, for all other 314 // objects getDeclaredAnnotations is the same as 315 // getAnnotations. 316 return getAnnotationsByType(annotationClass); 317 } 318 319 /** 320 * {@inheritDoc} 321 */ getAnnotations()322 public Annotation[] getAnnotations() { 323 return getDeclaredAnnotations(); 324 } 325 } 326