1. /*
  2. * @(#)Field.java 1.17 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.lang.reflect;
  8. /**
  9. * A <code>Field</code> provides information about, and dynamic access to, a
  10. * single field of a class or an interface. The reflected field may
  11. * be a class (static) field or an instance field.
  12. *
  13. * <p>A <code>Field</code> permits widening conversions to occur during a get or
  14. * set access operation, but throws an <code>IllegalArgumentException</code> if a
  15. * narrowing conversion would occur.
  16. *
  17. * @see Member
  18. * @see java.lang.Class
  19. * @see java.lang.Class#getFields()
  20. * @see java.lang.Class#getField()
  21. * @see java.lang.Class#getDeclaredFields()
  22. * @see java.lang.Class#getDeclaredField()
  23. *
  24. * @author Nakul Saraiya
  25. */
  26. public final
  27. class Field extends AccessibleObject implements Member {
  28. private Class clazz;
  29. private int slot;
  30. private String name;
  31. private Class type;
  32. private int modifiers;
  33. /**
  34. * Constructor. Only the Java Virtual Machine may construct a Field.
  35. */
  36. private Field() {}
  37. /**
  38. * Returns the <code>Class</code> object representing the class or interface
  39. * that declares the field represented by this <code>Field</code> object.
  40. */
  41. public Class getDeclaringClass() {
  42. return clazz;
  43. }
  44. /**
  45. * Returns the name of the field represented by this <code>Field</code> object.
  46. */
  47. public String getName() {
  48. return name;
  49. }
  50. /**
  51. * Returns the Java language modifiers for the field represented
  52. * by this <code>Field</code> object, as an integer. The <code>Modifier</code> class should
  53. * be used to decode the modifiers.
  54. *
  55. * @see Modifier
  56. */
  57. public int getModifiers() {
  58. return modifiers;
  59. }
  60. /**
  61. * Returns a <code>Class</code> object that identifies the declared type for
  62. * the field represented by this <code>Field</code> object.
  63. */
  64. public Class getType() {
  65. return type;
  66. }
  67. /**
  68. * Compares this <code>Field</code> against the specified object. Returns
  69. * true if the objects are the same. Two <code>Field</code> objects are the same if
  70. * they were declared by the same class and have the same name
  71. * and type.
  72. */
  73. public boolean equals(Object obj) {
  74. if (obj != null && obj instanceof Field) {
  75. Field other = (Field)obj;
  76. return (getDeclaringClass() == other.getDeclaringClass())
  77. && (getName().equals(other.getName()))
  78. && (getType() == other.getType());
  79. }
  80. return false;
  81. }
  82. /**
  83. * Returns a hashcode for this <code>Field</code>. This is computed as the
  84. * exclusive-or of the hashcodes for the underlying field's
  85. * declaring class name and its name.
  86. */
  87. public int hashCode() {
  88. return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
  89. }
  90. /**
  91. * Returns a string describing this <code>Field</code>. The format is
  92. * the access modifiers for the field, if any, followed
  93. * by the field type, followed by a space, followed by
  94. * the fully-qualified name of the class declaring the field,
  95. * followed by a period, followed by the name of the field.
  96. * For example:
  97. * <pre>
  98. * public static final int java.lang.Thread.MIN_PRIORITY
  99. * private int java.io.FileDescriptor.fd
  100. * </pre>
  101. *
  102. * <p>The modifiers are placed in canonical order as specified by
  103. * "The Java Language Specification". This is <tt>public</tt>,
  104. * <tt>protected</tt> or <tt>private</tt> first, and then other
  105. * modifiers in the following order: <tt>static</tt>, <tt>final</tt>,
  106. * <tt>transient</tt>, <tt>volatile</tt>.
  107. */
  108. public String toString() {
  109. int mod = getModifiers();
  110. return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
  111. + getTypeName(getType()) + " "
  112. + getTypeName(getDeclaringClass()) + "."
  113. + getName());
  114. }
  115. /**
  116. * Returns the value of the field represented by this <code>Field</code>, on
  117. * the specified object. The value is automatically wrapped in an
  118. * object if it has a primitive type.
  119. *
  120. * <p>The underlying field's value is obtained as follows:
  121. *
  122. * <p>If the underlying field is a static field, the <code>obj</code> argument
  123. * is ignored; it may be null.
  124. *
  125. * <p>Otherwise, the underlying field is an instance field. If the
  126. * specified <code>obj</code> argument is null, the method throws a
  127. * <code>NullPointerException.</code> If the specified object is not an
  128. * instance of the class or interface declaring the underlying
  129. * field, the method throws an <code>IllegalArgumentException</code>.
  130. *
  131. * <p>If this <code>Field</code> object enforces Java language access control, and
  132. * the underlying field is inaccessible, the method throws an
  133. * <code>IllegalAccessException</code>.
  134. * If the underlying field is static, the class that declared the
  135. * field is initialized if it has not already been initialized.
  136. *
  137. * <p>Otherwise, the value is retrieved from the underlying instance
  138. * or static field. If the field has a primitive type, the value
  139. * is wrapped in an object before being returned, otherwise it is
  140. * returned as is.
  141. *
  142. * <p>If the field is hidden in the type of <code>obj</code>,
  143. * the field's value is obtained according to the preceding rules.
  144. *
  145. * @exception IllegalAccessException if the underlying constructor
  146. * is inaccessible.
  147. * @exception IllegalArgumentException if the specified object is not an
  148. * instance of the class or interface declaring the underlying
  149. * field (or a subclass or implementor thereof).
  150. * @exception NullPointerException if the specified object is null
  151. * and the field is an instance field.
  152. * @exception ExceptionInInitializerError if the initialization provoked
  153. * by this method fails.
  154. */
  155. public native Object get(Object obj)
  156. throws IllegalArgumentException, IllegalAccessException;
  157. /**
  158. * Gets the value of a field as a <code>boolean</code> on the specified object.
  159. * This method is equivalent to
  160. * <code>((Boolean)get(obj)).booleanValue()</code>,
  161. * except that an <code>IllegalArgumentException</code> is thrown
  162. * if the field value cannot be converted to the type
  163. * <code>boolean</code> by a widening conversion.
  164. *
  165. * @exception IllegalAccessException if the underlying constructor
  166. * is inaccessible.
  167. * @exception IllegalArgumentException if the specified object is not
  168. * an instance of the class or interface declaring the
  169. * underlying field (or a subclass or implementor
  170. * thereof), or if the field value cannot be
  171. * converted to the type <code>boolean</code> by a
  172. * widening conversion.
  173. * @exception NullPointerException if the specified object is null
  174. * and the field is an instance field.
  175. * @exception ExceptionInInitializerError if the initialization provoked
  176. * by this method fails.
  177. * @see Field#get
  178. */
  179. public native boolean getBoolean(Object obj)
  180. throws IllegalArgumentException, IllegalAccessException;
  181. /**
  182. * Gets the value of a field as a <code>byte</code> on the specified object.
  183. * This method is equivalent to
  184. * <code>((Number)get(obj)).byteValue()</code>,
  185. * except that an <code>IllegalArgumentException</code> is thrown
  186. * if the field value cannot be converted to the type
  187. * <code>byte</code> by a widening conversion.
  188. *
  189. * @exception IllegalAccessException if the underlying constructor
  190. * is inaccessible.
  191. * @exception IllegalArgumentException if the specified object is not
  192. * an instance of the class or interface declaring the
  193. * underlying field (or a subclass or implementor
  194. * thereof), or if the field value cannot be
  195. * converted to the type <code>byte</code> by a
  196. * widening conversion.
  197. * @exception NullPointerException if the specified object is null
  198. * and the field is an instance field.
  199. * @exception ExceptionInInitializerError if the initialization provoked
  200. * by this method fails.
  201. * @see Field#get
  202. */
  203. public native byte getByte(Object obj)
  204. throws IllegalArgumentException, IllegalAccessException;
  205. /**
  206. * Gets the value of a field as a <code>char</code> on the specified object.
  207. * This method is equivalent to
  208. * <code>((Character)get(obj)).charValue()</code>,
  209. * except that an <code>IllegalArgumentException</code> is thrown
  210. * if the field value cannot be converted to the type
  211. * <code>char</code> by a widening conversion.
  212. *
  213. * @exception IllegalAccessException if the underlying constructor
  214. * is inaccessible.
  215. * @exception IllegalArgumentException if the specified object is not
  216. * an instance of the class or interface declaring the
  217. * underlying field (or a subclass or implementor
  218. * thereof), or if the field value cannot be
  219. * converted to the type <code>char</code> by a
  220. * widening conversion.
  221. * @exception NullPointerException if the specified object is null
  222. * and the field is an instance field.
  223. * @exception ExceptionInInitializerError if the initialization provoked
  224. * by this method fails.
  225. * @see Field#get
  226. */
  227. public native char getChar(Object obj)
  228. throws IllegalArgumentException, IllegalAccessException;
  229. /**
  230. * Gets the value of a field as a <code>short</code> on the specified object.
  231. * This method is equivalent to
  232. * <code>((Number)get(obj)).shortValue()</code>,
  233. * except that an <code>IllegalArgumentException</code> is thrown
  234. * if the field value cannot be converted to the type
  235. * <code>short</code> by a widening conversion.
  236. *
  237. * @exception IllegalAccessException if the underlying constructor
  238. * is inaccessible.
  239. * @exception IllegalArgumentException if the specified object is not
  240. * an instance of the class or interface declaring the
  241. * underlying field (or a subclass or implementor
  242. * thereof), or if the field value cannot be
  243. * converted to the type <code>short</code> by a
  244. * widening conversion.
  245. * @exception NullPointerException if the specified object is null
  246. * and the field is an instance field.
  247. * @exception ExceptionInInitializerError if the initialization provoked
  248. * by this method fails.
  249. * @see Field#get
  250. */
  251. public native short getShort(Object obj)
  252. throws IllegalArgumentException, IllegalAccessException;
  253. /**
  254. * Gets the value of a field as an <code>int</code> on the specified object.
  255. * This method is equivalent to
  256. * <code>((Number)get(obj)).intValue()</code>,
  257. * except that an <code>IllegalArgumentException</code> is thrown
  258. * if the field value cannot be converted to the type
  259. * <code>int</code> by a widening conversion.
  260. *
  261. * @exception IllegalAccessException if the underlying constructor
  262. * is inaccessible.
  263. * @exception IllegalArgumentException if the specified object is not
  264. * an instance of the class or interface declaring the
  265. * underlying field (or a subclass or implementor
  266. * thereof), or if the field value cannot be
  267. * converted to the type <code>int</code> by a
  268. * widening conversion.
  269. * @exception NullPointerException if the specified object is null
  270. * and the field is an instance field.
  271. * @exception ExceptionInInitializerError if the initialization provoked
  272. * by this method fails.
  273. * @see Field#get
  274. */
  275. public native int getInt(Object obj)
  276. throws IllegalArgumentException, IllegalAccessException;
  277. /**
  278. * Gets the value of a field as a <code>long</code> on the specified object.
  279. * This method is equivalent to
  280. * <code>((Number)get(obj)).longValue()</code>,
  281. * except that an <code>IllegalArgumentException</code> is thrown
  282. * if the field value cannot be converted to the type
  283. * <code>long</code> by a widening conversion.
  284. *
  285. * @exception IllegalAccessException if the underlying constructor
  286. * is inaccessible.
  287. * @exception IllegalArgumentException if the specified object is not
  288. * an instance of the class or interface declaring the
  289. * underlying field (or a subclass or implementor
  290. * thereof), or if the field value cannot be
  291. * converted to the type <code>long</code> by a
  292. * widening conversion.
  293. * @exception NullPointerException if the specified object is null
  294. * and the field is an instance field.
  295. * @exception ExceptionInInitializerError if the initialization provoked
  296. * by this method fails.
  297. * @see Field#get
  298. */
  299. public native long getLong(Object obj)
  300. throws IllegalArgumentException, IllegalAccessException;
  301. /**
  302. * Gets the value of a field as a <code>float</code> on the specified object.
  303. * This method is equivalent to
  304. * <code>((Number)get(obj)).floatValue()</code>,
  305. * except that an <code>IllegalArgumentException</code> is thrown
  306. * if the field value cannot be converted to the type
  307. * <code>float</code> by a widening conversion.
  308. *
  309. * @exception IllegalAccessException if the underlying constructor
  310. * is inaccessible.
  311. * @exception IllegalArgumentException if the specified object is not
  312. * an instance of the class or interface declaring the
  313. * underlying field (or a subclass or implementor
  314. * thereof), or if the field value cannot be
  315. * converted to the type <code>float</code> by a
  316. * widening conversion.
  317. * @exception NullPointerException if the specified object is null
  318. * and the field is an instance field.
  319. * @exception ExceptionInInitializerError if the initialization provoked
  320. * by this method fails.
  321. * @see Field#get
  322. */
  323. public native float getFloat(Object obj)
  324. throws IllegalArgumentException, IllegalAccessException;
  325. /**
  326. * Gets the value of a field as a <code>double</code> on the specified object.
  327. * This method is equivalent to
  328. * <code>((Number)get(obj)).doubleValue()</code>,
  329. * except that an <code>IllegalArgumentException</code> is thrown
  330. * if the field value cannot be converted to the type
  331. * <code>double</code> by a widening conversion.
  332. *
  333. * @exception IllegalAccessException if the underlying constructor
  334. * is inaccessible.
  335. * @exception IllegalArgumentException if the specified object is not
  336. * an instance of the class or interface declaring the
  337. * underlying field (or a subclass or implementor
  338. * thereof), or if the field value cannot be
  339. * converted to the type <code>double</code> by a
  340. * widening conversion.
  341. * @exception NullPointerException if the specified object is null
  342. * and the field is an instance field.
  343. * @exception ExceptionInInitializerError if the initialization provoked
  344. * by this method fails.
  345. * @see Field#get
  346. */
  347. public native double getDouble(Object obj)
  348. throws IllegalArgumentException, IllegalAccessException;
  349. /**
  350. * Sets the field represented by this <code>Field</code> object on the
  351. * specified object argument to the specified new value. The new
  352. * value is automatically unwrapped if the underlying field has a
  353. * primitive type.
  354. *
  355. * <p>The operation proceeds as follows:
  356. *
  357. * <p>If the underlying field is static, the <code>obj</code> argument is
  358. * ignored; it may be null.
  359. *
  360. * <p>Otherwise the underlying field is an instance field. If the
  361. * specified object argument is null, the method throws a
  362. * <code>NullPointerException</code>. If the specified object argument is not
  363. * an instance of the class or interface declaring the underlying
  364. * field, the method throws an <code>IllegalArgumentException</code>.
  365. *
  366. * <p>If this <code>Field</code> object enforces Java language access control, and
  367. * the underlying field is inaccessible, the method throws an
  368. * <code>IllegalAccessException</code>.
  369. *
  370. * <p>If the underlying field is final, the method throws an
  371. * <code>IllegalAccessException</code>.
  372. *
  373. * <p>If the underlying field is of a primitive type, an unwrapping
  374. * conversion is attempted to convert the new value to a value of
  375. * a primitive type. If this attempt fails, the method throws an
  376. * <code>IllegalArgumentException</code>.
  377. *
  378. * <p>If, after possible unwrapping, the new value cannot be
  379. * converted to the type of the underlying field by an identity or
  380. * widening conversion, the method throws an
  381. * <code>IllegalArgumentException</code>.
  382. *
  383. * <p>If the underlying field is static, the class that declared the
  384. * field is initialized if it has not already been initialized.
  385. *
  386. * <p>The field is set to the possibly unwrapped and widened new value.
  387. *
  388. * <p>If the field is hidden in the type of <code>obj</code>,
  389. * the field's value is set according to the preceding rules.
  390. *
  391. * @exception IllegalAccessException if the underlying constructor
  392. * is inaccessible.
  393. * @exception IllegalArgumentException if the specified object is not an
  394. * instance of the class or interface declaring the underlying
  395. * field (or a subclass or implementor thereof),
  396. * or if an unwrapping conversion fails.
  397. * @exception NullPointerException if the specified object is null
  398. * and the field is an instance field.
  399. * @exception ExceptionInInitializerError if the initialization provoked
  400. * by this method fails.
  401. */
  402. public native void set(Object obj, Object value)
  403. throws IllegalArgumentException, IllegalAccessException;
  404. /**
  405. * Sets the value of a field as a <code>boolean</code> on the specified object.
  406. * This method is equivalent to
  407. * <code>set(obj, zObj)</code>,
  408. * where <code>zObj</code> is a <code>Boolean</code> object and
  409. * <code>zObj.booleanValue() == z</code>.
  410. *
  411. * @exception IllegalAccessException if the underlying constructor
  412. * is inaccessible.
  413. * @exception IllegalArgumentException if the specified object is not an
  414. * instance of the class or interface declaring the underlying
  415. * field (or a subclass or implementor thereof),
  416. * or if an unwrapping conversion fails.
  417. * @exception NullPointerException if the specified object is null
  418. * and the field is an instance field.
  419. * @exception ExceptionInInitializerError if the initialization provoked
  420. * by this method fails.
  421. * @see Field#set
  422. */
  423. public native void setBoolean(Object obj, boolean z)
  424. throws IllegalArgumentException, IllegalAccessException;
  425. /**
  426. * Sets the value of a field as a <code>byte</code> on the specified object.
  427. * This method is equivalent to
  428. * <code>set(obj, bObj)</code>,
  429. * where <code>bObj</code> is a <code>Byte</code> object and
  430. * <code>bObj.byteValue() == b</code>.
  431. *
  432. * @exception IllegalAccessException if the underlying constructor
  433. * is inaccessible.
  434. * @exception IllegalArgumentException if the specified object is not an
  435. * instance of the class or interface declaring the underlying
  436. * field (or a subclass or implementor thereof),
  437. * or if an unwrapping conversion fails.
  438. * @exception NullPointerException if the specified object is null
  439. * and the field is an instance field.
  440. * @exception ExceptionInInitializerError if the initialization provoked
  441. * by this method fails.
  442. * @see Field#set
  443. */
  444. public native void setByte(Object obj, byte b)
  445. throws IllegalArgumentException, IllegalAccessException;
  446. /**
  447. * Sets the value of a field as a <code>char</code> on the specified object.
  448. * This method is equivalent to
  449. * <code>set(obj, cObj)</code>,
  450. * where <code>cObj</code> is a <code>Character</code> object and
  451. * <code>cObj.charValue() == c</code>.
  452. *
  453. * @exception IllegalAccessException if the underlying constructor
  454. * is inaccessible.
  455. * @exception IllegalArgumentException if the specified object is not an
  456. * instance of the class or interface declaring the underlying
  457. * field (or a subclass or implementor thereof),
  458. * or if an unwrapping conversion fails.
  459. * @exception NullPointerException if the specified object is null
  460. * and the field is an instance field.
  461. * @exception ExceptionInInitializerError if the initialization provoked
  462. * by this method fails.
  463. * @see Field#set
  464. */
  465. public native void setChar(Object obj, char c)
  466. throws IllegalArgumentException, IllegalAccessException;
  467. /**
  468. * Sets the value of a field as a <code>short</code> on the specified object.
  469. * This method is equivalent to
  470. * <code>set(obj, sObj)</code>,
  471. * where <code>sObj</code> is a <code>Short</code> object and
  472. * <code>sObj.shortValue() == s</code>.
  473. *
  474. * @exception IllegalAccessException if the underlying constructor
  475. * is inaccessible.
  476. * @exception IllegalArgumentException if the specified object is not an
  477. * instance of the class or interface declaring the underlying
  478. * field (or a subclass or implementor thereof),
  479. * or if an unwrapping conversion fails.
  480. * @exception NullPointerException if the specified object is null
  481. * and the field is an instance field.
  482. * @exception ExceptionInInitializerError if the initialization provoked
  483. * by this method fails.
  484. * @see Field#set
  485. */
  486. public native void setShort(Object obj, short s)
  487. throws IllegalArgumentException, IllegalAccessException;
  488. /**
  489. * Sets the value of a field as an <code>int</code> on the specified object.
  490. * This method is equivalent to
  491. * <code>set(obj, iObj)</code>,
  492. * where <code>iObj</code> is a <code>Integer</code> object and
  493. * <code>iObj.intValue() == i</code>.
  494. *
  495. * @exception IllegalAccessException if the underlying constructor
  496. * is inaccessible.
  497. * @exception IllegalArgumentException if the specified object is not an
  498. * instance of the class or interface declaring the underlying
  499. * field (or a subclass or implementor thereof),
  500. * or if an unwrapping conversion fails.
  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#set
  506. */
  507. public native void setInt(Object obj, int i)
  508. throws IllegalArgumentException, IllegalAccessException;
  509. /**
  510. * Sets the value of a field as a <code>long</code> on the specified object.
  511. * This method is equivalent to
  512. * <code>set(obj, lObj)</code>,
  513. * where <code>lObj</code> is a <code>Long</code> object and
  514. * <code>lObj.longValue() == l</code>.
  515. *
  516. * @exception IllegalAccessException if the underlying constructor
  517. * is inaccessible.
  518. * @exception IllegalArgumentException if the specified object is not an
  519. * instance of the class or interface declaring the underlying
  520. * field (or a subclass or implementor thereof),
  521. * or if an unwrapping conversion fails.
  522. * @exception NullPointerException if the specified object is null
  523. * and the field is an instance field.
  524. * @exception ExceptionInInitializerError if the initialization provoked
  525. * by this method fails.
  526. * @see Field#set
  527. */
  528. public native void setLong(Object obj, long l)
  529. throws IllegalArgumentException, IllegalAccessException;
  530. /**
  531. * Sets the value of a field as a <code>float</code> on the specified object.
  532. * This method is equivalent to
  533. * <code>set(obj, fObj)</code>,
  534. * where <code>fObj</code> is a <code>Float</code> object and
  535. * <code>fObj.floatValue() == f</code>.
  536. *
  537. * @exception IllegalAccessException if the underlying constructor
  538. * is inaccessible.
  539. * @exception IllegalArgumentException if the specified object is not an
  540. * instance of the class or interface declaring the underlying
  541. * field (or a subclass or implementor thereof),
  542. * or if an unwrapping conversion fails.
  543. * @exception NullPointerException if the specified object is null
  544. * and the field is an instance field.
  545. * @exception ExceptionInInitializerError if the initialization provoked
  546. * by this method fails.
  547. * @see Field#set
  548. */
  549. public native void setFloat(Object obj, float f)
  550. throws IllegalArgumentException, IllegalAccessException;
  551. /**
  552. * Sets the value of a field as a <code>double</code> on the specified object.
  553. * This method is equivalent to
  554. * <code>set(obj, dObj)</code>,
  555. * where <code>dObj</code> is a <code>Double</code> object and
  556. * <code>dObj.doubleValue() == d</code>.
  557. *
  558. * @exception IllegalAccessException if the underlying constructor
  559. * is inaccessible.
  560. * @exception IllegalArgumentException if the specified object is not an
  561. * instance of the class or interface declaring the underlying
  562. * field (or a subclass or implementor thereof),
  563. * or if an unwrapping conversion fails.
  564. * @exception NullPointerException if the specified object is null
  565. * and the field is an instance field.
  566. * @exception ExceptionInInitializerError if the initialization provoked
  567. * by this method fails.
  568. * @see Field#set
  569. */
  570. public native void setDouble(Object obj, double d)
  571. throws IllegalArgumentException, IllegalAccessException;
  572. /*
  573. * Utility routine to paper over array type names
  574. */
  575. static String getTypeName(Class type) {
  576. if (type.isArray()) {
  577. try {
  578. Class cl = type;
  579. int dimensions = 0;
  580. while (cl.isArray()) {
  581. dimensions++;
  582. cl = cl.getComponentType();
  583. }
  584. StringBuffer sb = new StringBuffer();
  585. sb.append(cl.getName());
  586. for (int i = 0; i < dimensions; i++) {
  587. sb.append("[]");
  588. }
  589. return sb.toString();
  590. } catch (Throwable e) { /*FALLTHRU*/ }
  591. }
  592. return type.getName();
  593. }
  594. }