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