jtulach@258: /* jtulach@258: * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. jtulach@258: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jtulach@258: * jtulach@258: * This code is free software; you can redistribute it and/or modify it jtulach@258: * under the terms of the GNU General Public License version 2 only, as jtulach@258: * published by the Free Software Foundation. Oracle designates this jtulach@258: * particular file as subject to the "Classpath" exception as provided jtulach@258: * by Oracle in the LICENSE file that accompanied this code. jtulach@258: * jtulach@258: * This code is distributed in the hope that it will be useful, but WITHOUT jtulach@258: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jtulach@258: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jtulach@258: * version 2 for more details (a copy is included in the LICENSE file that jtulach@258: * accompanied this code). jtulach@258: * jtulach@258: * You should have received a copy of the GNU General Public License version jtulach@258: * 2 along with this work; if not, write to the Free Software Foundation, jtulach@258: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jtulach@258: * jtulach@258: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jtulach@258: * or visit www.oracle.com if you need additional information or have any jtulach@258: * questions. jtulach@258: */ jtulach@258: jtulach@258: package java.lang.reflect; jtulach@258: jtulach@258: import sun.reflect.FieldAccessor; jtulach@258: import sun.reflect.Reflection; jtulach@258: import sun.reflect.generics.repository.FieldRepository; jtulach@258: import sun.reflect.generics.factory.CoreReflectionFactory; jtulach@258: import sun.reflect.generics.factory.GenericsFactory; jtulach@258: import sun.reflect.generics.scope.ClassScope; jtulach@258: import java.lang.annotation.Annotation; jtulach@258: import java.util.Map; jtulach@258: import sun.reflect.annotation.AnnotationParser; jtulach@258: jtulach@258: jtulach@258: /** jtulach@258: * A {@code Field} provides information about, and dynamic access to, a jtulach@258: * single field of a class or an interface. The reflected field may jtulach@258: * be a class (static) field or an instance field. jtulach@258: * jtulach@258: *

A {@code Field} permits widening conversions to occur during a get or jtulach@258: * set access operation, but throws an {@code IllegalArgumentException} if a jtulach@258: * narrowing conversion would occur. jtulach@258: * jtulach@258: * @see Member jtulach@258: * @see java.lang.Class jtulach@258: * @see java.lang.Class#getFields() jtulach@258: * @see java.lang.Class#getField(String) jtulach@258: * @see java.lang.Class#getDeclaredFields() jtulach@258: * @see java.lang.Class#getDeclaredField(String) jtulach@258: * jtulach@258: * @author Kenneth Russell jtulach@258: * @author Nakul Saraiya jtulach@258: */ jtulach@258: public final jtulach@258: class Field extends AccessibleObject implements Member { jtulach@258: jtulach@258: private Class clazz; jtulach@258: private int slot; jtulach@258: // This is guaranteed to be interned by the VM in the 1.4 jtulach@258: // reflection implementation jtulach@258: private String name; jtulach@258: private Class type; jtulach@258: private int modifiers; jtulach@258: // Generics and annotations support jtulach@258: private transient String signature; jtulach@258: // generic info repository; lazily initialized jtulach@258: private transient FieldRepository genericInfo; jtulach@258: private byte[] annotations; jtulach@258: // Cached field accessor created without override jtulach@258: private FieldAccessor fieldAccessor; jtulach@258: // Cached field accessor created with override jtulach@258: private FieldAccessor overrideFieldAccessor; jtulach@258: // For sharing of FieldAccessors. This branching structure is jtulach@258: // currently only two levels deep (i.e., one root Field and jtulach@258: // potentially many Field objects pointing to it.) jtulach@258: private Field root; jtulach@258: jtulach@258: // Generics infrastructure jtulach@258: jtulach@258: private String getGenericSignature() {return signature;} jtulach@258: jtulach@258: // Accessor for factory jtulach@258: private GenericsFactory getFactory() { jtulach@258: Class c = getDeclaringClass(); jtulach@258: // create scope and factory jtulach@258: return CoreReflectionFactory.make(c, ClassScope.make(c)); jtulach@258: } jtulach@258: jtulach@258: // Accessor for generic info repository jtulach@258: private FieldRepository getGenericInfo() { jtulach@258: // lazily initialize repository if necessary jtulach@258: if (genericInfo == null) { jtulach@258: // create and cache generic info repository jtulach@258: genericInfo = FieldRepository.make(getGenericSignature(), jtulach@258: getFactory()); jtulach@258: } jtulach@258: return genericInfo; //return cached repository jtulach@258: } jtulach@258: jtulach@258: jtulach@258: /** jtulach@258: * Package-private constructor used by ReflectAccess to enable jtulach@258: * instantiation of these objects in Java code from the java.lang jtulach@258: * package via sun.reflect.LangReflectAccess. jtulach@258: */ jtulach@258: Field(Class declaringClass, jtulach@258: String name, jtulach@258: Class type, jtulach@258: int modifiers, jtulach@258: int slot, jtulach@258: String signature, jtulach@258: byte[] annotations) jtulach@258: { jtulach@258: this.clazz = declaringClass; jtulach@258: this.name = name; jtulach@258: this.type = type; jtulach@258: this.modifiers = modifiers; jtulach@258: this.slot = slot; jtulach@258: this.signature = signature; jtulach@258: this.annotations = annotations; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Package-private routine (exposed to java.lang.Class via jtulach@258: * ReflectAccess) which returns a copy of this Field. The copy's jtulach@258: * "root" field points to this Field. jtulach@258: */ jtulach@258: Field copy() { jtulach@258: // This routine enables sharing of FieldAccessor objects jtulach@258: // among Field objects which refer to the same underlying jtulach@258: // method in the VM. (All of this contortion is only necessary jtulach@258: // because of the "accessibility" bit in AccessibleObject, jtulach@258: // which implicitly requires that new java.lang.reflect jtulach@258: // objects be fabricated for each reflective call on Class jtulach@258: // objects.) jtulach@258: Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations); jtulach@258: res.root = this; jtulach@258: // Might as well eagerly propagate this if already present jtulach@258: res.fieldAccessor = fieldAccessor; jtulach@258: res.overrideFieldAccessor = overrideFieldAccessor; jtulach@258: return res; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns the {@code Class} object representing the class or interface jtulach@258: * that declares the field represented by this {@code Field} object. jtulach@258: */ jtulach@258: public Class getDeclaringClass() { jtulach@258: return clazz; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns the name of the field represented by this {@code Field} object. jtulach@258: */ jtulach@258: public String getName() { jtulach@258: return name; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns the Java language modifiers for the field represented jtulach@258: * by this {@code Field} object, as an integer. The {@code Modifier} class should jtulach@258: * be used to decode the modifiers. jtulach@258: * jtulach@258: * @see Modifier jtulach@258: */ jtulach@258: public int getModifiers() { jtulach@258: return modifiers; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns {@code true} if this field represents an element of jtulach@258: * an enumerated type; returns {@code false} otherwise. jtulach@258: * jtulach@258: * @return {@code true} if and only if this field represents an element of jtulach@258: * an enumerated type. jtulach@258: * @since 1.5 jtulach@258: */ jtulach@258: public boolean isEnumConstant() { jtulach@258: return (getModifiers() & Modifier.ENUM) != 0; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns {@code true} if this field is a synthetic jtulach@258: * field; returns {@code false} otherwise. jtulach@258: * jtulach@258: * @return true if and only if this field is a synthetic jtulach@258: * field as defined by the Java Language Specification. jtulach@258: * @since 1.5 jtulach@258: */ jtulach@258: public boolean isSynthetic() { jtulach@258: return Modifier.isSynthetic(getModifiers()); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns a {@code Class} object that identifies the jtulach@258: * declared type for the field represented by this jtulach@258: * {@code Field} object. jtulach@258: * jtulach@258: * @return a {@code Class} object identifying the declared jtulach@258: * type of the field represented by this object jtulach@258: */ jtulach@258: public Class getType() { jtulach@258: return type; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns a {@code Type} object that represents the declared type for jtulach@258: * the field represented by this {@code Field} object. jtulach@258: * jtulach@258: *

If the {@code Type} is a parameterized type, the jtulach@258: * {@code Type} object returned must accurately reflect the jtulach@258: * actual type parameters used in the source code. jtulach@258: * jtulach@258: *

If the type of the underlying field is a type variable or a jtulach@258: * parameterized type, it is created. Otherwise, it is resolved. jtulach@258: * jtulach@258: * @return a {@code Type} object that represents the declared type for jtulach@258: * the field represented by this {@code Field} object jtulach@258: * @throws GenericSignatureFormatError if the generic field jtulach@258: * signature does not conform to the format specified in jtulach@258: * The Java™ Virtual Machine Specification jtulach@258: * @throws TypeNotPresentException if the generic type jtulach@258: * signature of the underlying field refers to a non-existent jtulach@258: * type declaration jtulach@258: * @throws MalformedParameterizedTypeException if the generic jtulach@258: * signature of the underlying field refers to a parameterized type jtulach@258: * that cannot be instantiated for any reason jtulach@258: * @since 1.5 jtulach@258: */ jtulach@258: public Type getGenericType() { jtulach@258: if (getGenericSignature() != null) jtulach@258: return getGenericInfo().getGenericType(); jtulach@258: else jtulach@258: return getType(); jtulach@258: } jtulach@258: jtulach@258: jtulach@258: /** jtulach@258: * Compares this {@code Field} against the specified object. Returns jtulach@258: * true if the objects are the same. Two {@code Field} objects are the same if jtulach@258: * they were declared by the same class and have the same name jtulach@258: * and type. jtulach@258: */ jtulach@258: public boolean equals(Object obj) { jtulach@258: if (obj != null && obj instanceof Field) { jtulach@258: Field other = (Field)obj; jtulach@258: return (getDeclaringClass() == other.getDeclaringClass()) jtulach@258: && (getName() == other.getName()) jtulach@258: && (getType() == other.getType()); jtulach@258: } jtulach@258: return false; jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns a hashcode for this {@code Field}. This is computed as the jtulach@258: * exclusive-or of the hashcodes for the underlying field's jtulach@258: * declaring class name and its name. jtulach@258: */ jtulach@258: public int hashCode() { jtulach@258: return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns a string describing this {@code Field}. The format is jtulach@258: * the access modifiers for the field, if any, followed jtulach@258: * by the field type, followed by a space, followed by jtulach@258: * the fully-qualified name of the class declaring the field, jtulach@258: * followed by a period, followed by the name of the field. jtulach@258: * For example: jtulach@258: *

jtulach@258:      *    public static final int java.lang.Thread.MIN_PRIORITY
jtulach@258:      *    private int java.io.FileDescriptor.fd
jtulach@258:      * 
jtulach@258: * jtulach@258: *

The modifiers are placed in canonical order as specified by jtulach@258: * "The Java Language Specification". This is {@code public}, jtulach@258: * {@code protected} or {@code private} first, and then other jtulach@258: * modifiers in the following order: {@code static}, {@code final}, jtulach@258: * {@code transient}, {@code volatile}. jtulach@258: */ jtulach@258: public String toString() { jtulach@258: int mod = getModifiers(); jtulach@258: return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) jtulach@258: + getTypeName(getType()) + " " jtulach@258: + getTypeName(getDeclaringClass()) + "." jtulach@258: + getName()); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns a string describing this {@code Field}, including jtulach@258: * its generic type. The format is the access modifiers for the jtulach@258: * field, if any, followed by the generic field type, followed by jtulach@258: * a space, followed by the fully-qualified name of the class jtulach@258: * declaring the field, followed by a period, followed by the name jtulach@258: * of the field. jtulach@258: * jtulach@258: *

The modifiers are placed in canonical order as specified by jtulach@258: * "The Java Language Specification". This is {@code public}, jtulach@258: * {@code protected} or {@code private} first, and then other jtulach@258: * modifiers in the following order: {@code static}, {@code final}, jtulach@258: * {@code transient}, {@code volatile}. jtulach@258: * jtulach@258: * @return a string describing this {@code Field}, including jtulach@258: * its generic type jtulach@258: * jtulach@258: * @since 1.5 jtulach@258: */ jtulach@258: public String toGenericString() { jtulach@258: int mod = getModifiers(); jtulach@258: Type fieldType = getGenericType(); jtulach@258: return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) jtulach@258: + ((fieldType instanceof Class) ? jtulach@258: getTypeName((Class)fieldType): fieldType.toString())+ " " jtulach@258: + getTypeName(getDeclaringClass()) + "." jtulach@258: + getName()); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Returns the value of the field represented by this {@code Field}, on jtulach@258: * the specified object. The value is automatically wrapped in an jtulach@258: * object if it has a primitive type. jtulach@258: * jtulach@258: *

