emul/mini/src/main/java/java/lang/reflect/Field.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 26 Jan 2013 08:47:05 +0100
changeset 592 5e13b1ac2886
parent 260 1d03cb35fbda
permissions -rw-r--r--
In order to support fields of the same name in subclasses we are now prefixing them with name of the class that defines them. To provide convenient way to access them from generated bytecode and also directly from JavaScript, there is a getter/setter function for each field. It starts with _ followed by the field name. If called with a parameter, it sets the field, with a parameter it just returns it.
     1 /*
     2  * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.lang.reflect;
    27 
    28 import java.lang.annotation.Annotation;
    29 
    30 
    31 /**
    32  * A {@code Field} provides information about, and dynamic access to, a
    33  * single field of a class or an interface.  The reflected field may
    34  * be a class (static) field or an instance field.
    35  *
    36  * <p>A {@code Field} permits widening conversions to occur during a get or
    37  * set access operation, but throws an {@code IllegalArgumentException} if a
    38  * narrowing conversion would occur.
    39  *
    40  * @see Member
    41  * @see java.lang.Class
    42  * @see java.lang.Class#getFields()
    43  * @see java.lang.Class#getField(String)
    44  * @see java.lang.Class#getDeclaredFields()
    45  * @see java.lang.Class#getDeclaredField(String)
    46  *
    47  * @author Kenneth Russell
    48  * @author Nakul Saraiya
    49  */
    50 public final
    51 class Field extends AccessibleObject implements Member {
    52 
    53     private Class<?>            clazz;
    54     private int                 slot;
    55     // This is guaranteed to be interned by the VM in the 1.4
    56     // reflection implementation
    57     private String              name;
    58     private Class<?>            type;
    59     private int                 modifiers;
    60     // Generics and annotations support
    61     private transient String    signature;
    62     private byte[]              annotations;
    63     // For sharing of FieldAccessors. This branching structure is
    64     // currently only two levels deep (i.e., one root Field and
    65     // potentially many Field objects pointing to it.)
    66     private Field               root;
    67 
    68     // Generics infrastructure
    69 
    70     private String getGenericSignature() {return signature;}
    71 
    72 
    73     /**
    74      * Package-private constructor used by ReflectAccess to enable
    75      * instantiation of these objects in Java code from the java.lang
    76      * package via sun.reflect.LangReflectAccess.
    77      */
    78     Field(Class<?> declaringClass,
    79           String name,
    80           Class<?> type,
    81           int modifiers,
    82           int slot,
    83           String signature,
    84           byte[] annotations)
    85     {
    86         this.clazz = declaringClass;
    87         this.name = name;
    88         this.type = type;
    89         this.modifiers = modifiers;
    90         this.slot = slot;
    91         this.signature = signature;
    92         this.annotations = annotations;
    93     }
    94 
    95     /**
    96      * Package-private routine (exposed to java.lang.Class via
    97      * ReflectAccess) which returns a copy of this Field. The copy's
    98      * "root" field points to this Field.
    99      */
   100     Field copy() {
   101         // This routine enables sharing of FieldAccessor objects
   102         // among Field objects which refer to the same underlying
   103         // method in the VM. (All of this contortion is only necessary
   104         // because of the "accessibility" bit in AccessibleObject,
   105         // which implicitly requires that new java.lang.reflect
   106         // objects be fabricated for each reflective call on Class
   107         // objects.)
   108         Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations);
   109         res.root = this;
   110         return res;
   111     }
   112 
   113     /**
   114      * Returns the {@code Class} object representing the class or interface
   115      * that declares the field represented by this {@code Field} object.
   116      */
   117     public Class<?> getDeclaringClass() {
   118         return clazz;
   119     }
   120 
   121     /**
   122      * Returns the name of the field represented by this {@code Field} object.
   123      */
   124     public String getName() {
   125         return name;
   126     }
   127 
   128     /**
   129      * Returns the Java language modifiers for the field represented
   130      * by this {@code Field} object, as an integer. The {@code Modifier} class should
   131      * be used to decode the modifiers.
   132      *
   133      * @see Modifier
   134      */
   135     public int getModifiers() {
   136         return modifiers;
   137     }
   138 
   139     /**
   140      * Returns {@code true} if this field represents an element of
   141      * an enumerated type; returns {@code false} otherwise.
   142      *
   143      * @return {@code true} if and only if this field represents an element of
   144      * an enumerated type.
   145      * @since 1.5
   146      */
   147     public boolean isEnumConstant() {
   148         return (getModifiers() & Modifier.ENUM) != 0;
   149     }
   150 
   151     /**
   152      * Returns {@code true} if this field is a synthetic
   153      * field; returns {@code false} otherwise.
   154      *
   155      * @return true if and only if this field is a synthetic
   156      * field as defined by the Java Language Specification.
   157      * @since 1.5
   158      */
   159     public boolean isSynthetic() {
   160         return Modifier.isSynthetic(getModifiers());
   161     }
   162 
   163     /**
   164      * Returns a {@code Class} object that identifies the
   165      * declared type for the field represented by this
   166      * {@code Field} object.
   167      *
   168      * @return a {@code Class} object identifying the declared
   169      * type of the field represented by this object
   170      */
   171     public Class<?> getType() {
   172         return type;
   173     }
   174 
   175     /**
   176      * Returns a {@code Type} object that represents the declared type for
   177      * the field represented by this {@code Field} object.
   178      *
   179      * <p>If the {@code Type} is a parameterized type, the
   180      * {@code Type} object returned must accurately reflect the
   181      * actual type parameters used in the source code.
   182      *
   183      * <p>If the type of the underlying field is a type variable or a
   184      * parameterized type, it is created. Otherwise, it is resolved.
   185      *
   186      * @return a {@code Type} object that represents the declared type for
   187      *     the field represented by this {@code Field} object
   188      * @throws GenericSignatureFormatError if the generic field
   189      *     signature does not conform to the format specified in
   190      *     <cite>The Java&trade; Virtual Machine Specification</cite>
   191      * @throws TypeNotPresentException if the generic type
   192      *     signature of the underlying field refers to a non-existent
   193      *     type declaration
   194      * @throws MalformedParameterizedTypeException if the generic
   195      *     signature of the underlying field refers to a parameterized type
   196      *     that cannot be instantiated for any reason
   197      * @since 1.5
   198      */
   199     public Type getGenericType() {
   200         throw new UnsupportedOperationException();
   201     }
   202 
   203 
   204     /**
   205      * Compares this {@code Field} against the specified object.  Returns
   206      * true if the objects are the same.  Two {@code Field} objects are the same if
   207      * they were declared by the same class and have the same name
   208      * and type.
   209      */
   210     public boolean equals(Object obj) {
   211         if (obj != null && obj instanceof Field) {
   212             Field other = (Field)obj;
   213             return (getDeclaringClass() == other.getDeclaringClass())
   214                 && (getName() == other.getName())
   215                 && (getType() == other.getType());
   216         }
   217         return false;
   218     }
   219 
   220     /**
   221      * Returns a hashcode for this {@code Field}.  This is computed as the
   222      * exclusive-or of the hashcodes for the underlying field's
   223      * declaring class name and its name.
   224      */
   225     public int hashCode() {
   226         return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
   227     }
   228 
   229     /**
   230      * Returns a string describing this {@code Field}.  The format is
   231      * the access modifiers for the field, if any, followed
   232      * by the field type, followed by a space, followed by
   233      * the fully-qualified name of the class declaring the field,
   234      * followed by a period, followed by the name of the field.
   235      * For example:
   236      * <pre>
   237      *    public static final int java.lang.Thread.MIN_PRIORITY
   238      *    private int java.io.FileDescriptor.fd
   239      * </pre>
   240      *
   241      * <p>The modifiers are placed in canonical order as specified by
   242      * "The Java Language Specification".  This is {@code public},
   243      * {@code protected} or {@code private} first, and then other
   244      * modifiers in the following order: {@code static}, {@code final},
   245      * {@code transient}, {@code volatile}.
   246      */
   247     public String toString() {
   248         int mod = getModifiers();
   249         return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
   250             + getTypeName(getType()) + " "
   251             + getTypeName(getDeclaringClass()) + "."
   252             + getName());
   253     }
   254 
   255     /**
   256      * Returns a string describing this {@code Field}, including
   257      * its generic type.  The format is the access modifiers for the
   258      * field, if any, followed by the generic field type, followed by
   259      * a space, followed by the fully-qualified name of the class
   260      * declaring the field, followed by a period, followed by the name
   261      * of the field.
   262      *
   263      * <p>The modifiers are placed in canonical order as specified by
   264      * "The Java Language Specification".  This is {@code public},
   265      * {@code protected} or {@code private} first, and then other
   266      * modifiers in the following order: {@code static}, {@code final},
   267      * {@code transient}, {@code volatile}.
   268      *
   269      * @return a string describing this {@code Field}, including
   270      * its generic type
   271      *
   272      * @since 1.5
   273      */
   274     public String toGenericString() {
   275         int mod = getModifiers();
   276         Type fieldType = getGenericType();
   277         return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
   278             +  ((fieldType instanceof Class) ?
   279                 getTypeName((Class)fieldType): fieldType.toString())+ " "
   280             + getTypeName(getDeclaringClass()) + "."
   281             + getName());
   282     }
   283 
   284     /**
   285      * Returns the value of the field represented by this {@code Field}, on
   286      * the specified object. The value is automatically wrapped in an
   287      * object if it has a primitive type.
   288      *
   289      * <p>The underlying field's value is obtained as follows:
   290      *
   291      * <p>If the underlying field is a static field, the {@code obj} argument
   292      * is ignored; it may be null.
   293      *
   294      * <p>Otherwise, the underlying field is an instance field.  If the
   295      * specified {@code obj} argument is null, the method throws a
   296      * {@code NullPointerException}. If the specified object is not an
   297      * instance of the class or interface declaring the underlying
   298      * field, the method throws an {@code IllegalArgumentException}.
   299      *
   300      * <p>If this {@code Field} object is enforcing Java language access control, and
   301      * the underlying field is inaccessible, the method throws an
   302      * {@code IllegalAccessException}.
   303      * If the underlying field is static, the class that declared the
   304      * field is initialized if it has not already been initialized.
   305      *
   306      * <p>Otherwise, the value is retrieved from the underlying instance
   307      * or static field.  If the field has a primitive type, the value
   308      * is wrapped in an object before being returned, otherwise it is
   309      * returned as is.
   310      *
   311      * <p>If the field is hidden in the type of {@code obj},
   312      * the field's value is obtained according to the preceding rules.
   313      *
   314      * @param obj object from which the represented field's value is
   315      * to be extracted
   316      * @return the value of the represented field in object
   317      * {@code obj}; primitive values are wrapped in an appropriate
   318      * object before being returned
   319      *
   320      * @exception IllegalAccessException    if this {@code Field} object
   321      *              is enforcing Java language access control and the underlying
   322      *              field is inaccessible.
   323      * @exception IllegalArgumentException  if the specified object is not an
   324      *              instance of the class or interface declaring the underlying
   325      *              field (or a subclass or implementor thereof).
   326      * @exception NullPointerException      if the specified object is null
   327      *              and the field is an instance field.
   328      * @exception ExceptionInInitializerError if the initialization provoked
   329      *              by this method fails.
   330      */
   331     public Object get(Object obj)
   332         throws IllegalArgumentException, IllegalAccessException
   333     {
   334         return getFieldAccessor(obj).get(obj);
   335     }
   336 
   337     /**
   338      * Gets the value of a static or instance {@code boolean} field.
   339      *
   340      * @param obj the object to extract the {@code boolean} value
   341      * from
   342      * @return the value of the {@code boolean} field
   343      *
   344      * @exception IllegalAccessException    if this {@code Field} object
   345      *              is enforcing Java language access control and the underlying
   346      *              field is inaccessible.
   347      * @exception IllegalArgumentException  if the specified object is not
   348      *              an instance of the class or interface declaring the
   349      *              underlying field (or a subclass or implementor
   350      *              thereof), or if the field value cannot be
   351      *              converted to the type {@code boolean} by a
   352      *              widening conversion.
   353      * @exception NullPointerException      if the specified object is null
   354      *              and the field is an instance field.
   355      * @exception ExceptionInInitializerError if the initialization provoked
   356      *              by this method fails.
   357      * @see       Field#get
   358      */
   359     public boolean getBoolean(Object obj)
   360         throws IllegalArgumentException, IllegalAccessException
   361     {
   362         return getFieldAccessor(obj).getBoolean(obj);
   363     }
   364 
   365     /**
   366      * Gets the value of a static or instance {@code byte} field.
   367      *
   368      * @param obj the object to extract the {@code byte} value
   369      * from
   370      * @return the value of the {@code byte} field
   371      *
   372      * @exception IllegalAccessException    if this {@code Field} object
   373      *              is enforcing Java language access control and the underlying
   374      *              field is inaccessible.
   375      * @exception IllegalArgumentException  if the specified object is not
   376      *              an instance of the class or interface declaring the
   377      *              underlying field (or a subclass or implementor
   378      *              thereof), or if the field value cannot be
   379      *              converted to the type {@code byte} by a
   380      *              widening conversion.
   381      * @exception NullPointerException      if the specified object is null
   382      *              and the field is an instance field.
   383      * @exception ExceptionInInitializerError if the initialization provoked
   384      *              by this method fails.
   385      * @see       Field#get
   386      */
   387     public byte getByte(Object obj)
   388         throws IllegalArgumentException, IllegalAccessException
   389     {
   390         return getFieldAccessor(obj).getByte(obj);
   391     }
   392 
   393     /**
   394      * Gets the value of a static or instance field of type
   395      * {@code char} or of another primitive type convertible to
   396      * type {@code char} via a widening conversion.
   397      *
   398      * @param obj the object to extract the {@code char} value
   399      * from
   400      * @return the value of the field converted to type {@code char}
   401      *
   402      * @exception IllegalAccessException    if this {@code Field} object
   403      *              is enforcing Java language access control and the underlying
   404      *              field is inaccessible.
   405      * @exception IllegalArgumentException  if the specified object is not
   406      *              an instance of the class or interface declaring the
   407      *              underlying field (or a subclass or implementor
   408      *              thereof), or if the field value cannot be
   409      *              converted to the type {@code char} by a
   410      *              widening conversion.
   411      * @exception NullPointerException      if the specified object is null
   412      *              and the field is an instance field.
   413      * @exception ExceptionInInitializerError if the initialization provoked
   414      *              by this method fails.
   415      * @see Field#get
   416      */
   417     public char getChar(Object obj)
   418         throws IllegalArgumentException, IllegalAccessException
   419     {
   420         return getFieldAccessor(obj).getChar(obj);
   421     }
   422 
   423     /**
   424      * Gets the value of a static or instance field of type
   425      * {@code short} or of another primitive type convertible to
   426      * type {@code short} via a widening conversion.
   427      *
   428      * @param obj the object to extract the {@code short} value
   429      * from
   430      * @return the value of the field converted to type {@code short}
   431      *
   432      * @exception IllegalAccessException    if this {@code Field} object
   433      *              is enforcing Java language access control and the underlying
   434      *              field is inaccessible.
   435      * @exception IllegalArgumentException  if the specified object is not
   436      *              an instance of the class or interface declaring the
   437      *              underlying field (or a subclass or implementor
   438      *              thereof), or if the field value cannot be
   439      *              converted to the type {@code short} by a
   440      *              widening conversion.
   441      * @exception NullPointerException      if the specified object is null
   442      *              and the field is an instance field.
   443      * @exception ExceptionInInitializerError if the initialization provoked
   444      *              by this method fails.
   445      * @see       Field#get
   446      */
   447     public short getShort(Object obj)
   448         throws IllegalArgumentException, IllegalAccessException
   449     {
   450         return getFieldAccessor(obj).getShort(obj);
   451     }
   452 
   453     /**
   454      * Gets the value of a static or instance field of type
   455      * {@code int} or of another primitive type convertible to
   456      * type {@code int} via a widening conversion.
   457      *
   458      * @param obj the object to extract the {@code int} value
   459      * from
   460      * @return the value of the field converted to type {@code int}
   461      *
   462      * @exception IllegalAccessException    if this {@code Field} object
   463      *              is enforcing Java language access control and the underlying
   464      *              field is inaccessible.
   465      * @exception IllegalArgumentException  if the specified object is not
   466      *              an instance of the class or interface declaring the
   467      *              underlying field (or a subclass or implementor
   468      *              thereof), or if the field value cannot be
   469      *              converted to the type {@code int} by a
   470      *              widening conversion.
   471      * @exception NullPointerException      if the specified object is null
   472      *              and the field is an instance field.
   473      * @exception ExceptionInInitializerError if the initialization provoked
   474      *              by this method fails.
   475      * @see       Field#get
   476      */
   477     public int getInt(Object obj)
   478         throws IllegalArgumentException, IllegalAccessException
   479     {
   480         return getFieldAccessor(obj).getInt(obj);
   481     }
   482 
   483     /**
   484      * Gets the value of a static or instance field of type
   485      * {@code long} or of another primitive type convertible to
   486      * type {@code long} via a widening conversion.
   487      *
   488      * @param obj the object to extract the {@code long} value
   489      * from
   490      * @return the value of the field converted to type {@code long}
   491      *
   492      * @exception IllegalAccessException    if this {@code Field} object
   493      *              is enforcing Java language access control and the underlying
   494      *              field is inaccessible.
   495      * @exception IllegalArgumentException  if the specified object is not
   496      *              an instance of the class or interface declaring the
   497      *              underlying field (or a subclass or implementor
   498      *              thereof), or if the field value cannot be
   499      *              converted to the type {@code long} by a
   500      *              widening conversion.
   501      * @exception NullPointerException      if the specified object is null
   502      *              and the field is an instance field.
   503      * @exception ExceptionInInitializerError if the initialization provoked
   504      *              by this method fails.
   505      * @see       Field#get
   506      */
   507     public long getLong(Object obj)
   508         throws IllegalArgumentException, IllegalAccessException
   509     {
   510         return getFieldAccessor(obj).getLong(obj);
   511     }
   512 
   513     /**
   514      * Gets the value of a static or instance field of type
   515      * {@code float} or of another primitive type convertible to
   516      * type {@code float} via a widening conversion.
   517      *
   518      * @param obj the object to extract the {@code float} value
   519      * from
   520      * @return the value of the field converted to type {@code float}
   521      *
   522      * @exception IllegalAccessException    if this {@code Field} object
   523      *              is enforcing Java language access control and the underlying
   524      *              field is inaccessible.
   525      * @exception IllegalArgumentException  if the specified object is not
   526      *              an instance of the class or interface declaring the
   527      *              underlying field (or a subclass or implementor
   528      *              thereof), or if the field value cannot be
   529      *              converted to the type {@code float} by a
   530      *              widening conversion.
   531      * @exception NullPointerException      if the specified object is null
   532      *              and the field is an instance field.
   533      * @exception ExceptionInInitializerError if the initialization provoked
   534      *              by this method fails.
   535      * @see Field#get
   536      */
   537     public float getFloat(Object obj)
   538         throws IllegalArgumentException, IllegalAccessException
   539     {
   540         return getFieldAccessor(obj).getFloat(obj);
   541     }
   542 
   543     /**
   544      * Gets the value of a static or instance field of type
   545      * {@code double} or of another primitive type convertible to
   546      * type {@code double} via a widening conversion.
   547      *
   548      * @param obj the object to extract the {@code double} value
   549      * from
   550      * @return the value of the field converted to type {@code double}
   551      *
   552      * @exception IllegalAccessException    if this {@code Field} object
   553      *              is enforcing Java language access control and the underlying
   554      *              field is inaccessible.
   555      * @exception IllegalArgumentException  if the specified object is not
   556      *              an instance of the class or interface declaring the
   557      *              underlying field (or a subclass or implementor
   558      *              thereof), or if the field value cannot be
   559      *              converted to the type {@code double} by a
   560      *              widening conversion.
   561      * @exception NullPointerException      if the specified object is null
   562      *              and the field is an instance field.
   563      * @exception ExceptionInInitializerError if the initialization provoked
   564      *              by this method fails.
   565      * @see       Field#get
   566      */
   567     public double getDouble(Object obj)
   568         throws IllegalArgumentException, IllegalAccessException
   569     {
   570         return getFieldAccessor(obj).getDouble(obj);
   571     }
   572 
   573     /**
   574      * Sets the field represented by this {@code Field} object on the
   575      * specified object argument to the specified new value. The new
   576      * value is automatically unwrapped if the underlying field has a
   577      * primitive type.
   578      *
   579      * <p>The operation proceeds as follows:
   580      *
   581      * <p>If the underlying field is static, the {@code obj} argument is
   582      * ignored; it may be null.
   583      *
   584      * <p>Otherwise the underlying field is an instance field.  If the
   585      * specified object argument is null, the method throws a
   586      * {@code NullPointerException}.  If the specified object argument is not
   587      * an instance of the class or interface declaring the underlying
   588      * field, the method throws an {@code IllegalArgumentException}.
   589      *
   590      * <p>If this {@code Field} object is enforcing Java language access control, and
   591      * the underlying field is inaccessible, the method throws an
   592      * {@code IllegalAccessException}.
   593      *
   594      * <p>If the underlying field is final, the method throws an
   595      * {@code IllegalAccessException} unless {@code setAccessible(true)}
   596      * has succeeded for this {@code Field} object
   597      * and the field is non-static. Setting a final field in this way
   598      * is meaningful only during deserialization or reconstruction of
   599      * instances of classes with blank final fields, before they are
   600      * made available for access by other parts of a program. Use in
   601      * any other context may have unpredictable effects, including cases
   602      * in which other parts of a program continue to use the original
   603      * value of this field.
   604      *
   605      * <p>If the underlying field is of a primitive type, an unwrapping
   606      * conversion is attempted to convert the new value to a value of
   607      * a primitive type.  If this attempt fails, the method throws an
   608      * {@code IllegalArgumentException}.
   609      *
   610      * <p>If, after possible unwrapping, the new value cannot be
   611      * converted to the type of the underlying field by an identity or
   612      * widening conversion, the method throws an
   613      * {@code IllegalArgumentException}.
   614      *
   615      * <p>If the underlying field is static, the class that declared the
   616      * field is initialized if it has not already been initialized.
   617      *
   618      * <p>The field is set to the possibly unwrapped and widened new value.
   619      *
   620      * <p>If the field is hidden in the type of {@code obj},
   621      * the field's value is set according to the preceding rules.
   622      *
   623      * @param obj the object whose field should be modified
   624      * @param value the new value for the field of {@code obj}
   625      * being modified
   626      *
   627      * @exception IllegalAccessException    if this {@code Field} object
   628      *              is enforcing Java language access control and the underlying
   629      *              field is either inaccessible or final.
   630      * @exception IllegalArgumentException  if the specified object is not an
   631      *              instance of the class or interface declaring the underlying
   632      *              field (or a subclass or implementor thereof),
   633      *              or if an unwrapping conversion fails.
   634      * @exception NullPointerException      if the specified object is null
   635      *              and the field is an instance field.
   636      * @exception ExceptionInInitializerError if the initialization provoked
   637      *              by this method fails.
   638      */
   639     public void set(Object obj, Object value)
   640         throws IllegalArgumentException, IllegalAccessException
   641     {
   642         getFieldAccessor(obj).set(obj, value);
   643     }
   644 
   645     /**
   646      * Sets the value of a field as a {@code boolean} on the specified object.
   647      * This method is equivalent to
   648      * {@code set(obj, zObj)},
   649      * where {@code zObj} is a {@code Boolean} object and
   650      * {@code zObj.booleanValue() == z}.
   651      *
   652      * @param obj the object whose field should be modified
   653      * @param z   the new value for the field of {@code obj}
   654      * being modified
   655      *
   656      * @exception IllegalAccessException    if this {@code Field} object
   657      *              is enforcing Java language access control and the underlying
   658      *              field is either inaccessible or final.
   659      * @exception IllegalArgumentException  if the specified object is not an
   660      *              instance of the class or interface declaring the underlying
   661      *              field (or a subclass or implementor thereof),
   662      *              or if an unwrapping conversion fails.
   663      * @exception NullPointerException      if the specified object is null
   664      *              and the field is an instance field.
   665      * @exception ExceptionInInitializerError if the initialization provoked
   666      *              by this method fails.
   667      * @see       Field#set
   668      */
   669     public void setBoolean(Object obj, boolean z)
   670         throws IllegalArgumentException, IllegalAccessException
   671     {
   672         getFieldAccessor(obj).setBoolean(obj, z);
   673     }
   674 
   675     /**
   676      * Sets the value of a field as a {@code byte} on the specified object.
   677      * This method is equivalent to
   678      * {@code set(obj, bObj)},
   679      * where {@code bObj} is a {@code Byte} object and
   680      * {@code bObj.byteValue() == b}.
   681      *
   682      * @param obj the object whose field should be modified
   683      * @param b   the new value for the field of {@code obj}
   684      * being modified
   685      *
   686      * @exception IllegalAccessException    if this {@code Field} object
   687      *              is enforcing Java language access control and the underlying
   688      *              field is either inaccessible or final.
   689      * @exception IllegalArgumentException  if the specified object is not an
   690      *              instance of the class or interface declaring the underlying
   691      *              field (or a subclass or implementor thereof),
   692      *              or if an unwrapping conversion fails.
   693      * @exception NullPointerException      if the specified object is null
   694      *              and the field is an instance field.
   695      * @exception ExceptionInInitializerError if the initialization provoked
   696      *              by this method fails.
   697      * @see       Field#set
   698      */
   699     public void setByte(Object obj, byte b)
   700         throws IllegalArgumentException, IllegalAccessException
   701     {
   702         getFieldAccessor(obj).setByte(obj, b);
   703     }
   704 
   705     /**
   706      * Sets the value of a field as a {@code char} on the specified object.
   707      * This method is equivalent to
   708      * {@code set(obj, cObj)},
   709      * where {@code cObj} is a {@code Character} object and
   710      * {@code cObj.charValue() == c}.
   711      *
   712      * @param obj the object whose field should be modified
   713      * @param c   the new value for the field of {@code obj}
   714      * being modified
   715      *
   716      * @exception IllegalAccessException    if this {@code Field} object
   717      *              is enforcing Java language access control and the underlying
   718      *              field is either inaccessible or final.
   719      * @exception IllegalArgumentException  if the specified object is not an
   720      *              instance of the class or interface declaring the underlying
   721      *              field (or a subclass or implementor thereof),
   722      *              or if an unwrapping conversion fails.
   723      * @exception NullPointerException      if the specified object is null
   724      *              and the field is an instance field.
   725      * @exception ExceptionInInitializerError if the initialization provoked
   726      *              by this method fails.
   727      * @see       Field#set
   728      */
   729     public void setChar(Object obj, char c)
   730         throws IllegalArgumentException, IllegalAccessException
   731     {
   732         getFieldAccessor(obj).setChar(obj, c);
   733     }
   734 
   735     /**
   736      * Sets the value of a field as a {@code short} on the specified object.
   737      * This method is equivalent to
   738      * {@code set(obj, sObj)},
   739      * where {@code sObj} is a {@code Short} object and
   740      * {@code sObj.shortValue() == s}.
   741      *
   742      * @param obj the object whose field should be modified
   743      * @param s   the new value for the field of {@code obj}
   744      * being modified
   745      *
   746      * @exception IllegalAccessException    if this {@code Field} object
   747      *              is enforcing Java language access control and the underlying
   748      *              field is either inaccessible or final.
   749      * @exception IllegalArgumentException  if the specified object is not an
   750      *              instance of the class or interface declaring the underlying
   751      *              field (or a subclass or implementor thereof),
   752      *              or if an unwrapping conversion fails.
   753      * @exception NullPointerException      if the specified object is null
   754      *              and the field is an instance field.
   755      * @exception ExceptionInInitializerError if the initialization provoked
   756      *              by this method fails.
   757      * @see       Field#set
   758      */
   759     public void setShort(Object obj, short s)
   760         throws IllegalArgumentException, IllegalAccessException
   761     {
   762         getFieldAccessor(obj).setShort(obj, s);
   763     }
   764 
   765     /**
   766      * Sets the value of a field as an {@code int} on the specified object.
   767      * This method is equivalent to
   768      * {@code set(obj, iObj)},
   769      * where {@code iObj} is a {@code Integer} object and
   770      * {@code iObj.intValue() == i}.
   771      *
   772      * @param obj the object whose field should be modified
   773      * @param i   the new value for the field of {@code obj}
   774      * being modified
   775      *
   776      * @exception IllegalAccessException    if this {@code Field} object
   777      *              is enforcing Java language access control and the underlying
   778      *              field is either inaccessible or final.
   779      * @exception IllegalArgumentException  if the specified object is not an
   780      *              instance of the class or interface declaring the underlying
   781      *              field (or a subclass or implementor thereof),
   782      *              or if an unwrapping conversion fails.
   783      * @exception NullPointerException      if the specified object is null
   784      *              and the field is an instance field.
   785      * @exception ExceptionInInitializerError if the initialization provoked
   786      *              by this method fails.
   787      * @see       Field#set
   788      */
   789     public void setInt(Object obj, int i)
   790         throws IllegalArgumentException, IllegalAccessException
   791     {
   792         getFieldAccessor(obj).setInt(obj, i);
   793     }
   794 
   795     /**
   796      * Sets the value of a field as a {@code long} on the specified object.
   797      * This method is equivalent to
   798      * {@code set(obj, lObj)},
   799      * where {@code lObj} is a {@code Long} object and
   800      * {@code lObj.longValue() == l}.
   801      *
   802      * @param obj the object whose field should be modified
   803      * @param l   the new value for the field of {@code obj}
   804      * being modified
   805      *
   806      * @exception IllegalAccessException    if this {@code Field} object
   807      *              is enforcing Java language access control and the underlying
   808      *              field is either inaccessible or final.
   809      * @exception IllegalArgumentException  if the specified object is not an
   810      *              instance of the class or interface declaring the underlying
   811      *              field (or a subclass or implementor thereof),
   812      *              or if an unwrapping conversion fails.
   813      * @exception NullPointerException      if the specified object is null
   814      *              and the field is an instance field.
   815      * @exception ExceptionInInitializerError if the initialization provoked
   816      *              by this method fails.
   817      * @see       Field#set
   818      */
   819     public void setLong(Object obj, long l)
   820         throws IllegalArgumentException, IllegalAccessException
   821     {
   822         getFieldAccessor(obj).setLong(obj, l);
   823     }
   824 
   825     /**
   826      * Sets the value of a field as a {@code float} on the specified object.
   827      * This method is equivalent to
   828      * {@code set(obj, fObj)},
   829      * where {@code fObj} is a {@code Float} object and
   830      * {@code fObj.floatValue() == f}.
   831      *
   832      * @param obj the object whose field should be modified
   833      * @param f   the new value for the field of {@code obj}
   834      * being modified
   835      *
   836      * @exception IllegalAccessException    if this {@code Field} object
   837      *              is enforcing Java language access control and the underlying
   838      *              field is either inaccessible or final.
   839      * @exception IllegalArgumentException  if the specified object is not an
   840      *              instance of the class or interface declaring the underlying
   841      *              field (or a subclass or implementor thereof),
   842      *              or if an unwrapping conversion fails.
   843      * @exception NullPointerException      if the specified object is null
   844      *              and the field is an instance field.
   845      * @exception ExceptionInInitializerError if the initialization provoked
   846      *              by this method fails.
   847      * @see       Field#set
   848      */
   849     public void setFloat(Object obj, float f)
   850         throws IllegalArgumentException, IllegalAccessException
   851     {
   852         getFieldAccessor(obj).setFloat(obj, f);
   853     }
   854 
   855     /**
   856      * Sets the value of a field as a {@code double} on the specified object.
   857      * This method is equivalent to
   858      * {@code set(obj, dObj)},
   859      * where {@code dObj} is a {@code Double} object and
   860      * {@code dObj.doubleValue() == d}.
   861      *
   862      * @param obj the object whose field should be modified
   863      * @param d   the new value for the field of {@code obj}
   864      * being modified
   865      *
   866      * @exception IllegalAccessException    if this {@code Field} object
   867      *              is enforcing Java language access control and the underlying
   868      *              field is either inaccessible or final.
   869      * @exception IllegalArgumentException  if the specified object is not an
   870      *              instance of the class or interface declaring the underlying
   871      *              field (or a subclass or implementor thereof),
   872      *              or if an unwrapping conversion fails.
   873      * @exception NullPointerException      if the specified object is null
   874      *              and the field is an instance field.
   875      * @exception ExceptionInInitializerError if the initialization provoked
   876      *              by this method fails.
   877      * @see       Field#set
   878      */
   879     public void setDouble(Object obj, double d)
   880         throws IllegalArgumentException, IllegalAccessException
   881     {
   882         getFieldAccessor(obj).setDouble(obj, d);
   883     }
   884 
   885     // Convenience routine which performs security checks
   886     private FieldAccessor getFieldAccessor(Object obj)
   887         throws IllegalAccessException
   888     {
   889         throw new SecurityException();
   890     }
   891     
   892     private static abstract class FieldAccessor {
   893         abstract void setShort(Object obj, short s);
   894         abstract void setInt(Object obj, int i);
   895         abstract void setChar(Object obj, char c);
   896         abstract void setByte(Object obj, byte b);
   897         abstract void setBoolean(Object obj, boolean z);
   898         abstract void set(Object obj, Object value);
   899         abstract double getDouble(Object obj);
   900         abstract void setLong(Object obj, long l);
   901         abstract void setFloat(Object obj, float f);
   902         abstract void setDouble(Object obj, double d);
   903         abstract long getLong(Object obj);
   904         abstract int getInt(Object obj);
   905         abstract short getShort(Object obj);
   906         abstract char getChar(Object obj);
   907         abstract byte getByte(Object obj);
   908         abstract boolean getBoolean(Object obj);
   909         abstract Object get(Object obj);
   910         abstract float getFloat(Object obj);
   911     }
   912 
   913     /*
   914      * Utility routine to paper over array type names
   915      */
   916     static String getTypeName(Class<?> type) {
   917         if (type.isArray()) {
   918             try {
   919                 Class<?> cl = type;
   920                 int dimensions = 0;
   921                 while (cl.isArray()) {
   922                     dimensions++;
   923                     cl = cl.getComponentType();
   924                 }
   925                 StringBuffer sb = new StringBuffer();
   926                 sb.append(cl.getName());
   927                 for (int i = 0; i < dimensions; i++) {
   928                     sb.append("[]");
   929                 }
   930                 return sb.toString();
   931             } catch (Throwable e) { /*FALLTHRU*/ }
   932         }
   933         return type.getName();
   934     }
   935 
   936     /**
   937      * @throws NullPointerException {@inheritDoc}
   938      * @since 1.5
   939      */
   940     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
   941         if (annotationClass == null)
   942             throw new NullPointerException();
   943 
   944         throw new UnsupportedOperationException();
   945     }
   946 
   947     /**
   948      * @since 1.5
   949      */
   950     public Annotation[] getDeclaredAnnotations()  {
   951         throw new UnsupportedOperationException();
   952     }
   953 }