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 dalvik.system.VMStack; 36 37 import java.lang.annotation.Annotation; 38 39 import org.apache.harmony.kernel.vm.StringUtils; 40 import org.apache.harmony.luni.lang.reflect.GenericSignatureParser; 41 import org.apache.harmony.luni.lang.reflect.ListOfTypes; 42 import org.apache.harmony.luni.lang.reflect.Types; 43 44 /** 45 * This class represents a constructor. Information about the constructor can be 46 * accessed, and the constructor can be invoked dynamically. 47 * 48 * @param <T> the class that declares this constructor 49 * 50 * @since Android 1.0 51 */ 52 public final class Constructor<T> extends AccessibleObject implements GenericDeclaration, 53 Member { 54 55 Class<T> declaringClass; 56 57 Class<?>[] parameterTypes; 58 59 Class<?>[] exceptionTypes; 60 61 ListOfTypes genericExceptionTypes; 62 ListOfTypes genericParameterTypes; 63 TypeVariable<Constructor<T>>[] formalTypeParameters; 64 private volatile boolean genericTypesAreInitialized = false; 65 initGenericTypes()66 private synchronized void initGenericTypes() { 67 if (!genericTypesAreInitialized) { 68 String signatureAttribute = getSignatureAttribute(); 69 GenericSignatureParser parser = new GenericSignatureParser( 70 VMStack.getCallingClassLoader2()); 71 parser.parseForConstructor(this, signatureAttribute); 72 formalTypeParameters = parser.formalTypeParameters; 73 genericParameterTypes = parser.parameterTypes; 74 genericExceptionTypes = parser.exceptionTypes; 75 genericTypesAreInitialized = true; 76 } 77 } 78 79 int slot; 80 81 /** 82 * Prevent this class from being instantiated. 83 */ Constructor()84 private Constructor(){ 85 //do nothing 86 } 87 88 /** 89 * Creates an instance of the class. Only called from native code, thus 90 * private. 91 * 92 * @param declaringClass 93 * the class this constructor object belongs to 94 * @param ptypes 95 * the parameter types of the constructor 96 * @param extypes 97 * the exception types of the constructor 98 * @param slot 99 * the slot of the constructor inside the VM class structure 100 */ Constructor(Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot)101 private Constructor (Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot){ 102 this.declaringClass = declaringClass; 103 this.parameterTypes = ptypes; 104 this.exceptionTypes = extypes; // may be null 105 this.slot = slot; 106 } 107 getSignatureAttribute()108 @Override /*package*/ String getSignatureAttribute() { 109 Object[] annotation = getSignatureAnnotation(declaringClass, slot); 110 111 if (annotation == null) { 112 return null; 113 } 114 115 return StringUtils.combineStrings(annotation); 116 } 117 118 /** 119 * Get the Signature annotation for this constructor. Returns null if not 120 * found. 121 */ getSignatureAnnotation(Class declaringClass, int slot)122 native private Object[] getSignatureAnnotation(Class declaringClass, 123 int slot); 124 getTypeParameters()125 public TypeVariable<Constructor<T>>[] getTypeParameters() { 126 initGenericTypes(); 127 return formalTypeParameters.clone(); 128 } 129 130 /** 131 * Returns the string representation of the constructor's declaration, 132 * including the type parameters. 133 * 134 * @return the string representation of the constructor's declaration 135 * 136 * @since Android 1.0 137 */ toGenericString()138 public String toGenericString() { 139 StringBuilder sb = new StringBuilder(80); 140 initGenericTypes(); 141 // append modifiers if any 142 int modifier = getModifiers(); 143 if (modifier != 0) { 144 sb.append(Modifier.toString(modifier & ~Modifier.VARARGS)).append(' '); 145 } 146 // append type parameters 147 if (formalTypeParameters != null && formalTypeParameters.length > 0) { 148 sb.append('<'); 149 for (int i = 0; i < formalTypeParameters.length; i++) { 150 appendGenericType(sb, formalTypeParameters[i]); 151 if (i < formalTypeParameters.length - 1) { 152 sb.append(", "); 153 } 154 } 155 sb.append("> "); 156 } 157 // append constructor name 158 appendArrayType(sb, getDeclaringClass()); 159 // append parameters 160 sb.append('('); 161 appendArrayGenericType(sb, 162 Types.getClonedTypeArray(genericParameterTypes)); 163 sb.append(')'); 164 // append exeptions if any 165 Type[] genericEceptionTypeArray = 166 Types.getClonedTypeArray(genericExceptionTypes); 167 if (genericEceptionTypeArray.length > 0) { 168 sb.append(" throws "); 169 appendArrayGenericType(sb, genericEceptionTypeArray); 170 } 171 return sb.toString(); 172 } 173 174 /** 175 * Returns the generic parameter types as an array of {@code Type} 176 * instances, in declaration order. If this constructor has no generic 177 * parameters, an empty array is returned. 178 * 179 * @return the parameter types 180 * 181 * @throws GenericSignatureFormatError 182 * if the generic constructor signature is invalid 183 * @throws TypeNotPresentException 184 * if any parameter type points to a missing type 185 * @throws MalformedParameterizedTypeException 186 * if any parameter type points to a type that cannot be 187 * instantiated for some reason 188 * 189 * @since Android 1.0 190 */ getGenericParameterTypes()191 public Type[] getGenericParameterTypes() { 192 initGenericTypes(); 193 return Types.getClonedTypeArray(genericParameterTypes); 194 } 195 196 /** 197 * Returns the exception types as an array of {@code Type} instances. If 198 * this constructor has no declared exceptions, an empty array will be 199 * returned. 200 * 201 * @return an array of generic exception types 202 * 203 * @throws GenericSignatureFormatError 204 * if the generic constructor signature is invalid 205 * @throws TypeNotPresentException 206 * if any exception type points to a missing type 207 * @throws MalformedParameterizedTypeException 208 * if any exception type points to a type that cannot be 209 * instantiated for some reason 210 * @since Android 1.0 211 */ getGenericExceptionTypes()212 public Type[] getGenericExceptionTypes() { 213 initGenericTypes(); 214 return Types.getClonedTypeArray(genericExceptionTypes); 215 } 216 217 @Override getDeclaredAnnotations()218 public Annotation[] getDeclaredAnnotations() { 219 return getDeclaredAnnotations(declaringClass, slot); 220 } getDeclaredAnnotations(Class declaringClass, int slot)221 native private Annotation[] getDeclaredAnnotations(Class declaringClass, 222 int slot); 223 224 /** 225 * Returns an array of arrays that represent the annotations of the formal 226 * parameters of this constructor. If there are no parameters on this 227 * constructor, then an empty array is returned. If there are no annotations 228 * set, then an array of empty arrays is returned. 229 * 230 * @return an array of arrays of {@code Annotation} instances 231 * 232 * @since Android 1.0 233 */ getParameterAnnotations()234 public Annotation[][] getParameterAnnotations() { 235 Annotation[][] parameterAnnotations 236 = getParameterAnnotations(declaringClass, slot); 237 if (parameterAnnotations.length == 0) { 238 return Method.noAnnotations(parameterTypes.length); 239 } 240 return parameterAnnotations; 241 } getParameterAnnotations(Class declaringClass, int slot)242 native private Annotation[][] getParameterAnnotations(Class declaringClass, 243 int slot); 244 245 /** 246 * Indicates whether or not this constructor takes a variable number of 247 * arguments. 248 * 249 * @return {@code true} if a vararg is declare, otherwise 250 * {@code false} 251 * 252 * @since Android 1.0 253 */ isVarArgs()254 public boolean isVarArgs() { 255 int mods = getConstructorModifiers(declaringClass, slot); 256 return (mods & Modifier.VARARGS) != 0; 257 } 258 259 /** 260 * Indicates whether or not this constructor is synthetic (artificially 261 * introduced by the compiler). 262 * 263 * @return {@code true} if this constructor is synthetic, {@code false} 264 * otherwise 265 * 266 * @since Android 1.0 267 */ isSynthetic()268 public boolean isSynthetic() { 269 int mods = getConstructorModifiers(declaringClass, slot); 270 return (mods & Modifier.SYNTHETIC) != 0; 271 } 272 273 /** 274 * Indicates whether or not the specified {@code object} is equal to this 275 * constructor. To be equal, the specified object must be an instance 276 * of {@code Constructor} with the same declaring class and parameter types 277 * as this constructor. 278 * 279 * @param object 280 * the object to compare 281 * 282 * @return {@code true} if the specified object is equal to this 283 * constructor, {@code false} otherwise 284 * 285 * @see #hashCode 286 * 287 * @since Android 1.0 288 */ 289 @Override equals(Object object)290 public boolean equals(Object object) { 291 return object instanceof Constructor && toString().equals(object.toString()); 292 } 293 294 /** 295 * Returns the class that declares this constructor. 296 * 297 * @return the declaring class 298 * 299 * @since Android 1.0 300 */ getDeclaringClass()301 public Class<T> getDeclaringClass() { 302 return declaringClass; 303 } 304 305 /** 306 * Returns the exception types as an array of {@code Class} instances. If 307 * this constructor has no declared exceptions, an empty array will be 308 * returned. 309 * 310 * @return the declared exception classes 311 * 312 * @since Android 1.0 313 */ getExceptionTypes()314 public Class<?>[] getExceptionTypes() { 315 if (exceptionTypes == null) 316 return new Class[0]; 317 return exceptionTypes; 318 } 319 320 /** 321 * Returns the modifiers for this constructor. The {@link Modifier} class 322 * should be used to decode the result. 323 * 324 * @return the modifiers for this constructor 325 * 326 * @see Modifier 327 * 328 * @since Android 1.0 329 */ getModifiers()330 public int getModifiers() { 331 return getConstructorModifiers(declaringClass, slot); 332 } 333 getConstructorModifiers(Class<T> declaringClass, int slot)334 private native int getConstructorModifiers(Class<T> declaringClass, int slot); 335 336 /** 337 * Returns the name of this constructor. 338 * 339 * @return the name of this constructor 340 * 341 * @since Android 1.0 342 */ getName()343 public String getName() { 344 return declaringClass.getName(); 345 } 346 347 /** 348 * Returns an array of the {@code Class} objects associated with the 349 * parameter types of this constructor. If the constructor was declared with 350 * no parameters, an empty array will be returned. 351 * 352 * @return the parameter types 353 * 354 * @since Android 1.0 355 */ getParameterTypes()356 public Class<?>[] getParameterTypes() { 357 return parameterTypes; 358 } 359 360 /** 361 * Returns the constructor's signature in non-printable form. This is called 362 * (only) from IO native code and needed for deriving the serialVersionUID 363 * of the class 364 * 365 * @return the constructor's signature 366 */ 367 @SuppressWarnings("unused") getSignature()368 private String getSignature() { 369 StringBuilder result = new StringBuilder(); 370 371 result.append('('); 372 for(int i = 0; i < parameterTypes.length; i++) { 373 result.append(getSignature(parameterTypes[i])); 374 } 375 result.append(")V"); 376 377 return result.toString(); 378 } 379 380 /** 381 * Returns an integer hash code for this constructor. Constructors which are 382 * equal return the same value for this method. The hash code for a 383 * Constructor is the hash code of the name of the declaring class. 384 * 385 * @return the hash code 386 * 387 * @see #equals 388 * 389 * @since Android 1.0 390 */ 391 @Override hashCode()392 public int hashCode() { 393 return declaringClass.getName().hashCode(); 394 } 395 396 /** 397 * Returns a new instance of the declaring class, initialized by dynamically 398 * invoking the constructor represented by this {@code Constructor} object. 399 * This reproduces the effect of {@code new declaringClass(arg1, arg2, ... , 400 * argN)} This method performs the following: 401 * <ul> 402 * <li>A new instance of the declaring class is created. If the declaring 403 * class cannot be instantiated (i.e. abstract class, an interface, an array 404 * type, or a primitive type) then an InstantiationException is thrown.</li> 405 * <li>If this Constructor object is enforcing access control (see 406 * {@link AccessibleObject}) and this constructor is not accessible from the 407 * current context, an IllegalAccessException is thrown.</li> 408 * <li>If the number of arguments passed and the number of parameters do not 409 * match, an IllegalArgumentException is thrown.</li> 410 * <li>For each argument passed: 411 * <ul> 412 * <li>If the corresponding parameter type is a primitive type, the argument 413 * is unwrapped. If the unwrapping fails, an IllegalArgumentException is 414 * thrown.</li> 415 * <li>If the resulting argument cannot be converted to the parameter type 416 * via a widening conversion, an IllegalArgumentException is thrown.</li> 417 * </ul> 418 * <li>The constructor represented by this {@code Constructor} object is 419 * then invoked. If an exception is thrown during the invocation, it is 420 * caught and wrapped in an InvocationTargetException. This exception is 421 * then thrown. If the invocation completes normally, the newly initialized 422 * object is returned. 423 * </ul> 424 * 425 * @param args 426 * the arguments to the constructor 427 * 428 * @return the new, initialized, object 429 * 430 * @exception InstantiationException 431 * if the class cannot be instantiated 432 * @exception IllegalAccessException 433 * if this constructor is not accessible 434 * @exception IllegalArgumentException 435 * if an incorrect number of arguments are passed, or an 436 * argument could not be converted by a widening conversion 437 * @exception InvocationTargetException 438 * if an exception was thrown by the invoked constructor 439 * 440 * @see AccessibleObject 441 * 442 * @since Android 1.0 443 */ newInstance(Object... args)444 public T newInstance(Object... args) throws InstantiationException, IllegalAccessException, 445 IllegalArgumentException, InvocationTargetException { 446 return constructNative (args, declaringClass, parameterTypes, slot, flag); 447 } 448 constructNative(Object[] args, Class<T> declaringClass, Class<?>[] parameterTypes, int slot, boolean noAccessCheck)449 private native T constructNative(Object[] args, Class<T> declaringClass, 450 Class<?>[] parameterTypes, int slot, 451 boolean noAccessCheck) throws InstantiationException, IllegalAccessException, 452 InvocationTargetException; 453 454 /** 455 * Returns a string containing a concise, human-readable description of this 456 * constructor. The format of the string is: 457 * 458 * <ol> 459 * <li>modifiers (if any) 460 * <li>declaring class name 461 * <li>'(' 462 * <li>parameter types, separated by ',' (if any) 463 * <li>')' 464 * <li>'throws' plus exception types, separated by ',' (if any) 465 * </ol> 466 * 467 * For example: 468 * {@code public String(byte[],String) throws UnsupportedEncodingException} 469 * 470 * @return a printable representation for this constructor 471 * 472 * @since Android 1.0 473 */ 474 @Override toString()475 public String toString() { 476 StringBuilder result = new StringBuilder(Modifier.toString(getModifiers())); 477 478 if (result.length() != 0) 479 result.append(' '); 480 result.append(declaringClass.getName()); 481 result.append("("); 482 result.append(toString(parameterTypes)); 483 result.append(")"); 484 if (exceptionTypes != null && exceptionTypes.length != 0) { 485 result.append(" throws "); 486 result.append(toString(exceptionTypes)); 487 } 488 489 return result.toString(); 490 } 491 } 492