The underlying field's value is obtained as follows: jtulach@258: * jtulach@258: *

If the underlying field is a static field, the {@code obj} argument jtulach@258: * is ignored; it may be null. jtulach@258: * jtulach@258: *

Otherwise, the underlying field is an instance field. If the jtulach@258: * specified {@code obj} argument is null, the method throws a jtulach@258: * {@code NullPointerException}. If the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field, the method throws an {@code IllegalArgumentException}. jtulach@258: * jtulach@258: *

If this {@code Field} object is enforcing Java language access control, and jtulach@258: * the underlying field is inaccessible, the method throws an jtulach@258: * {@code IllegalAccessException}. jtulach@258: * If the underlying field is static, the class that declared the jtulach@258: * field is initialized if it has not already been initialized. jtulach@258: * jtulach@258: *

Otherwise, the value is retrieved from the underlying instance jtulach@258: * or static field. If the field has a primitive type, the value jtulach@258: * is wrapped in an object before being returned, otherwise it is jtulach@258: * returned as is. jtulach@258: * jtulach@258: *

If the field is hidden in the type of {@code obj}, jtulach@258: * the field's value is obtained according to the preceding rules. jtulach@258: * jtulach@258: * @param obj object from which the represented field's value is jtulach@258: * to be extracted jtulach@258: * @return the value of the represented field in object jtulach@258: * {@code obj}; primitive values are wrapped in an appropriate jtulach@258: * object before being returned jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is inaccessible. jtulach@258: * @exception IllegalArgumentException if the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field (or a subclass or implementor thereof). jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: */ jtulach@258: public Object get(Object obj) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: return getFieldAccessor(obj).get(obj); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Gets the value of a static or instance {@code boolean} field. jtulach@258: * jtulach@258: * @param obj the object to extract the {@code boolean} value jtulach@258: * from jtulach@258: * @return the value of the {@code boolean} field jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is inaccessible. jtulach@258: * @exception IllegalArgumentException if the specified object is not jtulach@258: * an instance of the class or interface declaring the jtulach@258: * underlying field (or a subclass or implementor jtulach@258: * thereof), or if the field value cannot be jtulach@258: * converted to the type {@code boolean} by a jtulach@258: * widening conversion. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#get jtulach@258: */ jtulach@258: public boolean getBoolean(Object obj) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: return getFieldAccessor(obj).getBoolean(obj); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Gets the value of a static or instance {@code byte} field. jtulach@258: * jtulach@258: * @param obj the object to extract the {@code byte} value jtulach@258: * from jtulach@258: * @return the value of the {@code byte} field jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is inaccessible. jtulach@258: * @exception IllegalArgumentException if the specified object is not jtulach@258: * an instance of the class or interface declaring the jtulach@258: * underlying field (or a subclass or implementor jtulach@258: * thereof), or if the field value cannot be jtulach@258: * converted to the type {@code byte} by a jtulach@258: * widening conversion. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#get jtulach@258: */ jtulach@258: public byte getByte(Object obj) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: return getFieldAccessor(obj).getByte(obj); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Gets the value of a static or instance field of type jtulach@258: * {@code char} or of another primitive type convertible to jtulach@258: * type {@code char} via a widening conversion. jtulach@258: * jtulach@258: * @param obj the object to extract the {@code char} value jtulach@258: * from jtulach@258: * @return the value of the field converted to type {@code char} jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is inaccessible. jtulach@258: * @exception IllegalArgumentException if the specified object is not jtulach@258: * an instance of the class or interface declaring the jtulach@258: * underlying field (or a subclass or implementor jtulach@258: * thereof), or if the field value cannot be jtulach@258: * converted to the type {@code char} by a jtulach@258: * widening conversion. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#get jtulach@258: */ jtulach@258: public char getChar(Object obj) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: return getFieldAccessor(obj).getChar(obj); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Gets the value of a static or instance field of type jtulach@258: * {@code short} or of another primitive type convertible to jtulach@258: * type {@code short} via a widening conversion. jtulach@258: * jtulach@258: * @param obj the object to extract the {@code short} value jtulach@258: * from jtulach@258: * @return the value of the field converted to type {@code short} jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is inaccessible. jtulach@258: * @exception IllegalArgumentException if the specified object is not jtulach@258: * an instance of the class or interface declaring the jtulach@258: * underlying field (or a subclass or implementor jtulach@258: * thereof), or if the field value cannot be jtulach@258: * converted to the type {@code short} by a jtulach@258: * widening conversion. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#get jtulach@258: */ jtulach@258: public short getShort(Object obj) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: return getFieldAccessor(obj).getShort(obj); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Gets the value of a static or instance field of type jtulach@258: * {@code int} or of another primitive type convertible to jtulach@258: * type {@code int} via a widening conversion. jtulach@258: * jtulach@258: * @param obj the object to extract the {@code int} value jtulach@258: * from jtulach@258: * @return the value of the field converted to type {@code int} jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is inaccessible. jtulach@258: * @exception IllegalArgumentException if the specified object is not jtulach@258: * an instance of the class or interface declaring the jtulach@258: * underlying field (or a subclass or implementor jtulach@258: * thereof), or if the field value cannot be jtulach@258: * converted to the type {@code int} by a jtulach@258: * widening conversion. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#get jtulach@258: */ jtulach@258: public int getInt(Object obj) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: return getFieldAccessor(obj).getInt(obj); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Gets the value of a static or instance field of type jtulach@258: * {@code long} or of another primitive type convertible to jtulach@258: * type {@code long} via a widening conversion. jtulach@258: * jtulach@258: * @param obj the object to extract the {@code long} value jtulach@258: * from jtulach@258: * @return the value of the field converted to type {@code long} jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is inaccessible. jtulach@258: * @exception IllegalArgumentException if the specified object is not jtulach@258: * an instance of the class or interface declaring the jtulach@258: * underlying field (or a subclass or implementor jtulach@258: * thereof), or if the field value cannot be jtulach@258: * converted to the type {@code long} by a jtulach@258: * widening conversion. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#get jtulach@258: */ jtulach@258: public long getLong(Object obj) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: return getFieldAccessor(obj).getLong(obj); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Gets the value of a static or instance field of type jtulach@258: * {@code float} or of another primitive type convertible to jtulach@258: * type {@code float} via a widening conversion. jtulach@258: * jtulach@258: * @param obj the object to extract the {@code float} value jtulach@258: * from jtulach@258: * @return the value of the field converted to type {@code float} jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is inaccessible. jtulach@258: * @exception IllegalArgumentException if the specified object is not jtulach@258: * an instance of the class or interface declaring the jtulach@258: * underlying field (or a subclass or implementor jtulach@258: * thereof), or if the field value cannot be jtulach@258: * converted to the type {@code float} by a jtulach@258: * widening conversion. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#get jtulach@258: */ jtulach@258: public float getFloat(Object obj) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: return getFieldAccessor(obj).getFloat(obj); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Gets the value of a static or instance field of type jtulach@258: * {@code double} or of another primitive type convertible to jtulach@258: * type {@code double} via a widening conversion. jtulach@258: * jtulach@258: * @param obj the object to extract the {@code double} value jtulach@258: * from jtulach@258: * @return the value of the field converted to type {@code double} jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is inaccessible. jtulach@258: * @exception IllegalArgumentException if the specified object is not jtulach@258: * an instance of the class or interface declaring the jtulach@258: * underlying field (or a subclass or implementor jtulach@258: * thereof), or if the field value cannot be jtulach@258: * converted to the type {@code double} by a jtulach@258: * widening conversion. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#get jtulach@258: */ jtulach@258: public double getDouble(Object obj) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: return getFieldAccessor(obj).getDouble(obj); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Sets the field represented by this {@code Field} object on the jtulach@258: * specified object argument to the specified new value. The new jtulach@258: * value is automatically unwrapped if the underlying field has a jtulach@258: * primitive type. jtulach@258: * jtulach@258: *

