Field.java revision fb0ec0e650bf8be35acb0d47da0311a7c446aa33
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17/*
18 * Copyright (C) 2008 The Android Open Source Project
19 *
20 * Licensed under the Apache License, Version 2.0 (the "License");
21 * you may not use this file except in compliance with the License.
22 * You may obtain a copy of the License at
23 *
24 *      http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS,
28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 * See the License for the specific language governing permissions and
30 * limitations under the License.
31 */
32
33package java.lang.reflect;
34
35import java.lang.annotation.Annotation;
36import org.apache.harmony.kernel.vm.StringUtils;
37import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
38import org.apache.harmony.luni.lang.reflect.Types;
39
40/**
41 * This class represents a field. Information about the field can be accessed,
42 * and the field's value can be accessed dynamically.
43 */
44public final class Field extends AccessibleObject implements Member {
45
46    private Class<?> declaringClass;
47
48    private Class<?> type;
49
50    private Type genericType;
51
52    private volatile boolean genericTypesAreInitialized = false;
53
54    private String name;
55
56    private int slot;
57
58    private static final int TYPE_BOOLEAN = 1;
59
60    private static final int TYPE_BYTE = 2;
61
62    private static final int TYPE_CHAR = 3;
63
64    private static final int TYPE_SHORT = 4;
65
66    private static final int TYPE_INTEGER = 5;
67
68    private static final int TYPE_FLOAT = 6;
69
70    private static final int TYPE_LONG = 7;
71
72    private static final int TYPE_DOUBLE = 8;
73
74    /**
75     * Construct a clone of the given instance.
76     *
77     * @param orig non-null; the original instance to clone
78     */
79    /*package*/ Field(Field orig) {
80        this(orig.declaringClass, orig.type, orig.name, orig.slot);
81
82        // Copy the accessible flag.
83        if (orig.flag) {
84            this.flag = true;
85        }
86    }
87
88    private Field(Class<?> declaringClass, Class<?> type, String name, int slot) {
89        this.declaringClass = declaringClass;
90        this.type = type;
91        this.name = name;
92        this.slot = slot;
93    }
94
95    private synchronized void initGenericType() {
96        if (!genericTypesAreInitialized) {
97            String signatureAttribute = getSignatureAttribute();
98            GenericSignatureParser parser = new GenericSignatureParser(
99                    declaringClass.getClassLoader());
100            parser.parseForField(this.declaringClass, signatureAttribute);
101            genericType = parser.fieldType;
102            if (genericType == null) {
103                genericType = getType();
104            }
105            genericTypesAreInitialized = true;
106        }
107    }
108
109    /** {@inheritDoc} */
110    @Override
111    /* package */String getSignatureAttribute() {
112        Object[] annotation = getSignatureAnnotation(declaringClass, slot);
113
114        if (annotation == null) {
115            return null;
116        }
117
118        return StringUtils.combineStrings(annotation);
119    }
120
121    /**
122     * Get the Signature annotation for this field. Returns null if not found.
123     */
124    native private Object[] getSignatureAnnotation(Class declaringClass, int slot);
125
126    /**
127     * Indicates whether or not this field is synthetic.
128     *
129     * @return {@code true} if this field is synthetic, {@code false} otherwise
130     */
131    public boolean isSynthetic() {
132        int flags = getFieldModifiers(declaringClass, slot);
133        return (flags & Modifier.SYNTHETIC) != 0;
134    }
135
136    /**
137     * Returns the string representation of this field, including the field's
138     * generic type.
139     *
140     * @return the string representation of this field
141     */
142    public String toGenericString() {
143        StringBuilder sb = new StringBuilder(80);
144        // append modifiers if any
145        int modifier = getModifiers();
146        if (modifier != 0) {
147            sb.append(Modifier.toString(modifier)).append(' ');
148        }
149        // append generic type
150        appendGenericType(sb, getGenericType());
151        sb.append(' ');
152        // append full field name
153        sb.append(getDeclaringClass().getName()).append('.').append(getName());
154        return sb.toString();
155    }
156
157    /**
158     * Indicates whether or not this field is an enumeration constant.
159     *
160     * @return {@code true} if this field is an enumeration constant, {@code
161     *         false} otherwise
162     */
163    public boolean isEnumConstant() {
164        int flags = getFieldModifiers(declaringClass, slot);
165        return (flags & Modifier.ENUM) != 0;
166    }
167
168    /**
169     * Returns the generic type of this field.
170     *
171     * @return the generic type
172     * @throws GenericSignatureFormatError
173     *             if the generic field signature is invalid
174     * @throws TypeNotPresentException
175     *             if the generic type points to a missing type
176     * @throws MalformedParameterizedTypeException
177     *             if the generic type points to a type that cannot be
178     *             instantiated for some reason
179     */
180    public Type getGenericType() {
181        initGenericType();
182        return Types.getType(genericType);
183    }
184
185    @Override
186    public Annotation[] getDeclaredAnnotations() {
187        return getDeclaredAnnotations(declaringClass, slot);
188    }
189
190    native private Annotation[] getDeclaredAnnotations(Class declaringClass, int slot);
191
192    /**
193     * Indicates whether or not the specified {@code object} is equal to this
194     * field. To be equal, the specified object must be an instance of
195     * {@code Field} with the same declaring class, type and name as this field.
196     *
197     * @param object
198     *            the object to compare
199     * @return {@code true} if the specified object is equal to this method,
200     *         {@code false} otherwise
201     * @see #hashCode
202     */
203    @Override
204    public boolean equals(Object object) {
205        return object instanceof Field && toString().equals(object.toString());
206    }
207
208    /**
209     * Returns the value of the field in the specified object. This reproduces
210     * the effect of {@code object.fieldName}
211     *
212     * <p>If the type of this field is a primitive type, the field value is
213     * automatically boxed.
214     *
215     * <p>If this field is static, the object argument is ignored.
216     * Otherwise, if the object is null, a NullPointerException is thrown. If
217     * the object is not an instance of the declaring class of the method, an
218     * IllegalArgumentException is thrown.
219     *
220     * <p>If this Field object is enforcing access control (see AccessibleObject)
221     * and this field is not accessible from the current context, an
222     * IllegalAccessException is thrown.
223     *
224     * @param object
225     *            the object to access
226     * @return the field value, possibly boxed
227     * @throws NullPointerException
228     *             if the object is {@code null} and the field is non-static
229     * @throws IllegalArgumentException
230     *             if the object is not compatible with the declaring class
231     * @throws IllegalAccessException
232     *             if this field is not accessible
233     */
234    public Object get(Object object) throws IllegalAccessException, IllegalArgumentException {
235        return getField(object, declaringClass, type, slot, flag);
236    }
237
238    /**
239     * Returns the value of the field in the specified object as a {@code
240     * boolean}. This reproduces the effect of {@code object.fieldName}
241     * <p>
242     * If this field is static, the object argument is ignored.
243     * Otherwise, if the object is {@code null}, a NullPointerException is
244     * thrown. If the object is not an instance of the declaring class of the
245     * method, an IllegalArgumentException is thrown.
246     * <p>
247     * If this Field object is enforcing access control (see AccessibleObject)
248     * and this field is not accessible from the current context, an
249     * IllegalAccessException is thrown.
250     *
251     * @param object
252     *            the object to access
253     * @return the field value
254     * @throws NullPointerException
255     *             if the object is {@code null} and the field is non-static
256     * @throws IllegalArgumentException
257     *             if the object is not compatible with the declaring class
258     * @throws IllegalAccessException
259     *             if this field is not accessible
260     */
261    public boolean getBoolean(Object object) throws IllegalAccessException,
262            IllegalArgumentException {
263        return getZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN);
264    }
265
266    /**
267     * Returns the value of the field in the specified object as a {@code byte}.
268     * This reproduces the effect of {@code object.fieldName}
269     * <p>
270     * If this field is static, the object argument is ignored.
271     * Otherwise, if the object is {@code null}, a NullPointerException is
272     * thrown. If the object is not an instance of the declaring class of the
273     * method, an IllegalArgumentException is thrown.
274     * <p>
275     * If this Field object is enforcing access control (see AccessibleObject)
276     * and this field is not accessible from the current context, an
277     * IllegalAccessException is thrown.
278     *
279     * @param object
280     *            the object to access
281     * @return the field value
282     * @throws NullPointerException
283     *             if the object is {@code null} and the field is non-static
284     * @throws IllegalArgumentException
285     *             if the object is not compatible with the declaring class
286     * @throws IllegalAccessException
287     *             if this field is not accessible
288     */
289    public byte getByte(Object object) throws IllegalAccessException, IllegalArgumentException {
290        return getBField(object, declaringClass, type, slot, flag, TYPE_BYTE);
291    }
292
293    /**
294     * Returns the value of the field in the specified object as a {@code char}.
295     * This reproduces the effect of {@code object.fieldName}
296     * <p>
297     * If this field is static, the object argument is ignored.
298     * Otherwise, if the object is {@code null}, a NullPointerException is
299     * thrown. If the object is not an instance of the declaring class of the
300     * method, an IllegalArgumentException is thrown.
301     * <p>
302     * If this Field object is enforcing access control (see AccessibleObject)
303     * and this field is not accessible from the current context, an
304     * IllegalAccessException is thrown.
305     *
306     * @param object
307     *            the object to access
308     * @return the field value
309     * @throws NullPointerException
310     *             if the object is {@code null} and the field is non-static
311     * @throws IllegalArgumentException
312     *             if the object is not compatible with the declaring class
313     * @throws IllegalAccessException
314     *             if this field is not accessible
315     */
316    public char getChar(Object object) throws IllegalAccessException, IllegalArgumentException {
317        return getCField(object, declaringClass, type, slot, flag, TYPE_CHAR);
318    }
319
320    /**
321     * Returns the class that declares this field.
322     *
323     * @return the declaring class
324     */
325    public Class<?> getDeclaringClass() {
326        return declaringClass;
327    }
328
329    /**
330     * Returns the value of the field in the specified object as a {@code
331     * double}. This reproduces the effect of {@code object.fieldName}
332     * <p>
333     * If this field is static, the object argument is ignored.
334     * Otherwise, if the object is {@code null}, a NullPointerException is
335     * thrown. If the object is not an instance of the declaring class of the
336     * method, an IllegalArgumentException is thrown.
337     * <p>
338     * If this Field object is enforcing access control (see AccessibleObject)
339     * and this field is not accessible from the current context, an
340     * IllegalAccessException is thrown.
341     *
342     * @param object
343     *            the object to access
344     * @return the field value
345     * @throws NullPointerException
346     *             if the object is {@code null} and the field is non-static
347     * @throws IllegalArgumentException
348     *             if the object is not compatible with the declaring class
349     * @throws IllegalAccessException
350     *             if this field is not accessible
351     */
352    public double getDouble(Object object) throws IllegalAccessException, IllegalArgumentException {
353        return getDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE);
354    }
355
356    /**
357     * Returns the value of the field in the specified object as a {@code float}
358     * . This reproduces the effect of {@code object.fieldName}
359     * <p>
360     * If this field is static, the object argument is ignored.
361     * Otherwise, if the object is {@code null}, a NullPointerException is
362     * thrown. If the object is not an instance of the declaring class of the
363     * method, an IllegalArgumentException is thrown.
364     * <p>
365     * If this Field object is enforcing access control (see AccessibleObject)
366     * and this field is not accessible from the current context, an
367     * IllegalAccessException is thrown.
368     *
369     * @param object
370     *            the object to access
371     * @return the field value
372     * @throws NullPointerException
373     *             if the object is {@code null} and the field is non-static
374     * @throws IllegalArgumentException
375     *             if the object is not compatible with the declaring class
376     * @throws IllegalAccessException
377     *             if this field is not accessible
378     */
379    public float getFloat(Object object) throws IllegalAccessException, IllegalArgumentException {
380        return getFField(object, declaringClass, type, slot, flag, TYPE_FLOAT);
381    }
382
383    /**
384     * Returns the value of the field in the specified object as an {@code int}.
385     * This reproduces the effect of {@code object.fieldName}
386     * <p>
387     * If this field is static, the object argument is ignored.
388     * Otherwise, if the object is {@code null}, a NullPointerException is
389     * thrown. If the object is not an instance of the declaring class of the
390     * method, an IllegalArgumentException is thrown.
391     * <p>
392     * If this Field object is enforcing access control (see AccessibleObject)
393     * and this field is not accessible from the current context, an
394     * IllegalAccessException is thrown.
395     *
396     * @param object
397     *            the object to access
398     * @return the field value
399     * @throws NullPointerException
400     *             if the object is {@code null} and the field is non-static
401     * @throws IllegalArgumentException
402     *             if the object is not compatible with the declaring class
403     * @throws IllegalAccessException
404     *             if this field is not accessible
405     */
406    public int getInt(Object object) throws IllegalAccessException, IllegalArgumentException {
407        return getIField(object, declaringClass, type, slot, flag, TYPE_INTEGER);
408    }
409
410    /**
411     * Returns the value of the field in the specified object as a {@code long}.
412     * This reproduces the effect of {@code object.fieldName}
413     * <p>
414     * If this field is static, the object argument is ignored.
415     * Otherwise, if the object is {@code null}, a NullPointerException is
416     * thrown. If the object is not an instance of the declaring class of the
417     * method, an IllegalArgumentException is thrown.
418     * <p>
419     * If this Field object is enforcing access control (see AccessibleObject)
420     * and this field is not accessible from the current context, an
421     * IllegalAccessException is thrown.
422     *
423     * @param object
424     *            the object to access
425     * @return the field value
426     * @throws NullPointerException
427     *             if the object is {@code null} and the field is non-static
428     * @throws IllegalArgumentException
429     *             if the object is not compatible with the declaring class
430     * @throws IllegalAccessException
431     *             if this field is not accessible
432     */
433    public long getLong(Object object) throws IllegalAccessException, IllegalArgumentException {
434        return getJField(object, declaringClass, type, slot, flag, TYPE_LONG);
435    }
436
437    /**
438     * Returns the modifiers for this field. The {@link Modifier} class should
439     * be used to decode the result.
440     *
441     * @return the modifiers for this field
442     * @see Modifier
443     */
444    public int getModifiers() {
445        return getFieldModifiers(declaringClass, slot);
446    }
447
448    private native int getFieldModifiers(Class<?> declaringClass, int slot);
449
450    /**
451     * Returns the name of this field.
452     *
453     * @return the name of this field
454     */
455    public String getName() {
456        return name;
457    }
458
459    /**
460     * Returns the value of the field in the specified object as a {@code short}
461     * . This reproduces the effect of {@code object.fieldName}
462     * <p>
463     * If this field is static, the object argument is ignored.
464     * Otherwise, if the object is {@code null}, a NullPointerException is
465     * thrown. If the object is not an instance of the declaring class of the
466     * method, an IllegalArgumentException is thrown.
467     * <p>
468     * If this Field object is enforcing access control (see AccessibleObject)
469     * and this field is not accessible from the current context, an
470     * IllegalAccessException is thrown.
471     *
472     * @param object
473     *            the object to access
474     * @return the field value
475     * @throws NullPointerException
476     *             if the object is {@code null} and the field is non-static
477     * @throws IllegalArgumentException
478     *             if the object is not compatible with the declaring class
479     * @throws IllegalAccessException
480     *             if this field is not accessible
481     */
482    public short getShort(Object object) throws IllegalAccessException, IllegalArgumentException {
483        return getSField(object, declaringClass, type, slot, flag, TYPE_SHORT);
484    }
485
486    /**
487     * Returns the constructor's signature in non-printable form. This is called
488     * (only) from IO native code and needed for deriving the serialVersionUID
489     * of the class
490     *
491     * @return the constructor's signature.
492     */
493    @SuppressWarnings("unused")
494    private String getSignature() {
495        return getSignature(type);
496    }
497
498    /**
499     * Return the {@link Class} associated with the type of this field.
500     *
501     * @return the type of this field
502     */
503    public Class<?> getType() {
504        return type;
505    }
506
507    /**
508     * Returns an integer hash code for this field. Objects which are equal
509     * return the same value for this method.
510     * <p>
511     * The hash code for a Field is the exclusive-or combination of the hash
512     * code of the field's name and the hash code of the name of its declaring
513     * class.
514     *
515     * @return the hash code for this field
516     * @see #equals
517     */
518    @Override
519    public int hashCode() {
520        return name.hashCode() ^ getDeclaringClass().getName().hashCode();
521    }
522
523    /**
524     * Sets the value of the field in the specified object to the value. This
525     * reproduces the effect of {@code object.fieldName = value}
526     *
527     * <p>If this field is static, the object argument is ignored.
528     * Otherwise, if the object is {@code null}, a NullPointerException is
529     * thrown. If the object is not an instance of the declaring class of the
530     * method, an IllegalArgumentException is thrown.
531     *
532     * <p>If this Field object is enforcing access control (see AccessibleObject)
533     * and this field is not accessible from the current context, an
534     * IllegalAccessException is thrown.
535     *
536     * <p>If the field type is a primitive type, the value is automatically
537     * unboxed. If the unboxing fails, an IllegalArgumentException is thrown. If
538     * the value cannot be converted to the field type via a widening
539     * conversion, an IllegalArgumentException is thrown.
540     *
541     * @param object
542     *            the object to access
543     * @param value
544     *            the new value
545     * @throws NullPointerException
546     *             if the object is {@code null} and the field is non-static
547     * @throws IllegalArgumentException
548     *             if the object is not compatible with the declaring class
549     * @throws IllegalAccessException
550     *             if this field is not accessible
551     */
552    public void set(Object object, Object value) throws IllegalAccessException,
553            IllegalArgumentException {
554        setField(object, declaringClass, type, slot, flag, value);
555    }
556
557    /**
558     * Sets the value of the field in the specified object to the {@code
559     * boolean} value. This reproduces the effect of {@code object.fieldName =
560     * value}
561     * <p>
562     * If this field is static, the object argument is ignored.
563     * Otherwise, if the object is {@code null}, a NullPointerException is
564     * thrown. If the object is not an instance of the declaring class of the
565     * method, an IllegalArgumentException is thrown.
566     * <p>
567     * If this Field object is enforcing access control (see AccessibleObject)
568     * and this field is not accessible from the current context, an
569     * IllegalAccessException is thrown.
570     * <p>
571     * If the value cannot be converted to the field type via a widening
572     * conversion, an IllegalArgumentException is thrown.
573     *
574     * @param object
575     *            the object to access
576     * @param value
577     *            the new value
578     * @throws NullPointerException
579     *             if the object is {@code null} and the field is non-static
580     * @throws IllegalArgumentException
581     *             if the object is not compatible with the declaring class
582     * @throws IllegalAccessException
583     *             if this field is not accessible
584     */
585    public void setBoolean(Object object, boolean value) throws IllegalAccessException,
586            IllegalArgumentException {
587        setZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN, value);
588    }
589
590    /**
591     * Sets the value of the field in the specified object to the {@code byte}
592     * value. This reproduces the effect of {@code object.fieldName = value}
593     * <p>
594     * If this field is static, the object argument is ignored.
595     * Otherwise, if the object is {@code null}, a NullPointerException is
596     * thrown. If the object is not an instance of the declaring class of the
597     * method, an IllegalArgumentException is thrown.
598     * <p>
599     * If this Field object is enforcing access control (see AccessibleObject)
600     * and this field is not accessible from the current context, an
601     * IllegalAccessException is thrown.
602     * <p>
603     * If the value cannot be converted to the field type via a widening
604     * conversion, an IllegalArgumentException is thrown.
605     *
606     * @param object
607     *            the object to access
608     * @param value
609     *            the new value
610     * @throws NullPointerException
611     *             if the object is {@code null} and the field is non-static
612     * @throws IllegalArgumentException
613     *             if the object is not compatible with the declaring class
614     * @throws IllegalAccessException
615     *             if this field is not accessible
616     */
617    public void setByte(Object object, byte value) throws IllegalAccessException,
618            IllegalArgumentException {
619        setBField(object, declaringClass, type, slot, flag, TYPE_BYTE, value);
620    }
621
622    /**
623     * Sets the value of the field in the specified object to the {@code char}
624     * value. This reproduces the effect of {@code object.fieldName = value}
625     * <p>
626     * If this field is static, the object argument is ignored.
627     * Otherwise, if the object is {@code null}, a NullPointerException is
628     * thrown. If the object is not an instance of the declaring class of the
629     * method, an IllegalArgumentException is thrown.
630     * <p>
631     * If this Field object is enforcing access control (see AccessibleObject)
632     * and this field is not accessible from the current context, an
633     * IllegalAccessException is thrown.
634     * <p>
635     * If the value cannot be converted to the field type via a widening
636     * conversion, an IllegalArgumentException is thrown.
637     *
638     * @param object
639     *            the object to access
640     * @param value
641     *            the new value
642     * @throws NullPointerException
643     *             if the object is {@code null} and the field is non-static
644     * @throws IllegalArgumentException
645     *             if the object is not compatible with the declaring class
646     * @throws IllegalAccessException
647     *             if this field is not accessible
648     */
649    public void setChar(Object object, char value) throws IllegalAccessException,
650            IllegalArgumentException {
651        setCField(object, declaringClass, type, slot, flag, TYPE_CHAR, value);
652    }
653
654    /**
655     * Sets the value of the field in the specified object to the {@code double}
656     * value. This reproduces the effect of {@code object.fieldName = value}
657     * <p>
658     * If this field is static, the object argument is ignored.
659     * Otherwise, if the object is {@code null}, a NullPointerException is
660     * thrown. If the object is not an instance of the declaring class of the
661     * method, an IllegalArgumentException is thrown.
662     * <p>
663     * If this Field object is enforcing access control (see AccessibleObject)
664     * and this field is not accessible from the current context, an
665     * IllegalAccessException is thrown.
666     * <p>
667     * If the value cannot be converted to the field type via a widening
668     * conversion, an IllegalArgumentException is thrown.
669     *
670     * @param object
671     *            the object to access
672     * @param value
673     *            the new value
674     * @throws NullPointerException
675     *             if the object is {@code null} and the field is non-static
676     * @throws IllegalArgumentException
677     *             if the object is not compatible with the declaring class
678     * @throws IllegalAccessException
679     *             if this field is not accessible
680     */
681    public void setDouble(Object object, double value) throws IllegalAccessException,
682            IllegalArgumentException {
683        setDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE, value);
684    }
685
686    /**
687     * Sets the value of the field in the specified object to the {@code float}
688     * value. This reproduces the effect of {@code object.fieldName = value}
689     * <p>
690     * If this field is static, the object argument is ignored.
691     * Otherwise, if the object is {@code null}, a NullPointerException is
692     * thrown. If the object is not an instance of the declaring class of the
693     * method, an IllegalArgumentException is thrown.
694     * <p>
695     * If this Field object is enforcing access control (see AccessibleObject)
696     * and this field is not accessible from the current context, an
697     * IllegalAccessException is thrown.
698     * <p>
699     * If the value cannot be converted to the field type via a widening
700     * conversion, an IllegalArgumentException is thrown.
701     *
702     * @param object
703     *            the object to access
704     * @param value
705     *            the new value
706     * @throws NullPointerException
707     *             if the object is {@code null} and the field is non-static
708     * @throws IllegalArgumentException
709     *             if the object is not compatible with the declaring class
710     * @throws IllegalAccessException
711     *             if this field is not accessible
712     */
713    public void setFloat(Object object, float value) throws IllegalAccessException,
714            IllegalArgumentException {
715        setFField(object, declaringClass, type, slot, flag, TYPE_FLOAT, value);
716    }
717
718    /**
719     * Set the value of the field in the specified object to the {@code int}
720     * value. This reproduces the effect of {@code object.fieldName = value}
721     * <p>
722     * If this field is static, the object argument is ignored.
723     * Otherwise, if the object is {@code null}, a NullPointerException is
724     * thrown. If the object is not an instance of the declaring class of the
725     * method, an IllegalArgumentException is thrown.
726     * <p>
727     * If this Field object is enforcing access control (see AccessibleObject)
728     * and this field is not accessible from the current context, an
729     * IllegalAccessException is thrown.
730     * <p>
731     * If the value cannot be converted to the field type via a widening
732     * conversion, an IllegalArgumentException is thrown.
733     *
734     * @param object
735     *            the object to access
736     * @param value
737     *            the new value
738     * @throws NullPointerException
739     *             if the object is {@code null} and the field is non-static
740     * @throws IllegalArgumentException
741     *             if the object is not compatible with the declaring class
742     * @throws IllegalAccessException
743     *             if this field is not accessible
744     */
745    public void setInt(Object object, int value) throws IllegalAccessException,
746            IllegalArgumentException {
747        setIField(object, declaringClass, type, slot, flag, TYPE_INTEGER, value);
748    }
749
750    /**
751     * Sets the value of the field in the specified object to the {@code long}
752     * value. This reproduces the effect of {@code object.fieldName = value}
753     * <p>
754     * If this field is static, the object argument is ignored.
755     * Otherwise, if the object is {@code null}, a NullPointerException is
756     * thrown. If the object is not an instance of the declaring class of the
757     * method, an IllegalArgumentException is thrown.
758     * <p>
759     * If this Field object is enforcing access control (see AccessibleObject)
760     * and this field is not accessible from the current context, an
761     * IllegalAccessException is thrown.
762     * <p>
763     * If the value cannot be converted to the field type via a widening
764     * conversion, an IllegalArgumentException is thrown.
765     *
766     * @param object
767     *            the object to access
768     * @param value
769     *            the new value
770     * @throws NullPointerException
771     *             if the object is {@code null} and the field is non-static
772     * @throws IllegalArgumentException
773     *             if the object is not compatible with the declaring class
774     * @throws IllegalAccessException
775     *             if this field is not accessible
776     */
777    public void setLong(Object object, long value) throws IllegalAccessException,
778            IllegalArgumentException {
779        setJField(object, declaringClass, type, slot, flag, TYPE_LONG, value);
780    }
781
782    /**
783     * Sets the value of the field in the specified object to the {@code short}
784     * value. This reproduces the effect of {@code object.fieldName = value}
785     * <p>
786     * If this field is static, the object argument is ignored.
787     * Otherwise, if the object is {@code null}, a NullPointerException is
788     * thrown. If the object is not an instance of the declaring class of the
789     * method, an IllegalArgumentException is thrown.
790     * <p>
791     * If this Field object is enforcing access control (see AccessibleObject)
792     * and this field is not accessible from the current context, an
793     * IllegalAccessException is thrown.
794     * <p>
795     * If the value cannot be converted to the field type via a widening
796     * conversion, an IllegalArgumentException is thrown.
797     *
798     * @param object
799     *            the object to access
800     * @param value
801     *            the new value
802     * @throws NullPointerException
803     *             if the object is {@code null} and the field is non-static
804     * @throws IllegalArgumentException
805     *             if the object is not compatible with the declaring class
806     * @throws IllegalAccessException
807     *             if this field is not accessible
808     */
809    public void setShort(Object object, short value) throws IllegalAccessException,
810            IllegalArgumentException {
811        setSField(object, declaringClass, type, slot, flag, TYPE_SHORT, value);
812    }
813
814    /**
815     * Returns a string containing a concise, human-readable description of this
816     * field.
817     * <p>
818     * The format of the string is:
819     * <ol>
820     *   <li>modifiers (if any)
821     *   <li>type
822     *   <li>declaring class name
823     *   <li>'.'
824     *   <li>field name
825     * </ol>
826     * <p>
827     * For example: {@code public static java.io.InputStream
828     * java.lang.System.in}
829     *
830     * @return a printable representation for this field
831     */
832    @Override
833    public String toString() {
834        StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
835        if (result.length() != 0) {
836            result.append(' ');
837        }
838        appendArrayType(result, type);
839        result.append(' ');
840        result.append(declaringClass.getName());
841        result.append('.');
842        result.append(name);
843        return result.toString();
844    }
845
846    private native Object getField(Object o, Class<?> declaringClass, Class<?> type, int slot,
847            boolean noAccessCheck) throws IllegalAccessException;
848
849    private native double getDField(Object o, Class<?> declaringClass, Class<?> type, int slot,
850            boolean noAccessCheck, int type_no) throws IllegalAccessException;
851
852    private native int getIField(Object o, Class<?> declaringClass, Class<?> type, int slot,
853            boolean noAccessCheck, int type_no) throws IllegalAccessException;
854
855    private native long getJField(Object o, Class<?> declaringClass, Class<?> type, int slot,
856            boolean noAccessCheck, int type_no) throws IllegalAccessException;
857
858    private native boolean getZField(Object o, Class<?> declaringClass, Class<?> type, int slot,
859            boolean noAccessCheck, int type_no) throws IllegalAccessException;
860
861    private native float getFField(Object o, Class<?> declaringClass, Class<?> type, int slot,
862            boolean noAccessCheck, int type_no) throws IllegalAccessException;
863
864    private native char getCField(Object o, Class<?> declaringClass, Class<?> type, int slot,
865            boolean noAccessCheck, int type_no) throws IllegalAccessException;
866
867    private native short getSField(Object o, Class<?> declaringClass, Class<?> type, int slot,
868            boolean noAccessCheck, int type_no) throws IllegalAccessException;
869
870    private native byte getBField(Object o, Class<?> declaringClass, Class<?> type, int slot,
871            boolean noAccessCheck, int type_no) throws IllegalAccessException;
872
873    private native void setField(Object o, Class<?> declaringClass, Class<?> type, int slot,
874            boolean noAccessCheck, Object value) throws IllegalAccessException;
875
876    private native void setDField(Object o, Class<?> declaringClass, Class<?> type, int slot,
877            boolean noAccessCheck, int type_no, double v) throws IllegalAccessException;
878
879    private native void setIField(Object o, Class<?> declaringClass, Class<?> type, int slot,
880            boolean noAccessCheck, int type_no, int i) throws IllegalAccessException;
881
882    private native void setJField(Object o, Class<?> declaringClass, Class<?> type, int slot,
883            boolean noAccessCheck, int type_no, long j) throws IllegalAccessException;
884
885    private native void setZField(Object o, Class<?> declaringClass, Class<?> type, int slot,
886            boolean noAccessCheck, int type_no, boolean z) throws IllegalAccessException;
887
888    private native void setFField(Object o, Class<?> declaringClass, Class<?> type, int slot,
889            boolean noAccessCheck, int type_no, float f) throws IllegalAccessException;
890
891    private native void setCField(Object o, Class<?> declaringClass, Class<?> type, int slot,
892            boolean noAccessCheck, int type_no, char c) throws IllegalAccessException;
893
894    private native void setSField(Object o, Class<?> declaringClass, Class<?> type, int slot,
895            boolean noAccessCheck, int type_no, short s) throws IllegalAccessException;
896
897    private native void setBField(Object o, Class<?> declaringClass, Class<?> type, int slot,
898            boolean noAccessCheck, int type_no, byte b) throws IllegalAccessException;
899
900}
901