0001 /*
0002 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.lang.reflect;
0027
0028 import sun.reflect.FieldAccessor;
0029 import sun.reflect.Reflection;
0030 import sun.reflect.generics.repository.FieldRepository;
0031 import sun.reflect.generics.factory.CoreReflectionFactory;
0032 import sun.reflect.generics.factory.GenericsFactory;
0033 import sun.reflect.generics.scope.ClassScope;
0034 import java.lang.annotation.Annotation;
0035 import java.util.Map;
0036 import sun.reflect.annotation.AnnotationParser;
0037
0038 /**
0039 * A {@code Field} provides information about, and dynamic access to, a
0040 * single field of a class or an interface. The reflected field may
0041 * be a class (static) field or an instance field.
0042 *
0043 * <p>A {@code Field} permits widening conversions to occur during a get or
0044 * set access operation, but throws an {@code IllegalArgumentException} if a
0045 * narrowing conversion would occur.
0046 *
0047 * @see Member
0048 * @see java.lang.Class
0049 * @see java.lang.Class#getFields()
0050 * @see java.lang.Class#getField(String)
0051 * @see java.lang.Class#getDeclaredFields()
0052 * @see java.lang.Class#getDeclaredField(String)
0053 *
0054 * @author Kenneth Russell
0055 * @author Nakul Saraiya
0056 */
0057 public final class Field extends AccessibleObject implements Member {
0058
0059 private Class clazz;
0060 private int slot;
0061 // This is guaranteed to be interned by the VM in the 1.4
0062 // reflection implementation
0063 private String name;
0064 private Class type;
0065 private int modifiers;
0066 // Generics and annotations support
0067 private transient String signature;
0068 // generic info repository; lazily initialized
0069 private transient FieldRepository genericInfo;
0070 private byte[] annotations;
0071 // Cached field accessor created without override
0072 private FieldAccessor fieldAccessor;
0073 // Cached field accessor created with override
0074 private FieldAccessor overrideFieldAccessor;
0075 // For sharing of FieldAccessors. This branching structure is
0076 // currently only two levels deep (i.e., one root Field and
0077 // potentially many Field objects pointing to it.)
0078 private Field root;
0079
0080 // More complicated security check cache needed here than for
0081 // Class.newInstance() and Constructor.newInstance()
0082 private Class securityCheckCache;
0083 private Class securityCheckTargetClassCache;
0084
0085 // Generics infrastructure
0086
0087 private String getGenericSignature() {
0088 return signature;
0089 }
0090
0091 // Accessor for factory
0092 private GenericsFactory getFactory() {
0093 Class<?> c = getDeclaringClass();
0094 // create scope and factory
0095 return CoreReflectionFactory.make(c, ClassScope.make(c));
0096 }
0097
0098 // Accessor for generic info repository
0099 private FieldRepository getGenericInfo() {
0100 // lazily initialize repository if necessary
0101 if (genericInfo == null) {
0102 // create and cache generic info repository
0103 genericInfo = FieldRepository.make(getGenericSignature(),
0104 getFactory());
0105 }
0106 return genericInfo; //return cached repository
0107 }
0108
0109 /**
0110 * Package-private constructor used by ReflectAccess to enable
0111 * instantiation of these objects in Java code from the java.lang
0112 * package via sun.reflect.LangReflectAccess.
0113 */
0114 Field(Class declaringClass, String name, Class type, int modifiers,
0115 int slot, String signature, byte[] annotations) {
0116 this .clazz = declaringClass;
0117 this .name = name;
0118 this .type = type;
0119 this .modifiers = modifiers;
0120 this .slot = slot;
0121 this .signature = signature;
0122 this .annotations = annotations;
0123 }
0124
0125 /**
0126 * Package-private routine (exposed to java.lang.Class via
0127 * ReflectAccess) which returns a copy of this Field. The copy's
0128 * "root" field points to this Field.
0129 */
0130 Field copy() {
0131 // This routine enables sharing of FieldAccessor objects
0132 // among Field objects which refer to the same underlying
0133 // method in the VM. (All of this contortion is only necessary
0134 // because of the "accessibility" bit in AccessibleObject,
0135 // which implicitly requires that new java.lang.reflect
0136 // objects be fabricated for each reflective call on Class
0137 // objects.)
0138 Field res = new Field(clazz, name, type, modifiers, slot,
0139 signature, annotations);
0140 res.root = this ;
0141 // Might as well eagerly propagate this if already present
0142 res.fieldAccessor = fieldAccessor;
0143 res.overrideFieldAccessor = overrideFieldAccessor;
0144 return res;
0145 }
0146
0147 /**
0148 * Returns the {@code Class} object representing the class or interface
0149 * that declares the field represented by this {@code Field} object.
0150 */
0151 public Class<?> getDeclaringClass() {
0152 return clazz;
0153 }
0154
0155 /**
0156 * Returns the name of the field represented by this {@code Field} object.
0157 */
0158 public String getName() {
0159 return name;
0160 }
0161
0162 /**
0163 * Returns the Java language modifiers for the field represented
0164 * by this {@code Field} object, as an integer. The {@code Modifier} class should
0165 * be used to decode the modifiers.
0166 *
0167 * @see Modifier
0168 */
0169 public int getModifiers() {
0170 return modifiers;
0171 }
0172
0173 /**
0174 * Returns {@code true} if this field represents an element of
0175 * an enumerated type; returns {@code false} otherwise.
0176 *
0177 * @return {@code true} if and only if this field represents an element of
0178 * an enumerated type.
0179 * @since 1.5
0180 */
0181 public boolean isEnumConstant() {
0182 return (getModifiers() & Modifier.ENUM) != 0;
0183 }
0184
0185 /**
0186 * Returns {@code true} if this field is a synthetic
0187 * field; returns {@code false} otherwise.
0188 *
0189 * @return true if and only if this field is a synthetic
0190 * field as defined by the Java Language Specification.
0191 * @since 1.5
0192 */
0193 public boolean isSynthetic() {
0194 return Modifier.isSynthetic(getModifiers());
0195 }
0196
0197 /**
0198 * Returns a {@code Class} object that identifies the
0199 * declared type for the field represented by this
0200 * {@code Field} object.
0201 *
0202 * @return a {@code Class} object identifying the declared
0203 * type of the field represented by this object
0204 */
0205 public Class<?> getType() {
0206 return type;
0207 }
0208
0209 /**
0210 * Returns a {@code Type} object that represents the declared type for
0211 * the field represented by this {@code Field} object.
0212 *
0213 * <p>If the {@code Type} is a parameterized type, the
0214 * {@code Type} object returned must accurately reflect the
0215 * actual type parameters used in the source code.
0216 *
0217 * <p>If the type of the underlying field is a type variable or a
0218 * parameterized type, it is created. Otherwise, it is resolved.
0219 *
0220 * @return a {@code Type} object that represents the declared type for
0221 * the field represented by this {@code Field} object
0222 * @throws GenericSignatureFormatError if the generic field
0223 * signature does not conform to the format specified in the Java
0224 * Virtual Machine Specification, 3rd edition
0225 * @throws TypeNotPresentException if the generic type
0226 * signature of the underlying field refers to a non-existent
0227 * type declaration
0228 * @throws MalformedParameterizedTypeException if the generic
0229 * signature of the underlying field refers to a parameterized type
0230 * that cannot be instantiated for any reason
0231 * @since 1.5
0232 */
0233 public Type getGenericType() {
0234 if (getGenericSignature() != null)
0235 return getGenericInfo().getGenericType();
0236 else
0237 return getType();
0238 }
0239
0240 /**
0241 * Compares this {@code Field} against the specified object. Returns
0242 * true if the objects are the same. Two {@code Field} objects are the same if
0243 * they were declared by the same class and have the same name
0244 * and type.
0245 */
0246 public boolean equals(Object obj) {
0247 if (obj != null && obj instanceof Field) {
0248 Field other = (Field) obj;
0249 return (getDeclaringClass() == other.getDeclaringClass())
0250 && (getName() == other.getName())
0251 && (getType() == other.getType());
0252 }
0253 return false;
0254 }
0255
0256 /**
0257 * Returns a hashcode for this {@code Field}. This is computed as the
0258 * exclusive-or of the hashcodes for the underlying field's
0259 * declaring class name and its name.
0260 */
0261 public int hashCode() {
0262 return getDeclaringClass().getName().hashCode()
0263 ^ getName().hashCode();
0264 }
0265
0266 /**
0267 * Returns a string describing this {@code Field}. The format is
0268 * the access modifiers for the field, if any, followed
0269 * by the field type, followed by a space, followed by
0270 * the fully-qualified name of the class declaring the field,
0271 * followed by a period, followed by the name of the field.
0272 * For example:
0273 * <pre>
0274 * public static final int java.lang.Thread.MIN_PRIORITY
0275 * private int java.io.FileDescriptor.fd
0276 * </pre>
0277 *
0278 * <p>The modifiers are placed in canonical order as specified by
0279 * "The Java Language Specification". This is {@code public},
0280 * {@code protected} or {@code private} first, and then other
0281 * modifiers in the following order: {@code static}, {@code final},
0282 * {@code transient}, {@code volatile}.
0283 */
0284 public String toString() {
0285 int mod = getModifiers();
0286 return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
0287 + getTypeName(getType()) + " "
0288 + getTypeName(getDeclaringClass()) + "." + getName());
0289 }
0290
0291 /**
0292 * Returns a string describing this {@code Field}, including
0293 * its generic type. The format is the access modifiers for the
0294 * field, if any, followed by the generic field type, followed by
0295 * a space, followed by the fully-qualified name of the class
0296 * declaring the field, followed by a period, followed by the name
0297 * of the field.
0298 *
0299 * <p>The modifiers are placed in canonical order as specified by
0300 * "The Java Language Specification". This is {@code public},
0301 * {@code protected} or {@code private} first, and then other
0302 * modifiers in the following order: {@code static}, {@code final},
0303 * {@code transient}, {@code volatile}.
0304 *
0305 * @return a string describing this {@code Field}, including
0306 * its generic type
0307 *
0308 * @since 1.5
0309 */
0310 public String toGenericString() {
0311 int mod = getModifiers();
0312 Type fieldType = getGenericType();
0313 return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
0314 + ((fieldType instanceof Class) ? getTypeName((Class) fieldType)
0315 : fieldType.toString()) + " "
0316 + getTypeName(getDeclaringClass()) + "." + getName());
0317 }
0318
0319 /**
0320 * Returns the value of the field represented by this {@code Field}, on
0321 * the specified object. The value is automatically wrapped in an
0322 * object if it has a primitive type.
0323 *
0324 * <p>The underlying field's value is obtained as follows:
0325 *
0326 * <p>If the underlying field is a static field, the {@code obj} argument
0327 * is ignored; it may be null.
0328 *
0329 * <p>Otherwise, the underlying field is an instance field. If the
0330 * specified {@code obj} argument is null, the method throws a
0331 * {@code NullPointerException}. If the specified object is not an
0332 * instance of the class or interface declaring the underlying
0333 * field, the method throws an {@code IllegalArgumentException}.
0334 *
0335 * <p>If this {@code Field} object enforces Java language access control, and
0336 * the underlying field is inaccessible, the method throws an
0337 * {@code IllegalAccessException}.
0338 * If the underlying field is static, the class that declared the
0339 * field is initialized if it has not already been initialized.
0340 *
0341 * <p>Otherwise, the value is retrieved from the underlying instance
0342 * or static field. If the field has a primitive type, the value
0343 * is wrapped in an object before being returned, otherwise it is
0344 * returned as is.
0345 *
0346 * <p>If the field is hidden in the type of {@code obj},
0347 * the field's value is obtained according to the preceding rules.
0348 *
0349 * @param obj object from which the represented field's value is
0350 * to be extracted
0351 * @return the value of the represented field in object
0352 * {@code obj}; primitive values are wrapped in an appropriate
0353 * object before being returned
0354 *
0355 * @exception IllegalAccessException if the underlying field
0356 * is inaccessible.
0357 * @exception IllegalArgumentException if the specified object is not an
0358 * instance of the class or interface declaring the underlying
0359 * field (or a subclass or implementor thereof).
0360 * @exception NullPointerException if the specified object is null
0361 * and the field is an instance field.
0362 * @exception ExceptionInInitializerError if the initialization provoked
0363 * by this method fails.
0364 */
0365 public Object get(Object obj) throws IllegalArgumentException,
0366 IllegalAccessException {
0367 return getFieldAccessor(obj).get(obj);
0368 }
0369
0370 /**
0371 * Gets the value of a static or instance {@code boolean} field.
0372 *
0373 * @param obj the object to extract the {@code boolean} value
0374 * from
0375 * @return the value of the {@code boolean} field
0376 *
0377 * @exception IllegalAccessException if the underlying field
0378 * is inaccessible.
0379 * @exception IllegalArgumentException if the specified object is not
0380 * an instance of the class or interface declaring the
0381 * underlying field (or a subclass or implementor
0382 * thereof), or if the field value cannot be
0383 * converted to the type {@code boolean} by a
0384 * widening conversion.
0385 * @exception NullPointerException if the specified object is null
0386 * and the field is an instance field.
0387 * @exception ExceptionInInitializerError if the initialization provoked
0388 * by this method fails.
0389 * @see Field#get
0390 */
0391 public boolean getBoolean(Object obj)
0392 throws IllegalArgumentException, IllegalAccessException {
0393 return getFieldAccessor(obj).getBoolean(obj);
0394 }
0395
0396 /**
0397 * Gets the value of a static or instance {@code byte} field.
0398 *
0399 * @param obj the object to extract the {@code byte} value
0400 * from
0401 * @return the value of the {@code byte} field
0402 *
0403 * @exception IllegalAccessException if the underlying field
0404 * is inaccessible.
0405 * @exception IllegalArgumentException if the specified object is not
0406 * an instance of the class or interface declaring the
0407 * underlying field (or a subclass or implementor
0408 * thereof), or if the field value cannot be
0409 * converted to the type {@code byte} by a
0410 * widening conversion.
0411 * @exception NullPointerException if the specified object is null
0412 * and the field is an instance field.
0413 * @exception ExceptionInInitializerError if the initialization provoked
0414 * by this method fails.
0415 * @see Field#get
0416 */
0417 public byte getByte(Object obj) throws IllegalArgumentException,
0418 IllegalAccessException {
0419 return getFieldAccessor(obj).getByte(obj);
0420 }
0421
0422 /**
0423 * Gets the value of a static or instance field of type
0424 * {@code char} or of another primitive type convertible to
0425 * type {@code char} via a widening conversion.
0426 *
0427 * @param obj the object to extract the {@code char} value
0428 * from
0429 * @return the value of the field converted to type {@code char}
0430 *
0431 * @exception IllegalAccessException if the underlying field
0432 * is inaccessible.
0433 * @exception IllegalArgumentException if the specified object is not
0434 * an instance of the class or interface declaring the
0435 * underlying field (or a subclass or implementor
0436 * thereof), or if the field value cannot be
0437 * converted to the type {@code char} by a
0438 * widening conversion.
0439 * @exception NullPointerException if the specified object is null
0440 * and the field is an instance field.
0441 * @exception ExceptionInInitializerError if the initialization provoked
0442 * by this method fails.
0443 * @see Field#get
0444 */
0445 public char getChar(Object obj) throws IllegalArgumentException,
0446 IllegalAccessException {
0447 return getFieldAccessor(obj).getChar(obj);
0448 }
0449
0450 /**
0451 * Gets the value of a static or instance field of type
0452 * {@code short} or of another primitive type convertible to
0453 * type {@code short} via a widening conversion.
0454 *
0455 * @param obj the object to extract the {@code short} value
0456 * from
0457 * @return the value of the field converted to type {@code short}
0458 *
0459 * @exception IllegalAccessException if the underlying field
0460 * is inaccessible.
0461 * @exception IllegalArgumentException if the specified object is not
0462 * an instance of the class or interface declaring the
0463 * underlying field (or a subclass or implementor
0464 * thereof), or if the field value cannot be
0465 * converted to the type {@code short} by a
0466 * widening conversion.
0467 * @exception NullPointerException if the specified object is null
0468 * and the field is an instance field.
0469 * @exception ExceptionInInitializerError if the initialization provoked
0470 * by this method fails.
0471 * @see Field#get
0472 */
0473 public short getShort(Object obj) throws IllegalArgumentException,
0474 IllegalAccessException {
0475 return getFieldAccessor(obj).getShort(obj);
0476 }
0477
0478 /**
0479 * Gets the value of a static or instance field of type
0480 * {@code int} or of another primitive type convertible to
0481 * type {@code int} via a widening conversion.
0482 *
0483 * @param obj the object to extract the {@code int} value
0484 * from
0485 * @return the value of the field converted to type {@code int}
0486 *
0487 * @exception IllegalAccessException if the underlying field
0488 * is inaccessible.
0489 * @exception IllegalArgumentException if the specified object is not
0490 * an instance of the class or interface declaring the
0491 * underlying field (or a subclass or implementor
0492 * thereof), or if the field value cannot be
0493 * converted to the type {@code int} by a
0494 * widening conversion.
0495 * @exception NullPointerException if the specified object is null
0496 * and the field is an instance field.
0497 * @exception ExceptionInInitializerError if the initialization provoked
0498 * by this method fails.
0499 * @see Field#get
0500 */
0501 public int getInt(Object obj) throws IllegalArgumentException,
0502 IllegalAccessException {
0503 return getFieldAccessor(obj).getInt(obj);
0504 }
0505
0506 /**
0507 * Gets the value of a static or instance field of type
0508 * {@code long} or of another primitive type convertible to
0509 * type {@code long} via a widening conversion.
0510 *
0511 * @param obj the object to extract the {@code long} value
0512 * from
0513 * @return the value of the field converted to type {@code long}
0514 *
0515 * @exception IllegalAccessException if the underlying field
0516 * is inaccessible.
0517 * @exception IllegalArgumentException if the specified object is not
0518 * an instance of the class or interface declaring the
0519 * underlying field (or a subclass or implementor
0520 * thereof), or if the field value cannot be
0521 * converted to the type {@code long} by a
0522 * widening conversion.
0523 * @exception NullPointerException if the specified object is null
0524 * and the field is an instance field.
0525 * @exception ExceptionInInitializerError if the initialization provoked
0526 * by this method fails.
0527 * @see Field#get
0528 */
0529 public long getLong(Object obj) throws IllegalArgumentException,
0530 IllegalAccessException {
0531 return getFieldAccessor(obj).getLong(obj);
0532 }
0533
0534 /**
0535 * Gets the value of a static or instance field of type
0536 * {@code float} or of another primitive type convertible to
0537 * type {@code float} via a widening conversion.
0538 *
0539 * @param obj the object to extract the {@code float} value
0540 * from
0541 * @return the value of the field converted to type {@code float}
0542 *
0543 * @exception IllegalAccessException if the underlying field
0544 * is inaccessible.
0545 * @exception IllegalArgumentException if the specified object is not
0546 * an instance of the class or interface declaring the
0547 * underlying field (or a subclass or implementor
0548 * thereof), or if the field value cannot be
0549 * converted to the type {@code float} by a
0550 * widening conversion.
0551 * @exception NullPointerException if the specified object is null
0552 * and the field is an instance field.
0553 * @exception ExceptionInInitializerError if the initialization provoked
0554 * by this method fails.
0555 * @see Field#get
0556 */
0557 public float getFloat(Object obj) throws IllegalArgumentException,
0558 IllegalAccessException {
0559 return getFieldAccessor(obj).getFloat(obj);
0560 }
0561
0562 /**
0563 * Gets the value of a static or instance field of type
0564 * {@code double} or of another primitive type convertible to
0565 * type {@code double} via a widening conversion.
0566 *
0567 * @param obj the object to extract the {@code double} value
0568 * from
0569 * @return the value of the field converted to type {@code double}
0570 *
0571 * @exception IllegalAccessException if the underlying field
0572 * is inaccessible.
0573 * @exception IllegalArgumentException if the specified object is not
0574 * an instance of the class or interface declaring the
0575 * underlying field (or a subclass or implementor
0576 * thereof), or if the field value cannot be
0577 * converted to the type {@code double} by a
0578 * widening conversion.
0579 * @exception NullPointerException if the specified object is null
0580 * and the field is an instance field.
0581 * @exception ExceptionInInitializerError if the initialization provoked
0582 * by this method fails.
0583 * @see Field#get
0584 */
0585 public double getDouble(Object obj)
0586 throws IllegalArgumentException, IllegalAccessException {
0587 return getFieldAccessor(obj).getDouble(obj);
0588 }
0589
0590 /**
0591 * Sets the field represented by this {@code Field} object on the
0592 * specified object argument to the specified new value. The new
0593 * value is automatically unwrapped if the underlying field has a
0594 * primitive type.
0595 *
0596 * <p>The operation proceeds as follows:
0597 *
0598 * <p>If the underlying field is static, the {@code obj} argument is
0599 * ignored; it may be null.
0600 *
0601 * <p>Otherwise the underlying field is an instance field. If the
0602 * specified object argument is null, the method throws a
0603 * {@code NullPointerException}. If the specified object argument is not
0604 * an instance of the class or interface declaring the underlying
0605 * field, the method throws an {@code IllegalArgumentException}.
0606 *
0607 * <p>If this {@code Field} object enforces Java language access control, and
0608 * the underlying field is inaccessible, the method throws an
0609 * {@code IllegalAccessException}.
0610 *
0611 * <p>If the underlying field is final, the method throws an
0612 * {@code IllegalAccessException} unless
0613 * {@code setAccessible(true)} has succeeded for this field
0614 * and this field is non-static. Setting a final field in this way
0615 * is meaningful only during deserialization or reconstruction of
0616 * instances of classes with blank final fields, before they are
0617 * made available for access by other parts of a program. Use in
0618 * any other context may have unpredictable effects, including cases
0619 * in which other parts of a program continue to use the original
0620 * value of this field.
0621 *
0622 * <p>If the underlying field is of a primitive type, an unwrapping
0623 * conversion is attempted to convert the new value to a value of
0624 * a primitive type. If this attempt fails, the method throws an
0625 * {@code IllegalArgumentException}.
0626 *
0627 * <p>If, after possible unwrapping, the new value cannot be
0628 * converted to the type of the underlying field by an identity or
0629 * widening conversion, the method throws an
0630 * {@code IllegalArgumentException}.
0631 *
0632 * <p>If the underlying field is static, the class that declared the
0633 * field is initialized if it has not already been initialized.
0634 *
0635 * <p>The field is set to the possibly unwrapped and widened new value.
0636 *
0637 * <p>If the field is hidden in the type of {@code obj},
0638 * the field's value is set according to the preceding rules.
0639 *
0640 * @param obj the object whose field should be modified
0641 * @param value the new value for the field of {@code obj}
0642 * being modified
0643 *
0644 * @exception IllegalAccessException if the underlying field
0645 * is inaccessible.
0646 * @exception IllegalArgumentException if the specified object is not an
0647 * instance of the class or interface declaring the underlying
0648 * field (or a subclass or implementor thereof),
0649 * or if an unwrapping conversion fails.
0650 * @exception NullPointerException if the specified object is null
0651 * and the field is an instance field.
0652 * @exception ExceptionInInitializerError if the initialization provoked
0653 * by this method fails.
0654 */
0655 public void set(Object obj, Object value)
0656 throws IllegalArgumentException, IllegalAccessException {
0657 getFieldAccessor(obj).set(obj, value);
0658 }
0659
0660 /**
0661 * Sets the value of a field as a {@code boolean} on the specified object.
0662 * This method is equivalent to
0663 * {@code set(obj, zObj)},
0664 * where {@code zObj} is a {@code Boolean} object and
0665 * {@code zObj.booleanValue() == z}.
0666 *
0667 * @param obj the object whose field should be modified
0668 * @param z the new value for the field of {@code obj}
0669 * being modified
0670 *
0671 * @exception IllegalAccessException if the underlying field
0672 * is inaccessible.
0673 * @exception IllegalArgumentException if the specified object is not an
0674 * instance of the class or interface declaring the underlying
0675 * field (or a subclass or implementor thereof),
0676 * or if an unwrapping conversion fails.
0677 * @exception NullPointerException if the specified object is null
0678 * and the field is an instance field.
0679 * @exception ExceptionInInitializerError if the initialization provoked
0680 * by this method fails.
0681 * @see Field#set
0682 */
0683 public void setBoolean(Object obj, boolean z)
0684 throws IllegalArgumentException, IllegalAccessException {
0685 getFieldAccessor(obj).setBoolean(obj, z);
0686 }
0687
0688 /**
0689 * Sets the value of a field as a {@code byte} on the specified object.
0690 * This method is equivalent to
0691 * {@code set(obj, bObj)},
0692 * where {@code bObj} is a {@code Byte} object and
0693 * {@code bObj.byteValue() == b}.
0694 *
0695 * @param obj the object whose field should be modified
0696 * @param b the new value for the field of {@code obj}
0697 * being modified
0698 *
0699 * @exception IllegalAccessException if the underlying field
0700 * is inaccessible.
0701 * @exception IllegalArgumentException if the specified object is not an
0702 * instance of the class or interface declaring the underlying
0703 * field (or a subclass or implementor thereof),
0704 * or if an unwrapping conversion fails.
0705 * @exception NullPointerException if the specified object is null
0706 * and the field is an instance field.
0707 * @exception ExceptionInInitializerError if the initialization provoked
0708 * by this method fails.
0709 * @see Field#set
0710 */
0711 public void setByte(Object obj, byte b)
0712 throws IllegalArgumentException, IllegalAccessException {
0713 getFieldAccessor(obj).setByte(obj, b);
0714 }
0715
0716 /**
0717 * Sets the value of a field as a {@code char} on the specified object.
0718 * This method is equivalent to
0719 * {@code set(obj, cObj)},
0720 * where {@code cObj} is a {@code Character} object and
0721 * {@code cObj.charValue() == c}.
0722 *
0723 * @param obj the object whose field should be modified
0724 * @param c the new value for the field of {@code obj}
0725 * being modified
0726 *
0727 * @exception IllegalAccessException if the underlying field
0728 * is inaccessible.
0729 * @exception IllegalArgumentException if the specified object is not an
0730 * instance of the class or interface declaring the underlying
0731 * field (or a subclass or implementor thereof),
0732 * or if an unwrapping conversion fails.
0733 * @exception NullPointerException if the specified object is null
0734 * and the field is an instance field.
0735 * @exception ExceptionInInitializerError if the initialization provoked
0736 * by this method fails.
0737 * @see Field#set
0738 */
0739 public void setChar(Object obj, char c)
0740 throws IllegalArgumentException, IllegalAccessException {
0741 getFieldAccessor(obj).setChar(obj, c);
0742 }
0743
0744 /**
0745 * Sets the value of a field as a {@code short} on the specified object.
0746 * This method is equivalent to
0747 * {@code set(obj, sObj)},
0748 * where {@code sObj} is a {@code Short} object and
0749 * {@code sObj.shortValue() == s}.
0750 *
0751 * @param obj the object whose field should be modified
0752 * @param s the new value for the field of {@code obj}
0753 * being modified
0754 *
0755 * @exception IllegalAccessException if the underlying field
0756 * is inaccessible.
0757 * @exception IllegalArgumentException if the specified object is not an
0758 * instance of the class or interface declaring the underlying
0759 * field (or a subclass or implementor thereof),
0760 * or if an unwrapping conversion fails.
0761 * @exception NullPointerException if the specified object is null
0762 * and the field is an instance field.
0763 * @exception ExceptionInInitializerError if the initialization provoked
0764 * by this method fails.
0765 * @see Field#set
0766 */
0767 public void setShort(Object obj, short s)
0768 throws IllegalArgumentException, IllegalAccessException {
0769 getFieldAccessor(obj).setShort(obj, s);
0770 }
0771
0772 /**
0773 * Sets the value of a field as an {@code int} on the specified object.
0774 * This method is equivalent to
0775 * {@code set(obj, iObj)},
0776 * where {@code iObj} is a {@code Integer} object and
0777 * {@code iObj.intValue() == i}.
0778 *
0779 * @param obj the object whose field should be modified
0780 * @param i the new value for the field of {@code obj}
0781 * being modified
0782 *
0783 * @exception IllegalAccessException if the underlying field
0784 * is inaccessible.
0785 * @exception IllegalArgumentException if the specified object is not an
0786 * instance of the class or interface declaring the underlying
0787 * field (or a subclass or implementor thereof),
0788 * or if an unwrapping conversion fails.
0789 * @exception NullPointerException if the specified object is null
0790 * and the field is an instance field.
0791 * @exception ExceptionInInitializerError if the initialization provoked
0792 * by this method fails.
0793 * @see Field#set
0794 */
0795 public void setInt(Object obj, int i)
0796 throws IllegalArgumentException, IllegalAccessException {
0797 getFieldAccessor(obj).setInt(obj, i);
0798 }
0799
0800 /**
0801 * Sets the value of a field as a {@code long} on the specified object.
0802 * This method is equivalent to
0803 * {@code set(obj, lObj)},
0804 * where {@code lObj} is a {@code Long} object and
0805 * {@code lObj.longValue() == l}.
0806 *
0807 * @param obj the object whose field should be modified
0808 * @param l the new value for the field of {@code obj}
0809 * being modified
0810 *
0811 * @exception IllegalAccessException if the underlying field
0812 * is inaccessible.
0813 * @exception IllegalArgumentException if the specified object is not an
0814 * instance of the class or interface declaring the underlying
0815 * field (or a subclass or implementor thereof),
0816 * or if an unwrapping conversion fails.
0817 * @exception NullPointerException if the specified object is null
0818 * and the field is an instance field.
0819 * @exception ExceptionInInitializerError if the initialization provoked
0820 * by this method fails.
0821 * @see Field#set
0822 */
0823 public void setLong(Object obj, long l)
0824 throws IllegalArgumentException, IllegalAccessException {
0825 getFieldAccessor(obj).setLong(obj, l);
0826 }
0827
0828 /**
0829 * Sets the value of a field as a {@code float} on the specified object.
0830 * This method is equivalent to
0831 * {@code set(obj, fObj)},
0832 * where {@code fObj} is a {@code Float} object and
0833 * {@code fObj.floatValue() == f}.
0834 *
0835 * @param obj the object whose field should be modified
0836 * @param f the new value for the field of {@code obj}
0837 * being modified
0838 *
0839 * @exception IllegalAccessException if the underlying field
0840 * is inaccessible.
0841 * @exception IllegalArgumentException if the specified object is not an
0842 * instance of the class or interface declaring the underlying
0843 * field (or a subclass or implementor thereof),
0844 * or if an unwrapping conversion fails.
0845 * @exception NullPointerException if the specified object is null
0846 * and the field is an instance field.
0847 * @exception ExceptionInInitializerError if the initialization provoked
0848 * by this method fails.
0849 * @see Field#set
0850 */
0851 public void setFloat(Object obj, float f)
0852 throws IllegalArgumentException, IllegalAccessException {
0853 getFieldAccessor(obj).setFloat(obj, f);
0854 }
0855
0856 /**
0857 * Sets the value of a field as a {@code double} on the specified object.
0858 * This method is equivalent to
0859 * {@code set(obj, dObj)},
0860 * where {@code dObj} is a {@code Double} object and
0861 * {@code dObj.doubleValue() == d}.
0862 *
0863 * @param obj the object whose field should be modified
0864 * @param d the new value for the field of {@code obj}
0865 * being modified
0866 *
0867 * @exception IllegalAccessException if the underlying field
0868 * is inaccessible.
0869 * @exception IllegalArgumentException if the specified object is not an
0870 * instance of the class or interface declaring the underlying
0871 * field (or a subclass or implementor thereof),
0872 * or if an unwrapping conversion fails.
0873 * @exception NullPointerException if the specified object is null
0874 * and the field is an instance field.
0875 * @exception ExceptionInInitializerError if the initialization provoked
0876 * by this method fails.
0877 * @see Field#set
0878 */
0879 public void setDouble(Object obj, double d)
0880 throws IllegalArgumentException, IllegalAccessException {
0881 getFieldAccessor(obj).setDouble(obj, d);
0882 }
0883
0884 // Convenience routine which performs security checks
0885 private FieldAccessor getFieldAccessor(Object obj)
0886 throws IllegalAccessException {
0887 doSecurityCheck(obj);
0888 boolean ov = override;
0889 FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor;
0890 return (a != null) ? a : acquireFieldAccessor(ov);
0891 }
0892
0893 // NOTE that there is no synchronization used here. It is correct
0894 // (though not efficient) to generate more than one FieldAccessor
0895 // for a given Field. However, avoiding synchronization will
0896 // probably make the implementation more scalable.
0897 private FieldAccessor acquireFieldAccessor(
0898 boolean overrideFinalCheck) {
0899 // First check to see if one has been created yet, and take it
0900 // if so
0901 FieldAccessor tmp = null;
0902 if (root != null)
0903 tmp = root.getFieldAccessor(overrideFinalCheck);
0904 if (tmp != null) {
0905 if (overrideFinalCheck)
0906 overrideFieldAccessor = tmp;
0907 else
0908 fieldAccessor = tmp;
0909 } else {
0910 // Otherwise fabricate one and propagate it up to the root
0911 tmp = reflectionFactory.newFieldAccessor(this ,
0912 overrideFinalCheck);
0913 setFieldAccessor(tmp, overrideFinalCheck);
0914 }
0915 return tmp;
0916 }
0917
0918 // Returns FieldAccessor for this Field object, not looking up
0919 // the chain to the root
0920 private FieldAccessor getFieldAccessor(boolean overrideFinalCheck) {
0921 return (overrideFinalCheck) ? overrideFieldAccessor
0922 : fieldAccessor;
0923 }
0924
0925 // Sets the FieldAccessor for this Field object and
0926 // (recursively) its root
0927 private void setFieldAccessor(FieldAccessor accessor,
0928 boolean overrideFinalCheck) {
0929 if (overrideFinalCheck)
0930 overrideFieldAccessor = accessor;
0931 else
0932 fieldAccessor = accessor;
0933 // Propagate up
0934 if (root != null) {
0935 root.setFieldAccessor(accessor, overrideFinalCheck);
0936 }
0937 }
0938
0939 // NOTE: be very careful if you change the stack depth of this
0940 // routine. The depth of the "getCallerClass" call is hardwired so
0941 // that the compiler can have an easier time if this gets inlined.
0942 private void doSecurityCheck(Object obj)
0943 throws IllegalAccessException {
0944 if (!override) {
0945 if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
0946 Class caller = Reflection.getCallerClass(4);
0947 Class targetClass = ((obj == null || !Modifier
0948 .isProtected(modifiers)) ? clazz : obj
0949 .getClass());
0950
0951 synchronized (this ) {
0952 if ((securityCheckCache == caller)
0953 && (securityCheckTargetClassCache == targetClass)) {
0954 return;
0955 }
0956 }
0957 Reflection.ensureMemberAccess(caller, clazz, obj,
0958 modifiers);
0959 synchronized (this ) {
0960 securityCheckCache = caller;
0961 securityCheckTargetClassCache = targetClass;
0962 }
0963 }
0964 }
0965 }
0966
0967 /*
0968 * Utility routine to paper over array type names
0969 */
0970 static String getTypeName(Class type) {
0971 if (type.isArray()) {
0972 try {
0973 Class cl = type;
0974 int dimensions = 0;
0975 while (cl.isArray()) {
0976 dimensions++;
0977 cl = cl.getComponentType();
0978 }
0979 StringBuffer sb = new StringBuffer();
0980 sb.append(cl.getName());
0981 for (int i = 0; i < dimensions; i++) {
0982 sb.append("[]");
0983 }
0984 return sb.toString();
0985 } catch (Throwable e) { /*FALLTHRU*/
0986 }
0987 }
0988 return type.getName();
0989 }
0990
0991 /**
0992 * @throws NullPointerException {@inheritDoc}
0993 * @since 1.5
0994 */
0995 public <T extends Annotation> T getAnnotation(
0996 Class<T> annotationClass) {
0997 if (annotationClass == null)
0998 throw new NullPointerException();
0999
1000 return (T) declaredAnnotations().get(annotationClass);
1001 }
1002
1003 private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
1004
1005 /**
1006 * @since 1.5
1007 */
1008 public Annotation[] getDeclaredAnnotations() {
1009 return declaredAnnotations().values().toArray(
1010 EMPTY_ANNOTATION_ARRAY);
1011 }
1012
1013 private transient Map<Class, Annotation> declaredAnnotations;
1014
1015 private synchronized Map<Class, Annotation> declaredAnnotations() {
1016 if (declaredAnnotations == null) {
1017 declaredAnnotations = AnnotationParser.parseAnnotations(
1018 annotations, sun.misc.SharedSecrets
1019 .getJavaLangAccess().getConstantPool(
1020 getDeclaringClass()),
1021 getDeclaringClass());
1022 }
1023 return declaredAnnotations;
1024 }
1025 }
|