The operation proceeds as follows: jtulach@258: * jtulach@258: *

If the underlying field is static, the {@code obj} argument is jtulach@258: * ignored; it may be null. jtulach@258: * jtulach@258: *

Otherwise the underlying field is an instance field. If the jtulach@258: * specified object argument is null, the method throws a jtulach@258: * {@code NullPointerException}. If the specified object argument is not jtulach@258: * an instance of the class or interface declaring the underlying jtulach@258: * field, the method throws an {@code IllegalArgumentException}. jtulach@258: * jtulach@258: *

If this {@code Field} object is enforcing Java language access control, and jtulach@258: * the underlying field is inaccessible, the method throws an jtulach@258: * {@code IllegalAccessException}. jtulach@258: * jtulach@258: *

If the underlying field is final, the method throws an jtulach@258: * {@code IllegalAccessException} unless {@code setAccessible(true)} jtulach@258: * has succeeded for this {@code Field} object jtulach@258: * and the field is non-static. Setting a final field in this way jtulach@258: * is meaningful only during deserialization or reconstruction of jtulach@258: * instances of classes with blank final fields, before they are jtulach@258: * made available for access by other parts of a program. Use in jtulach@258: * any other context may have unpredictable effects, including cases jtulach@258: * in which other parts of a program continue to use the original jtulach@258: * value of this field. jtulach@258: * jtulach@258: *

