1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/emul/src/main/java/java/lang/reflect/Field.java Tue Dec 04 14:08:19 2012 +0100
1.3 @@ -0,0 +1,1040 @@
1.4 +/*
1.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +package java.lang.reflect;
1.30 +
1.31 +import sun.reflect.FieldAccessor;
1.32 +import sun.reflect.Reflection;
1.33 +import sun.reflect.generics.repository.FieldRepository;
1.34 +import sun.reflect.generics.factory.CoreReflectionFactory;
1.35 +import sun.reflect.generics.factory.GenericsFactory;
1.36 +import sun.reflect.generics.scope.ClassScope;
1.37 +import java.lang.annotation.Annotation;
1.38 +import java.util.Map;
1.39 +import sun.reflect.annotation.AnnotationParser;
1.40 +
1.41 +
1.42 +/**
1.43 + * A {@code Field} provides information about, and dynamic access to, a
1.44 + * single field of a class or an interface. The reflected field may
1.45 + * be a class (static) field or an instance field.
1.46 + *
1.47 + * <p>A {@code Field} permits widening conversions to occur during a get or
1.48 + * set access operation, but throws an {@code IllegalArgumentException} if a
1.49 + * narrowing conversion would occur.
1.50 + *
1.51 + * @see Member
1.52 + * @see java.lang.Class
1.53 + * @see java.lang.Class#getFields()
1.54 + * @see java.lang.Class#getField(String)
1.55 + * @see java.lang.Class#getDeclaredFields()
1.56 + * @see java.lang.Class#getDeclaredField(String)
1.57 + *
1.58 + * @author Kenneth Russell
1.59 + * @author Nakul Saraiya
1.60 + */
1.61 +public final
1.62 +class Field extends AccessibleObject implements Member {
1.63 +
1.64 + private Class<?> clazz;
1.65 + private int slot;
1.66 + // This is guaranteed to be interned by the VM in the 1.4
1.67 + // reflection implementation
1.68 + private String name;
1.69 + private Class<?> type;
1.70 + private int modifiers;
1.71 + // Generics and annotations support
1.72 + private transient String signature;
1.73 + // generic info repository; lazily initialized
1.74 + private transient FieldRepository genericInfo;
1.75 + private byte[] annotations;
1.76 + // Cached field accessor created without override
1.77 + private FieldAccessor fieldAccessor;
1.78 + // Cached field accessor created with override
1.79 + private FieldAccessor overrideFieldAccessor;
1.80 + // For sharing of FieldAccessors. This branching structure is
1.81 + // currently only two levels deep (i.e., one root Field and
1.82 + // potentially many Field objects pointing to it.)
1.83 + private Field root;
1.84 +
1.85 + // Generics infrastructure
1.86 +
1.87 + private String getGenericSignature() {return signature;}
1.88 +
1.89 + // Accessor for factory
1.90 + private GenericsFactory getFactory() {
1.91 + Class<?> c = getDeclaringClass();
1.92 + // create scope and factory
1.93 + return CoreReflectionFactory.make(c, ClassScope.make(c));
1.94 + }
1.95 +
1.96 + // Accessor for generic info repository
1.97 + private FieldRepository getGenericInfo() {
1.98 + // lazily initialize repository if necessary
1.99 + if (genericInfo == null) {
1.100 + // create and cache generic info repository
1.101 + genericInfo = FieldRepository.make(getGenericSignature(),
1.102 + getFactory());
1.103 + }
1.104 + return genericInfo; //return cached repository
1.105 + }
1.106 +
1.107 +
1.108 + /**
1.109 + * Package-private constructor used by ReflectAccess to enable
1.110 + * instantiation of these objects in Java code from the java.lang
1.111 + * package via sun.reflect.LangReflectAccess.
1.112 + */
1.113 + Field(Class<?> declaringClass,
1.114 + String name,
1.115 + Class<?> type,
1.116 + int modifiers,
1.117 + int slot,
1.118 + String signature,
1.119 + byte[] annotations)
1.120 + {
1.121 + this.clazz = declaringClass;
1.122 + this.name = name;
1.123 + this.type = type;
1.124 + this.modifiers = modifiers;
1.125 + this.slot = slot;
1.126 + this.signature = signature;
1.127 + this.annotations = annotations;
1.128 + }
1.129 +
1.130 + /**
1.131 + * Package-private routine (exposed to java.lang.Class via
1.132 + * ReflectAccess) which returns a copy of this Field. The copy's
1.133 + * "root" field points to this Field.
1.134 + */
1.135 + Field copy() {
1.136 + // This routine enables sharing of FieldAccessor objects
1.137 + // among Field objects which refer to the same underlying
1.138 + // method in the VM. (All of this contortion is only necessary
1.139 + // because of the "accessibility" bit in AccessibleObject,
1.140 + // which implicitly requires that new java.lang.reflect
1.141 + // objects be fabricated for each reflective call on Class
1.142 + // objects.)
1.143 + Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations);
1.144 + res.root = this;
1.145 + // Might as well eagerly propagate this if already present
1.146 + res.fieldAccessor = fieldAccessor;
1.147 + res.overrideFieldAccessor = overrideFieldAccessor;
1.148 + return res;
1.149 + }
1.150 +
1.151 + /**
1.152 + * Returns the {@code Class} object representing the class or interface
1.153 + * that declares the field represented by this {@code Field} object.
1.154 + */
1.155 + public Class<?> getDeclaringClass() {
1.156 + return clazz;
1.157 + }
1.158 +
1.159 + /**
1.160 + * Returns the name of the field represented by this {@code Field} object.
1.161 + */
1.162 + public String getName() {
1.163 + return name;
1.164 + }
1.165 +
1.166 + /**
1.167 + * Returns the Java language modifiers for the field represented
1.168 + * by this {@code Field} object, as an integer. The {@code Modifier} class should
1.169 + * be used to decode the modifiers.
1.170 + *
1.171 + * @see Modifier
1.172 + */
1.173 + public int getModifiers() {
1.174 + return modifiers;
1.175 + }
1.176 +
1.177 + /**
1.178 + * Returns {@code true} if this field represents an element of
1.179 + * an enumerated type; returns {@code false} otherwise.
1.180 + *
1.181 + * @return {@code true} if and only if this field represents an element of
1.182 + * an enumerated type.
1.183 + * @since 1.5
1.184 + */
1.185 + public boolean isEnumConstant() {
1.186 + return (getModifiers() & Modifier.ENUM) != 0;
1.187 + }
1.188 +
1.189 + /**
1.190 + * Returns {@code true} if this field is a synthetic
1.191 + * field; returns {@code false} otherwise.
1.192 + *
1.193 + * @return true if and only if this field is a synthetic
1.194 + * field as defined by the Java Language Specification.
1.195 + * @since 1.5
1.196 + */
1.197 + public boolean isSynthetic() {
1.198 + return Modifier.isSynthetic(getModifiers());
1.199 + }
1.200 +
1.201 + /**
1.202 + * Returns a {@code Class} object that identifies the
1.203 + * declared type for the field represented by this
1.204 + * {@code Field} object.
1.205 + *
1.206 + * @return a {@code Class} object identifying the declared
1.207 + * type of the field represented by this object
1.208 + */
1.209 + public Class<?> getType() {
1.210 + return type;
1.211 + }
1.212 +
1.213 + /**
1.214 + * Returns a {@code Type} object that represents the declared type for
1.215 + * the field represented by this {@code Field} object.
1.216 + *
1.217 + * <p>If the {@code Type} is a parameterized type, the
1.218 + * {@code Type} object returned must accurately reflect the
1.219 + * actual type parameters used in the source code.
1.220 + *
1.221 + * <p>If the type of the underlying field is a type variable or a
1.222 + * parameterized type, it is created. Otherwise, it is resolved.
1.223 + *
1.224 + * @return a {@code Type} object that represents the declared type for
1.225 + * the field represented by this {@code Field} object
1.226 + * @throws GenericSignatureFormatError if the generic field
1.227 + * signature does not conform to the format specified in
1.228 + * <cite>The Java™ Virtual Machine Specification</cite>
1.229 + * @throws TypeNotPresentException if the generic type
1.230 + * signature of the underlying field refers to a non-existent
1.231 + * type declaration
1.232 + * @throws MalformedParameterizedTypeException if the generic
1.233 + * signature of the underlying field refers to a parameterized type
1.234 + * that cannot be instantiated for any reason
1.235 + * @since 1.5
1.236 + */
1.237 + public Type getGenericType() {
1.238 + if (getGenericSignature() != null)
1.239 + return getGenericInfo().getGenericType();
1.240 + else
1.241 + return getType();
1.242 + }
1.243 +
1.244 +
1.245 + /**
1.246 + * Compares this {@code Field} against the specified object. Returns
1.247 + * true if the objects are the same. Two {@code Field} objects are the same if
1.248 + * they were declared by the same class and have the same name
1.249 + * and type.
1.250 + */
1.251 + public boolean equals(Object obj) {
1.252 + if (obj != null && obj instanceof Field) {
1.253 + Field other = (Field)obj;
1.254 + return (getDeclaringClass() == other.getDeclaringClass())
1.255 + && (getName() == other.getName())
1.256 + && (getType() == other.getType());
1.257 + }
1.258 + return false;
1.259 + }
1.260 +
1.261 + /**
1.262 + * Returns a hashcode for this {@code Field}. This is computed as the
1.263 + * exclusive-or of the hashcodes for the underlying field's
1.264 + * declaring class name and its name.
1.265 + */
1.266 + public int hashCode() {
1.267 + return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
1.268 + }
1.269 +
1.270 + /**
1.271 + * Returns a string describing this {@code Field}. The format is
1.272 + * the access modifiers for the field, if any, followed
1.273 + * by the field type, followed by a space, followed by
1.274 + * the fully-qualified name of the class declaring the field,
1.275 + * followed by a period, followed by the name of the field.
1.276 + * For example:
1.277 + * <pre>
1.278 + * public static final int java.lang.Thread.MIN_PRIORITY
1.279 + * private int java.io.FileDescriptor.fd
1.280 + * </pre>
1.281 + *
1.282 + * <p>The modifiers are placed in canonical order as specified by
1.283 + * "The Java Language Specification". This is {@code public},
1.284 + * {@code protected} or {@code private} first, and then other
1.285 + * modifiers in the following order: {@code static}, {@code final},
1.286 + * {@code transient}, {@code volatile}.
1.287 + */
1.288 + public String toString() {
1.289 + int mod = getModifiers();
1.290 + return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
1.291 + + getTypeName(getType()) + " "
1.292 + + getTypeName(getDeclaringClass()) + "."
1.293 + + getName());
1.294 + }
1.295 +
1.296 + /**
1.297 + * Returns a string describing this {@code Field}, including
1.298 + * its generic type. The format is the access modifiers for the
1.299 + * field, if any, followed by the generic field type, followed by
1.300 + * a space, followed by the fully-qualified name of the class
1.301 + * declaring the field, followed by a period, followed by the name
1.302 + * of the field.
1.303 + *
1.304 + * <p>The modifiers are placed in canonical order as specified by
1.305 + * "The Java Language Specification". This is {@code public},
1.306 + * {@code protected} or {@code private} first, and then other
1.307 + * modifiers in the following order: {@code static}, {@code final},
1.308 + * {@code transient}, {@code volatile}.
1.309 + *
1.310 + * @return a string describing this {@code Field}, including
1.311 + * its generic type
1.312 + *
1.313 + * @since 1.5
1.314 + */
1.315 + public String toGenericString() {
1.316 + int mod = getModifiers();
1.317 + Type fieldType = getGenericType();
1.318 + return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
1.319 + + ((fieldType instanceof Class) ?
1.320 + getTypeName((Class)fieldType): fieldType.toString())+ " "
1.321 + + getTypeName(getDeclaringClass()) + "."
1.322 + + getName());
1.323 + }
1.324 +
1.325 + /**
1.326 + * Returns the value of the field represented by this {@code Field}, on
1.327 + * the specified object. The value is automatically wrapped in an
1.328 + * object if it has a primitive type.
1.329 + *
1.330 + * <p>The underlying field's value is obtained as follows:
1.331 + *
1.332 + * <p>If the underlying field is a static field, the {@code obj} argument
1.333 + * is ignored; it may be null.
1.334 + *
1.335 + * <p>Otherwise, the underlying field is an instance field. If the
1.336 + * specified {@code obj} argument is null, the method throws a
1.337 + * {@code NullPointerException}. If the specified object is not an
1.338 + * instance of the class or interface declaring the underlying
1.339 + * field, the method throws an {@code IllegalArgumentException}.
1.340 + *
1.341 + * <p>If this {@code Field} object is enforcing Java language access control, and
1.342 + * the underlying field is inaccessible, the method throws an
1.343 + * {@code IllegalAccessException}.
1.344 + * If the underlying field is static, the class that declared the
1.345 + * field is initialized if it has not already been initialized.
1.346 + *
1.347 + * <p>Otherwise, the value is retrieved from the underlying instance
1.348 + * or static field. If the field has a primitive type, the value
1.349 + * is wrapped in an object before being returned, otherwise it is
1.350 + * returned as is.
1.351 + *
1.352 + * <p>If the field is hidden in the type of {@code obj},
1.353 + * the field's value is obtained according to the preceding rules.
1.354 + *
1.355 + * @param obj object from which the represented field's value is
1.356 + * to be extracted
1.357 + * @return the value of the represented field in object
1.358 + * {@code obj}; primitive values are wrapped in an appropriate
1.359 + * object before being returned
1.360 + *
1.361 + * @exception IllegalAccessException if this {@code Field} object
1.362 + * is enforcing Java language access control and the underlying
1.363 + * field is inaccessible.
1.364 + * @exception IllegalArgumentException if the specified object is not an
1.365 + * instance of the class or interface declaring the underlying
1.366 + * field (or a subclass or implementor thereof).
1.367 + * @exception NullPointerException if the specified object is null
1.368 + * and the field is an instance field.
1.369 + * @exception ExceptionInInitializerError if the initialization provoked
1.370 + * by this method fails.
1.371 + */
1.372 + public Object get(Object obj)
1.373 + throws IllegalArgumentException, IllegalAccessException
1.374 + {
1.375 + return getFieldAccessor(obj).get(obj);
1.376 + }
1.377 +
1.378 + /**
1.379 + * Gets the value of a static or instance {@code boolean} field.
1.380 + *
1.381 + * @param obj the object to extract the {@code boolean} value
1.382 + * from
1.383 + * @return the value of the {@code boolean} field
1.384 + *
1.385 + * @exception IllegalAccessException if this {@code Field} object
1.386 + * is enforcing Java language access control and the underlying
1.387 + * field is inaccessible.
1.388 + * @exception IllegalArgumentException if the specified object is not
1.389 + * an instance of the class or interface declaring the
1.390 + * underlying field (or a subclass or implementor
1.391 + * thereof), or if the field value cannot be
1.392 + * converted to the type {@code boolean} by a
1.393 + * widening conversion.
1.394 + * @exception NullPointerException if the specified object is null
1.395 + * and the field is an instance field.
1.396 + * @exception ExceptionInInitializerError if the initialization provoked
1.397 + * by this method fails.
1.398 + * @see Field#get
1.399 + */
1.400 + public boolean getBoolean(Object obj)
1.401 + throws IllegalArgumentException, IllegalAccessException
1.402 + {
1.403 + return getFieldAccessor(obj).getBoolean(obj);
1.404 + }
1.405 +
1.406 + /**
1.407 + * Gets the value of a static or instance {@code byte} field.
1.408 + *
1.409 + * @param obj the object to extract the {@code byte} value
1.410 + * from
1.411 + * @return the value of the {@code byte} field
1.412 + *
1.413 + * @exception IllegalAccessException if this {@code Field} object
1.414 + * is enforcing Java language access control and the underlying
1.415 + * field is inaccessible.
1.416 + * @exception IllegalArgumentException if the specified object is not
1.417 + * an instance of the class or interface declaring the
1.418 + * underlying field (or a subclass or implementor
1.419 + * thereof), or if the field value cannot be
1.420 + * converted to the type {@code byte} by a
1.421 + * widening conversion.
1.422 + * @exception NullPointerException if the specified object is null
1.423 + * and the field is an instance field.
1.424 + * @exception ExceptionInInitializerError if the initialization provoked
1.425 + * by this method fails.
1.426 + * @see Field#get
1.427 + */
1.428 + public byte getByte(Object obj)
1.429 + throws IllegalArgumentException, IllegalAccessException
1.430 + {
1.431 + return getFieldAccessor(obj).getByte(obj);
1.432 + }
1.433 +
1.434 + /**
1.435 + * Gets the value of a static or instance field of type
1.436 + * {@code char} or of another primitive type convertible to
1.437 + * type {@code char} via a widening conversion.
1.438 + *
1.439 + * @param obj the object to extract the {@code char} value
1.440 + * from
1.441 + * @return the value of the field converted to type {@code char}
1.442 + *
1.443 + * @exception IllegalAccessException if this {@code Field} object
1.444 + * is enforcing Java language access control and the underlying
1.445 + * field is inaccessible.
1.446 + * @exception IllegalArgumentException if the specified object is not
1.447 + * an instance of the class or interface declaring the
1.448 + * underlying field (or a subclass or implementor
1.449 + * thereof), or if the field value cannot be
1.450 + * converted to the type {@code char} by a
1.451 + * widening conversion.
1.452 + * @exception NullPointerException if the specified object is null
1.453 + * and the field is an instance field.
1.454 + * @exception ExceptionInInitializerError if the initialization provoked
1.455 + * by this method fails.
1.456 + * @see Field#get
1.457 + */
1.458 + public char getChar(Object obj)
1.459 + throws IllegalArgumentException, IllegalAccessException
1.460 + {
1.461 + return getFieldAccessor(obj).getChar(obj);
1.462 + }
1.463 +
1.464 + /**
1.465 + * Gets the value of a static or instance field of type
1.466 + * {@code short} or of another primitive type convertible to
1.467 + * type {@code short} via a widening conversion.
1.468 + *
1.469 + * @param obj the object to extract the {@code short} value
1.470 + * from
1.471 + * @return the value of the field converted to type {@code short}
1.472 + *
1.473 + * @exception IllegalAccessException if this {@code Field} object
1.474 + * is enforcing Java language access control and the underlying
1.475 + * field is inaccessible.
1.476 + * @exception IllegalArgumentException if the specified object is not
1.477 + * an instance of the class or interface declaring the
1.478 + * underlying field (or a subclass or implementor
1.479 + * thereof), or if the field value cannot be
1.480 + * converted to the type {@code short} by a
1.481 + * widening conversion.
1.482 + * @exception NullPointerException if the specified object is null
1.483 + * and the field is an instance field.
1.484 + * @exception ExceptionInInitializerError if the initialization provoked
1.485 + * by this method fails.
1.486 + * @see Field#get
1.487 + */
1.488 + public short getShort(Object obj)
1.489 + throws IllegalArgumentException, IllegalAccessException
1.490 + {
1.491 + return getFieldAccessor(obj).getShort(obj);
1.492 + }
1.493 +
1.494 + /**
1.495 + * Gets the value of a static or instance field of type
1.496 + * {@code int} or of another primitive type convertible to
1.497 + * type {@code int} via a widening conversion.
1.498 + *
1.499 + * @param obj the object to extract the {@code int} value
1.500 + * from
1.501 + * @return the value of the field converted to type {@code int}
1.502 + *
1.503 + * @exception IllegalAccessException if this {@code Field} object
1.504 + * is enforcing Java language access control and the underlying
1.505 + * field is inaccessible.
1.506 + * @exception IllegalArgumentException if the specified object is not
1.507 + * an instance of the class or interface declaring the
1.508 + * underlying field (or a subclass or implementor
1.509 + * thereof), or if the field value cannot be
1.510 + * converted to the type {@code int} by a
1.511 + * widening conversion.
1.512 + * @exception NullPointerException if the specified object is null
1.513 + * and the field is an instance field.
1.514 + * @exception ExceptionInInitializerError if the initialization provoked
1.515 + * by this method fails.
1.516 + * @see Field#get
1.517 + */
1.518 + public int getInt(Object obj)
1.519 + throws IllegalArgumentException, IllegalAccessException
1.520 + {
1.521 + return getFieldAccessor(obj).getInt(obj);
1.522 + }
1.523 +
1.524 + /**
1.525 + * Gets the value of a static or instance field of type
1.526 + * {@code long} or of another primitive type convertible to
1.527 + * type {@code long} via a widening conversion.
1.528 + *
1.529 + * @param obj the object to extract the {@code long} value
1.530 + * from
1.531 + * @return the value of the field converted to type {@code long}
1.532 + *
1.533 + * @exception IllegalAccessException if this {@code Field} object
1.534 + * is enforcing Java language access control and the underlying
1.535 + * field is inaccessible.
1.536 + * @exception IllegalArgumentException if the specified object is not
1.537 + * an instance of the class or interface declaring the
1.538 + * underlying field (or a subclass or implementor
1.539 + * thereof), or if the field value cannot be
1.540 + * converted to the type {@code long} by a
1.541 + * widening conversion.
1.542 + * @exception NullPointerException if the specified object is null
1.543 + * and the field is an instance field.
1.544 + * @exception ExceptionInInitializerError if the initialization provoked
1.545 + * by this method fails.
1.546 + * @see Field#get
1.547 + */
1.548 + public long getLong(Object obj)
1.549 + throws IllegalArgumentException, IllegalAccessException
1.550 + {
1.551 + return getFieldAccessor(obj).getLong(obj);
1.552 + }
1.553 +
1.554 + /**
1.555 + * Gets the value of a static or instance field of type
1.556 + * {@code float} or of another primitive type convertible to
1.557 + * type {@code float} via a widening conversion.
1.558 + *
1.559 + * @param obj the object to extract the {@code float} value
1.560 + * from
1.561 + * @return the value of the field converted to type {@code float}
1.562 + *
1.563 + * @exception IllegalAccessException if this {@code Field} object
1.564 + * is enforcing Java language access control and the underlying
1.565 + * field is inaccessible.
1.566 + * @exception IllegalArgumentException if the specified object is not
1.567 + * an instance of the class or interface declaring the
1.568 + * underlying field (or a subclass or implementor
1.569 + * thereof), or if the field value cannot be
1.570 + * converted to the type {@code float} by a
1.571 + * widening conversion.
1.572 + * @exception NullPointerException if the specified object is null
1.573 + * and the field is an instance field.
1.574 + * @exception ExceptionInInitializerError if the initialization provoked
1.575 + * by this method fails.
1.576 + * @see Field#get
1.577 + */
1.578 + public float getFloat(Object obj)
1.579 + throws IllegalArgumentException, IllegalAccessException
1.580 + {
1.581 + return getFieldAccessor(obj).getFloat(obj);
1.582 + }
1.583 +
1.584 + /**
1.585 + * Gets the value of a static or instance field of type
1.586 + * {@code double} or of another primitive type convertible to
1.587 + * type {@code double} via a widening conversion.
1.588 + *
1.589 + * @param obj the object to extract the {@code double} value
1.590 + * from
1.591 + * @return the value of the field converted to type {@code double}
1.592 + *
1.593 + * @exception IllegalAccessException if this {@code Field} object
1.594 + * is enforcing Java language access control and the underlying
1.595 + * field is inaccessible.
1.596 + * @exception IllegalArgumentException if the specified object is not
1.597 + * an instance of the class or interface declaring the
1.598 + * underlying field (or a subclass or implementor
1.599 + * thereof), or if the field value cannot be
1.600 + * converted to the type {@code double} by a
1.601 + * widening conversion.
1.602 + * @exception NullPointerException if the specified object is null
1.603 + * and the field is an instance field.
1.604 + * @exception ExceptionInInitializerError if the initialization provoked
1.605 + * by this method fails.
1.606 + * @see Field#get
1.607 + */
1.608 + public double getDouble(Object obj)
1.609 + throws IllegalArgumentException, IllegalAccessException
1.610 + {
1.611 + return getFieldAccessor(obj).getDouble(obj);
1.612 + }
1.613 +
1.614 + /**
1.615 + * Sets the field represented by this {@code Field} object on the
1.616 + * specified object argument to the specified new value. The new
1.617 + * value is automatically unwrapped if the underlying field has a
1.618 + * primitive type.
1.619 + *
1.620 + * <p>The operation proceeds as follows:
1.621 + *
1.622 + * <p>If the underlying field is static, the {@code obj} argument is
1.623 + * ignored; it may be null.
1.624 + *
1.625 + * <p>Otherwise the underlying field is an instance field. If the
1.626 + * specified object argument is null, the method throws a
1.627 + * {@code NullPointerException}. If the specified object argument is not
1.628 + * an instance of the class or interface declaring the underlying
1.629 + * field, the method throws an {@code IllegalArgumentException}.
1.630 + *
1.631 + * <p>If this {@code Field} object is enforcing Java language access control, and
1.632 + * the underlying field is inaccessible, the method throws an
1.633 + * {@code IllegalAccessException}.
1.634 + *
1.635 + * <p>If the underlying field is final, the method throws an
1.636 + * {@code IllegalAccessException} unless {@code setAccessible(true)}
1.637 + * has succeeded for this {@code Field} object
1.638 + * and the field is non-static. Setting a final field in this way
1.639 + * is meaningful only during deserialization or reconstruction of
1.640 + * instances of classes with blank final fields, before they are
1.641 + * made available for access by other parts of a program. Use in
1.642 + * any other context may have unpredictable effects, including cases
1.643 + * in which other parts of a program continue to use the original
1.644 + * value of this field.
1.645 + *
1.646 + * <p>If the underlying field is of a primitive type, an unwrapping
1.647 + * conversion is attempted to convert the new value to a value of
1.648 + * a primitive type. If this attempt fails, the method throws an
1.649 + * {@code IllegalArgumentException}.
1.650 + *
1.651 + * <p>If, after possible unwrapping, the new value cannot be
1.652 + * converted to the type of the underlying field by an identity or
1.653 + * widening conversion, the method throws an
1.654 + * {@code IllegalArgumentException}.
1.655 + *
1.656 + * <p>If the underlying field is static, the class that declared the
1.657 + * field is initialized if it has not already been initialized.
1.658 + *
1.659 + * <p>The field is set to the possibly unwrapped and widened new value.
1.660 + *
1.661 + * <p>If the field is hidden in the type of {@code obj},
1.662 + * the field's value is set according to the preceding rules.
1.663 + *
1.664 + * @param obj the object whose field should be modified
1.665 + * @param value the new value for the field of {@code obj}
1.666 + * being modified
1.667 + *
1.668 + * @exception IllegalAccessException if this {@code Field} object
1.669 + * is enforcing Java language access control and the underlying
1.670 + * field is either inaccessible or final.
1.671 + * @exception IllegalArgumentException if the specified object is not an
1.672 + * instance of the class or interface declaring the underlying
1.673 + * field (or a subclass or implementor thereof),
1.674 + * or if an unwrapping conversion fails.
1.675 + * @exception NullPointerException if the specified object is null
1.676 + * and the field is an instance field.
1.677 + * @exception ExceptionInInitializerError if the initialization provoked
1.678 + * by this method fails.
1.679 + */
1.680 + public void set(Object obj, Object value)
1.681 + throws IllegalArgumentException, IllegalAccessException
1.682 + {
1.683 + getFieldAccessor(obj).set(obj, value);
1.684 + }
1.685 +
1.686 + /**
1.687 + * Sets the value of a field as a {@code boolean} on the specified object.
1.688 + * This method is equivalent to
1.689 + * {@code set(obj, zObj)},
1.690 + * where {@code zObj} is a {@code Boolean} object and
1.691 + * {@code zObj.booleanValue() == z}.
1.692 + *
1.693 + * @param obj the object whose field should be modified
1.694 + * @param z the new value for the field of {@code obj}
1.695 + * being modified
1.696 + *
1.697 + * @exception IllegalAccessException if this {@code Field} object
1.698 + * is enforcing Java language access control and the underlying
1.699 + * field is either inaccessible or final.
1.700 + * @exception IllegalArgumentException if the specified object is not an
1.701 + * instance of the class or interface declaring the underlying
1.702 + * field (or a subclass or implementor thereof),
1.703 + * or if an unwrapping conversion fails.
1.704 + * @exception NullPointerException if the specified object is null
1.705 + * and the field is an instance field.
1.706 + * @exception ExceptionInInitializerError if the initialization provoked
1.707 + * by this method fails.
1.708 + * @see Field#set
1.709 + */
1.710 + public void setBoolean(Object obj, boolean z)
1.711 + throws IllegalArgumentException, IllegalAccessException
1.712 + {
1.713 + getFieldAccessor(obj).setBoolean(obj, z);
1.714 + }
1.715 +
1.716 + /**
1.717 + * Sets the value of a field as a {@code byte} on the specified object.
1.718 + * This method is equivalent to
1.719 + * {@code set(obj, bObj)},
1.720 + * where {@code bObj} is a {@code Byte} object and
1.721 + * {@code bObj.byteValue() == b}.
1.722 + *
1.723 + * @param obj the object whose field should be modified
1.724 + * @param b the new value for the field of {@code obj}
1.725 + * being modified
1.726 + *
1.727 + * @exception IllegalAccessException if this {@code Field} object
1.728 + * is enforcing Java language access control and the underlying
1.729 + * field is either inaccessible or final.
1.730 + * @exception IllegalArgumentException if the specified object is not an
1.731 + * instance of the class or interface declaring the underlying
1.732 + * field (or a subclass or implementor thereof),
1.733 + * or if an unwrapping conversion fails.
1.734 + * @exception NullPointerException if the specified object is null
1.735 + * and the field is an instance field.
1.736 + * @exception ExceptionInInitializerError if the initialization provoked
1.737 + * by this method fails.
1.738 + * @see Field#set
1.739 + */
1.740 + public void setByte(Object obj, byte b)
1.741 + throws IllegalArgumentException, IllegalAccessException
1.742 + {
1.743 + getFieldAccessor(obj).setByte(obj, b);
1.744 + }
1.745 +
1.746 + /**
1.747 + * Sets the value of a field as a {@code char} on the specified object.
1.748 + * This method is equivalent to
1.749 + * {@code set(obj, cObj)},
1.750 + * where {@code cObj} is a {@code Character} object and
1.751 + * {@code cObj.charValue() == c}.
1.752 + *
1.753 + * @param obj the object whose field should be modified
1.754 + * @param c the new value for the field of {@code obj}
1.755 + * being modified
1.756 + *
1.757 + * @exception IllegalAccessException if this {@code Field} object
1.758 + * is enforcing Java language access control and the underlying
1.759 + * field is either inaccessible or final.
1.760 + * @exception IllegalArgumentException if the specified object is not an
1.761 + * instance of the class or interface declaring the underlying
1.762 + * field (or a subclass or implementor thereof),
1.763 + * or if an unwrapping conversion fails.
1.764 + * @exception NullPointerException if the specified object is null
1.765 + * and the field is an instance field.
1.766 + * @exception ExceptionInInitializerError if the initialization provoked
1.767 + * by this method fails.
1.768 + * @see Field#set
1.769 + */
1.770 + public void setChar(Object obj, char c)
1.771 + throws IllegalArgumentException, IllegalAccessException
1.772 + {
1.773 + getFieldAccessor(obj).setChar(obj, c);
1.774 + }
1.775 +
1.776 + /**
1.777 + * Sets the value of a field as a {@code short} on the specified object.
1.778 + * This method is equivalent to
1.779 + * {@code set(obj, sObj)},
1.780 + * where {@code sObj} is a {@code Short} object and
1.781 + * {@code sObj.shortValue() == s}.
1.782 + *
1.783 + * @param obj the object whose field should be modified
1.784 + * @param s the new value for the field of {@code obj}
1.785 + * being modified
1.786 + *
1.787 + * @exception IllegalAccessException if this {@code Field} object
1.788 + * is enforcing Java language access control and the underlying
1.789 + * field is either inaccessible or final.
1.790 + * @exception IllegalArgumentException if the specified object is not an
1.791 + * instance of the class or interface declaring the underlying
1.792 + * field (or a subclass or implementor thereof),
1.793 + * or if an unwrapping conversion fails.
1.794 + * @exception NullPointerException if the specified object is null
1.795 + * and the field is an instance field.
1.796 + * @exception ExceptionInInitializerError if the initialization provoked
1.797 + * by this method fails.
1.798 + * @see Field#set
1.799 + */
1.800 + public void setShort(Object obj, short s)
1.801 + throws IllegalArgumentException, IllegalAccessException
1.802 + {
1.803 + getFieldAccessor(obj).setShort(obj, s);
1.804 + }
1.805 +
1.806 + /**
1.807 + * Sets the value of a field as an {@code int} on the specified object.
1.808 + * This method is equivalent to
1.809 + * {@code set(obj, iObj)},
1.810 + * where {@code iObj} is a {@code Integer} object and
1.811 + * {@code iObj.intValue() == i}.
1.812 + *
1.813 + * @param obj the object whose field should be modified
1.814 + * @param i the new value for the field of {@code obj}
1.815 + * being modified
1.816 + *
1.817 + * @exception IllegalAccessException if this {@code Field} object
1.818 + * is enforcing Java language access control and the underlying
1.819 + * field is either inaccessible or final.
1.820 + * @exception IllegalArgumentException if the specified object is not an
1.821 + * instance of the class or interface declaring the underlying
1.822 + * field (or a subclass or implementor thereof),
1.823 + * or if an unwrapping conversion fails.
1.824 + * @exception NullPointerException if the specified object is null
1.825 + * and the field is an instance field.
1.826 + * @exception ExceptionInInitializerError if the initialization provoked
1.827 + * by this method fails.
1.828 + * @see Field#set
1.829 + */
1.830 + public void setInt(Object obj, int i)
1.831 + throws IllegalArgumentException, IllegalAccessException
1.832 + {
1.833 + getFieldAccessor(obj).setInt(obj, i);
1.834 + }
1.835 +
1.836 + /**
1.837 + * Sets the value of a field as a {@code long} on the specified object.
1.838 + * This method is equivalent to
1.839 + * {@code set(obj, lObj)},
1.840 + * where {@code lObj} is a {@code Long} object and
1.841 + * {@code lObj.longValue() == l}.
1.842 + *
1.843 + * @param obj the object whose field should be modified
1.844 + * @param l the new value for the field of {@code obj}
1.845 + * being modified
1.846 + *
1.847 + * @exception IllegalAccessException if this {@code Field} object
1.848 + * is enforcing Java language access control and the underlying
1.849 + * field is either inaccessible or final.
1.850 + * @exception IllegalArgumentException if the specified object is not an
1.851 + * instance of the class or interface declaring the underlying
1.852 + * field (or a subclass or implementor thereof),
1.853 + * or if an unwrapping conversion fails.
1.854 + * @exception NullPointerException if the specified object is null
1.855 + * and the field is an instance field.
1.856 + * @exception ExceptionInInitializerError if the initialization provoked
1.857 + * by this method fails.
1.858 + * @see Field#set
1.859 + */
1.860 + public void setLong(Object obj, long l)
1.861 + throws IllegalArgumentException, IllegalAccessException
1.862 + {
1.863 + getFieldAccessor(obj).setLong(obj, l);
1.864 + }
1.865 +
1.866 + /**
1.867 + * Sets the value of a field as a {@code float} on the specified object.
1.868 + * This method is equivalent to
1.869 + * {@code set(obj, fObj)},
1.870 + * where {@code fObj} is a {@code Float} object and
1.871 + * {@code fObj.floatValue() == f}.
1.872 + *
1.873 + * @param obj the object whose field should be modified
1.874 + * @param f the new value for the field of {@code obj}
1.875 + * being modified
1.876 + *
1.877 + * @exception IllegalAccessException if this {@code Field} object
1.878 + * is enforcing Java language access control and the underlying
1.879 + * field is either inaccessible or final.
1.880 + * @exception IllegalArgumentException if the specified object is not an
1.881 + * instance of the class or interface declaring the underlying
1.882 + * field (or a subclass or implementor thereof),
1.883 + * or if an unwrapping conversion fails.
1.884 + * @exception NullPointerException if the specified object is null
1.885 + * and the field is an instance field.
1.886 + * @exception ExceptionInInitializerError if the initialization provoked
1.887 + * by this method fails.
1.888 + * @see Field#set
1.889 + */
1.890 + public void setFloat(Object obj, float f)
1.891 + throws IllegalArgumentException, IllegalAccessException
1.892 + {
1.893 + getFieldAccessor(obj).setFloat(obj, f);
1.894 + }
1.895 +
1.896 + /**
1.897 + * Sets the value of a field as a {@code double} on the specified object.
1.898 + * This method is equivalent to
1.899 + * {@code set(obj, dObj)},
1.900 + * where {@code dObj} is a {@code Double} object and
1.901 + * {@code dObj.doubleValue() == d}.
1.902 + *
1.903 + * @param obj the object whose field should be modified
1.904 + * @param d the new value for the field of {@code obj}
1.905 + * being modified
1.906 + *
1.907 + * @exception IllegalAccessException if this {@code Field} object
1.908 + * is enforcing Java language access control and the underlying
1.909 + * field is either inaccessible or final.
1.910 + * @exception IllegalArgumentException if the specified object is not an
1.911 + * instance of the class or interface declaring the underlying
1.912 + * field (or a subclass or implementor thereof),
1.913 + * or if an unwrapping conversion fails.
1.914 + * @exception NullPointerException if the specified object is null
1.915 + * and the field is an instance field.
1.916 + * @exception ExceptionInInitializerError if the initialization provoked
1.917 + * by this method fails.
1.918 + * @see Field#set
1.919 + */
1.920 + public void setDouble(Object obj, double d)
1.921 + throws IllegalArgumentException, IllegalAccessException
1.922 + {
1.923 + getFieldAccessor(obj).setDouble(obj, d);
1.924 + }
1.925 +
1.926 + // Convenience routine which performs security checks
1.927 + private FieldAccessor getFieldAccessor(Object obj)
1.928 + throws IllegalAccessException
1.929 + {
1.930 + doSecurityCheck(obj);
1.931 + boolean ov = override;
1.932 + FieldAccessor a = (ov)? overrideFieldAccessor : fieldAccessor;
1.933 + return (a != null)? a : acquireFieldAccessor(ov);
1.934 + }
1.935 +
1.936 + // NOTE that there is no synchronization used here. It is correct
1.937 + // (though not efficient) to generate more than one FieldAccessor
1.938 + // for a given Field. However, avoiding synchronization will
1.939 + // probably make the implementation more scalable.
1.940 + private FieldAccessor acquireFieldAccessor(boolean overrideFinalCheck) {
1.941 + // First check to see if one has been created yet, and take it
1.942 + // if so
1.943 + FieldAccessor tmp = null;
1.944 + if (root != null) tmp = root.getFieldAccessor(overrideFinalCheck);
1.945 + if (tmp != null) {
1.946 + if (overrideFinalCheck)
1.947 + overrideFieldAccessor = tmp;
1.948 + else
1.949 + fieldAccessor = tmp;
1.950 + } else {
1.951 + // Otherwise fabricate one and propagate it up to the root
1.952 + tmp = reflectionFactory.newFieldAccessor(this, overrideFinalCheck);
1.953 + setFieldAccessor(tmp, overrideFinalCheck);
1.954 + }
1.955 +
1.956 + return tmp;
1.957 + }
1.958 +
1.959 + // Returns FieldAccessor for this Field object, not looking up
1.960 + // the chain to the root
1.961 + private FieldAccessor getFieldAccessor(boolean overrideFinalCheck) {
1.962 + return (overrideFinalCheck)? overrideFieldAccessor : fieldAccessor;
1.963 + }
1.964 +
1.965 + // Sets the FieldAccessor for this Field object and
1.966 + // (recursively) its root
1.967 + private void setFieldAccessor(FieldAccessor accessor, boolean overrideFinalCheck) {
1.968 + if (overrideFinalCheck)
1.969 + overrideFieldAccessor = accessor;
1.970 + else
1.971 + fieldAccessor = accessor;
1.972 + // Propagate up
1.973 + if (root != null) {
1.974 + root.setFieldAccessor(accessor, overrideFinalCheck);
1.975 + }
1.976 + }
1.977 +
1.978 + // NOTE: be very careful if you change the stack depth of this
1.979 + // routine. The depth of the "getCallerClass" call is hardwired so
1.980 + // that the compiler can have an easier time if this gets inlined.
1.981 + private void doSecurityCheck(Object obj) throws IllegalAccessException {
1.982 + if (!override) {
1.983 + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
1.984 + Class<?> caller = Reflection.getCallerClass(4);
1.985 +
1.986 + checkAccess(caller, clazz, obj, modifiers);
1.987 + }
1.988 + }
1.989 + }
1.990 +
1.991 + /*
1.992 + * Utility routine to paper over array type names
1.993 + */
1.994 + static String getTypeName(Class<?> type) {
1.995 + if (type.isArray()) {
1.996 + try {
1.997 + Class<?> cl = type;
1.998 + int dimensions = 0;
1.999 + while (cl.isArray()) {
1.1000 + dimensions++;
1.1001 + cl = cl.getComponentType();
1.1002 + }
1.1003 + StringBuffer sb = new StringBuffer();
1.1004 + sb.append(cl.getName());
1.1005 + for (int i = 0; i < dimensions; i++) {
1.1006 + sb.append("[]");
1.1007 + }
1.1008 + return sb.toString();
1.1009 + } catch (Throwable e) { /*FALLTHRU*/ }
1.1010 + }
1.1011 + return type.getName();
1.1012 + }
1.1013 +
1.1014 + /**
1.1015 + * @throws NullPointerException {@inheritDoc}
1.1016 + * @since 1.5
1.1017 + */
1.1018 + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
1.1019 + if (annotationClass == null)
1.1020 + throw new NullPointerException();
1.1021 +
1.1022 + return (T) declaredAnnotations().get(annotationClass);
1.1023 + }
1.1024 +
1.1025 + /**
1.1026 + * @since 1.5
1.1027 + */
1.1028 + public Annotation[] getDeclaredAnnotations() {
1.1029 + return AnnotationParser.toArray(declaredAnnotations());
1.1030 + }
1.1031 +
1.1032 + private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
1.1033 +
1.1034 + private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
1.1035 + if (declaredAnnotations == null) {
1.1036 + declaredAnnotations = AnnotationParser.parseAnnotations(
1.1037 + annotations, sun.misc.SharedSecrets.getJavaLangAccess().
1.1038 + getConstantPool(getDeclaringClass()),
1.1039 + getDeclaringClass());
1.1040 + }
1.1041 + return declaredAnnotations;
1.1042 + }
1.1043 +}