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