If the underlying field is of a primitive type, an unwrapping jtulach@258: * conversion is attempted to convert the new value to a value of jtulach@258: * a primitive type. If this attempt fails, the method throws an jtulach@258: * {@code IllegalArgumentException}. jtulach@258: * jtulach@258: *

If, after possible unwrapping, the new value cannot be jtulach@258: * converted to the type of the underlying field by an identity or jtulach@258: * widening conversion, the method throws an jtulach@258: * {@code IllegalArgumentException}. jtulach@258: * jtulach@258: *

If the underlying field is static, the class that declared the jtulach@258: * field is initialized if it has not already been initialized. jtulach@258: * jtulach@258: *

The field is set to the possibly unwrapped and widened new value. jtulach@258: * jtulach@258: *

If the field is hidden in the type of {@code obj}, jtulach@258: * the field's value is set according to the preceding rules. jtulach@258: * jtulach@258: * @param obj the object whose field should be modified jtulach@258: * @param value the new value for the field of {@code obj} jtulach@258: * being modified jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is either inaccessible or final. jtulach@258: * @exception IllegalArgumentException if the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field (or a subclass or implementor thereof), jtulach@258: * or if an unwrapping conversion fails. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: */ jtulach@258: public void set(Object obj, Object value) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: getFieldAccessor(obj).set(obj, value); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Sets the value of a field as a {@code boolean} on the specified object. jtulach@258: * This method is equivalent to jtulach@258: * {@code set(obj, zObj)}, jtulach@258: * where {@code zObj} is a {@code Boolean} object and jtulach@258: * {@code zObj.booleanValue() == z}. jtulach@258: * jtulach@258: * @param obj the object whose field should be modified jtulach@258: * @param z the new value for the field of {@code obj} jtulach@258: * being modified jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is either inaccessible or final. jtulach@258: * @exception IllegalArgumentException if the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field (or a subclass or implementor thereof), jtulach@258: * or if an unwrapping conversion fails. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#set jtulach@258: */ jtulach@258: public void setBoolean(Object obj, boolean z) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: getFieldAccessor(obj).setBoolean(obj, z); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Sets the value of a field as a {@code byte} on the specified object. jtulach@258: * This method is equivalent to jtulach@258: * {@code set(obj, bObj)}, jtulach@258: * where {@code bObj} is a {@code Byte} object and jtulach@258: * {@code bObj.byteValue() == b}. jtulach@258: * jtulach@258: * @param obj the object whose field should be modified jtulach@258: * @param b the new value for the field of {@code obj} jtulach@258: * being modified jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is either inaccessible or final. jtulach@258: * @exception IllegalArgumentException if the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field (or a subclass or implementor thereof), jtulach@258: * or if an unwrapping conversion fails. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#set jtulach@258: */ jtulach@258: public void setByte(Object obj, byte b) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: getFieldAccessor(obj).setByte(obj, b); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Sets the value of a field as a {@code char} on the specified object. jtulach@258: * This method is equivalent to jtulach@258: * {@code set(obj, cObj)}, jtulach@258: * where {@code cObj} is a {@code Character} object and jtulach@258: * {@code cObj.charValue() == c}. jtulach@258: * jtulach@258: * @param obj the object whose field should be modified jtulach@258: * @param c the new value for the field of {@code obj} jtulach@258: * being modified jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is either inaccessible or final. jtulach@258: * @exception IllegalArgumentException if the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field (or a subclass or implementor thereof), jtulach@258: * or if an unwrapping conversion fails. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#set jtulach@258: */ jtulach@258: public void setChar(Object obj, char c) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: getFieldAccessor(obj).setChar(obj, c); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Sets the value of a field as a {@code short} on the specified object. jtulach@258: * This method is equivalent to jtulach@258: * {@code set(obj, sObj)}, jtulach@258: * where {@code sObj} is a {@code Short} object and jtulach@258: * {@code sObj.shortValue() == s}. jtulach@258: * jtulach@258: * @param obj the object whose field should be modified jtulach@258: * @param s the new value for the field of {@code obj} jtulach@258: * being modified jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is either inaccessible or final. jtulach@258: * @exception IllegalArgumentException if the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field (or a subclass or implementor thereof), jtulach@258: * or if an unwrapping conversion fails. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#set jtulach@258: */ jtulach@258: public void setShort(Object obj, short s) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: getFieldAccessor(obj).setShort(obj, s); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Sets the value of a field as an {@code int} on the specified object. jtulach@258: * This method is equivalent to jtulach@258: * {@code set(obj, iObj)}, jtulach@258: * where {@code iObj} is a {@code Integer} object and jtulach@258: * {@code iObj.intValue() == i}. jtulach@258: * jtulach@258: * @param obj the object whose field should be modified jtulach@258: * @param i the new value for the field of {@code obj} jtulach@258: * being modified jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is either inaccessible or final. jtulach@258: * @exception IllegalArgumentException if the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field (or a subclass or implementor thereof), jtulach@258: * or if an unwrapping conversion fails. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#set jtulach@258: */ jtulach@258: public void setInt(Object obj, int i) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: getFieldAccessor(obj).setInt(obj, i); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Sets the value of a field as a {@code long} on the specified object. jtulach@258: * This method is equivalent to jtulach@258: * {@code set(obj, lObj)}, jtulach@258: * where {@code lObj} is a {@code Long} object and jtulach@258: * {@code lObj.longValue() == l}. jtulach@258: * jtulach@258: * @param obj the object whose field should be modified jtulach@258: * @param l the new value for the field of {@code obj} jtulach@258: * being modified jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is either inaccessible or final. jtulach@258: * @exception IllegalArgumentException if the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field (or a subclass or implementor thereof), jtulach@258: * or if an unwrapping conversion fails. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#set jtulach@258: */ jtulach@258: public void setLong(Object obj, long l) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: getFieldAccessor(obj).setLong(obj, l); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Sets the value of a field as a {@code float} on the specified object. jtulach@258: * This method is equivalent to jtulach@258: * {@code set(obj, fObj)}, jtulach@258: * where {@code fObj} is a {@code Float} object and jtulach@258: * {@code fObj.floatValue() == f}. jtulach@258: * jtulach@258: * @param obj the object whose field should be modified jtulach@258: * @param f the new value for the field of {@code obj} jtulach@258: * being modified jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is either inaccessible or final. jtulach@258: * @exception IllegalArgumentException if the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field (or a subclass or implementor thereof), jtulach@258: * or if an unwrapping conversion fails. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#set jtulach@258: */ jtulach@258: public void setFloat(Object obj, float f) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: getFieldAccessor(obj).setFloat(obj, f); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * Sets the value of a field as a {@code double} on the specified object. jtulach@258: * This method is equivalent to jtulach@258: * {@code set(obj, dObj)}, jtulach@258: * where {@code dObj} is a {@code Double} object and jtulach@258: * {@code dObj.doubleValue() == d}. jtulach@258: * jtulach@258: * @param obj the object whose field should be modified jtulach@258: * @param d the new value for the field of {@code obj} jtulach@258: * being modified jtulach@258: * jtulach@258: * @exception IllegalAccessException if this {@code Field} object jtulach@258: * is enforcing Java language access control and the underlying jtulach@258: * field is either inaccessible or final. jtulach@258: * @exception IllegalArgumentException if the specified object is not an jtulach@258: * instance of the class or interface declaring the underlying jtulach@258: * field (or a subclass or implementor thereof), jtulach@258: * or if an unwrapping conversion fails. jtulach@258: * @exception NullPointerException if the specified object is null jtulach@258: * and the field is an instance field. jtulach@258: * @exception ExceptionInInitializerError if the initialization provoked jtulach@258: * by this method fails. jtulach@258: * @see Field#set jtulach@258: */ jtulach@258: public void setDouble(Object obj, double d) jtulach@258: throws IllegalArgumentException, IllegalAccessException jtulach@258: { jtulach@258: getFieldAccessor(obj).setDouble(obj, d); jtulach@258: } jtulach@258: jtulach@258: // Convenience routine which performs security checks jtulach@258: private FieldAccessor getFieldAccessor(Object obj) jtulach@258: throws IllegalAccessException jtulach@258: { jtulach@258: doSecurityCheck(obj); jtulach@258: boolean ov = override; jtulach@258: FieldAccessor a = (ov)? overrideFieldAccessor : fieldAccessor; jtulach@258: return (a != null)? a : acquireFieldAccessor(ov); jtulach@258: } jtulach@258: jtulach@258: // NOTE that there is no synchronization used here. It is correct jtulach@258: // (though not efficient) to generate more than one FieldAccessor jtulach@258: // for a given Field. However, avoiding synchronization will jtulach@258: // probably make the implementation more scalable. jtulach@258: private FieldAccessor acquireFieldAccessor(boolean overrideFinalCheck) { jtulach@258: // First check to see if one has been created yet, and take it jtulach@258: // if so jtulach@258: FieldAccessor tmp = null; jtulach@258: if (root != null) tmp = root.getFieldAccessor(overrideFinalCheck); jtulach@258: if (tmp != null) { jtulach@258: if (overrideFinalCheck) jtulach@258: overrideFieldAccessor = tmp; jtulach@258: else jtulach@258: fieldAccessor = tmp; jtulach@258: } else { jtulach@258: // Otherwise fabricate one and propagate it up to the root jtulach@258: tmp = reflectionFactory.newFieldAccessor(this, overrideFinalCheck); jtulach@258: setFieldAccessor(tmp, overrideFinalCheck); jtulach@258: } jtulach@258: jtulach@258: return tmp; jtulach@258: } jtulach@258: jtulach@258: // Returns FieldAccessor for this Field object, not looking up jtulach@258: // the chain to the root jtulach@258: private FieldAccessor getFieldAccessor(boolean overrideFinalCheck) { jtulach@258: return (overrideFinalCheck)? overrideFieldAccessor : fieldAccessor; jtulach@258: } jtulach@258: jtulach@258: // Sets the FieldAccessor for this Field object and jtulach@258: // (recursively) its root jtulach@258: private void setFieldAccessor(FieldAccessor accessor, boolean overrideFinalCheck) { jtulach@258: if (overrideFinalCheck) jtulach@258: overrideFieldAccessor = accessor; jtulach@258: else jtulach@258: fieldAccessor = accessor; jtulach@258: // Propagate up jtulach@258: if (root != null) { jtulach@258: root.setFieldAccessor(accessor, overrideFinalCheck); jtulach@258: } jtulach@258: } jtulach@258: jtulach@258: // NOTE: be very careful if you change the stack depth of this jtulach@258: // routine. The depth of the "getCallerClass" call is hardwired so jtulach@258: // that the compiler can have an easier time if this gets inlined. jtulach@258: private void doSecurityCheck(Object obj) throws IllegalAccessException { jtulach@258: if (!override) { jtulach@258: if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { jtulach@258: Class caller = Reflection.getCallerClass(4); jtulach@258: jtulach@258: checkAccess(caller, clazz, obj, modifiers); jtulach@258: } jtulach@258: } jtulach@258: } jtulach@258: jtulach@258: /* jtulach@258: * Utility routine to paper over array type names jtulach@258: */ jtulach@258: static String getTypeName(Class type) { jtulach@258: if (type.isArray()) { jtulach@258: try { jtulach@258: Class cl = type; jtulach@258: int dimensions = 0; jtulach@258: while (cl.isArray()) { jtulach@258: dimensions++; jtulach@258: cl = cl.getComponentType(); jtulach@258: } jtulach@258: StringBuffer sb = new StringBuffer(); jtulach@258: sb.append(cl.getName()); jtulach@258: for (int i = 0; i < dimensions; i++) { jtulach@258: sb.append("[]"); jtulach@258: } jtulach@258: return sb.toString(); jtulach@258: } catch (Throwable e) { /*FALLTHRU*/ } jtulach@258: } jtulach@258: return type.getName(); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * @throws NullPointerException {@inheritDoc} jtulach@258: * @since 1.5 jtulach@258: */ jtulach@258: public T getAnnotation(Class annotationClass) { jtulach@258: if (annotationClass == null) jtulach@258: throw new NullPointerException(); jtulach@258: jtulach@258: return (T) declaredAnnotations().get(annotationClass); jtulach@258: } jtulach@258: jtulach@258: /** jtulach@258: * @since 1.5 jtulach@258: */ jtulach@258: public Annotation[] getDeclaredAnnotations() { jtulach@258: return AnnotationParser.toArray(declaredAnnotations()); jtulach@258: } jtulach@258: jtulach@258: private transient Map, Annotation> declaredAnnotations; jtulach@258: jtulach@258: private synchronized Map, Annotation> declaredAnnotations() { jtulach@258: if (declaredAnnotations == null) { jtulach@258: declaredAnnotations = AnnotationParser.parseAnnotations( jtulach@258: annotations, sun.misc.SharedSecrets.getJavaLangAccess(). jtulach@258: getConstantPool(getDeclaringClass()), jtulach@258: getDeclaringClass()); jtulach@258: } jtulach@258: return declaredAnnotations; jtulach@258: } jtulach@258: }