1. /*
  2. * @(#)Field.java 1.31 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.lang.reflect;
  8. import sun.reflect.FieldAccessor;
  9. import sun.reflect.Reflection;
  10. /**
  11. * A <code>Field</code> provides information about, and dynamic access to, a
  12. * single field of a class or an interface. The reflected field may
  13. * be a class (static) field or an instance field.
  14. *
  15. * <p>A <code>Field</code> permits widening conversions to occur during a get or
  16. * set access operation, but throws an <code>IllegalArgumentException</code> if a
  17. * narrowing conversion would occur.
  18. *
  19. * @see Member
  20. * @see java.lang.Class
  21. * @see java.lang.Class#getFields()
  22. * @see java.lang.Class#getField(String)
  23. * @see java.lang.Class#getDeclaredFields()
  24. * @see java.lang.Class#getDeclaredField(String)
  25. *
  26. * @author Kenneth Russell
  27. * @author Nakul Saraiya
  28. */
  29. public final
  30. class Field extends AccessibleObject implements Member {
  31. private Class clazz;
  32. private int slot;
  33. // This is guaranteed to be interned by the VM in the 1.4
  34. // reflection implementation
  35. private String name;
  36. private Class type;
  37. private int modifiers;
  38. private volatile FieldAccessor fieldAccessor;
  39. // For sharing of FieldAccessors. This branching structure is
  40. // currently only two levels deep (i.e., one root Field and
  41. // potentially many Field objects pointing to it.)
  42. private Field root;
  43. // More complicated security check cache needed here than for
  44. // Class.newInstance() and Constructor.newInstance()
  45. private volatile Class securityCheckTargetClassCache;
  46. /**
  47. * Package-private constructor used by ReflectAccess to enable
  48. * instantiation of these objects in Java code from the java.lang
  49. * package via sun.reflect.LangReflectAccess.
  50. */
  51. Field(Class declaringClass,
  52. String name,
  53. Class type,
  54. int modifiers,
  55. int slot)
  56. {
  57. this.clazz = declaringClass;
  58. this.name = name;
  59. this.type = type;
  60. this.modifiers = modifiers;
  61. this.slot = slot;
  62. }
  63. /**
  64. * Package-private routine (exposed to java.lang.Class via
  65. * ReflectAccess) which returns a copy of this Field. The copy's
  66. * "root" field points to this Field.
  67. */
  68. Field copy() {
  69. // This routine enables sharing of FieldAccessor objects
  70. // among Field objects which refer to the same underlying
  71. // method in the VM. (All of this contortion is only necessary
  72. // because of the "accessibility" bit in AccessibleObject,
  73. // which implicitly requires that new java.lang.reflect
  74. // objects be fabricated for each reflective call on Class
  75. // objects.)
  76. Field res = new Field(clazz, name, type, modifiers, slot);
  77. res.root = this;
  78. // Might as well eagerly propagate this if already present
  79. res.fieldAccessor = fieldAccessor;
  80. return res;
  81. }
  82. /**
  83. * Returns the <code>Class</code> object representing the class or interface
  84. * that declares the field represented by this <code>Field</code> object.
  85. */
  86. public Class getDeclaringClass() {
  87. return clazz;
  88. }
  89. /**
  90. * Returns the name of the field represented by this <code>Field</code> object.
  91. */
  92. public String getName() {
  93. return name;
  94. }
  95. /**
  96. * Returns the Java language modifiers for the field represented
  97. * by this <code>Field</code> object, as an integer. The <code>Modifier</code> class should
  98. * be used to decode the modifiers.
  99. *
  100. * @see Modifier
  101. */
  102. public int getModifiers() {
  103. return modifiers;
  104. }
  105. /**
  106. * Returns a <code>Class</code> object that identifies the
  107. * declared type for the field represented by this
  108. * <code>Field</code> object.
  109. *
  110. * @return a <code>Class</code> object identifying the declared
  111. * type of the field represented by this object
  112. */
  113. public Class getType() {
  114. return type;
  115. }
  116. /**
  117. * Compares this <code>Field</code> against the specified object. Returns
  118. * true if the objects are the same. Two <code>Field</code> objects are the same if
  119. * they were declared by the same class and have the same name
  120. * and type.
  121. */
  122. public boolean equals(Object obj) {
  123. if (obj != null && obj instanceof Field) {
  124. Field other = (Field)obj;
  125. return (getDeclaringClass() == other.getDeclaringClass())
  126. && (getName() == other.getName())
  127. && (getType() == other.getType());
  128. }
  129. return false;
  130. }
  131. /**
  132. * Returns a hashcode for this <code>Field</code>. This is computed as the
  133. * exclusive-or of the hashcodes for the underlying field's
  134. * declaring class name and its name.
  135. */
  136. public int hashCode() {
  137. return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
  138. }
  139. /**
  140. * Returns a string describing this <code>Field</code>. The format is
  141. * the access modifiers for the field, if any, followed
  142. * by the field type, followed by a space, followed by
  143. * the fully-qualified name of the class declaring the field,
  144. * followed by a period, followed by the name of the field.
  145. * For example:
  146. * <pre>
  147. * public static final int java.lang.Thread.MIN_PRIORITY
  148. * private int java.io.FileDescriptor.fd
  149. * </pre>
  150. *
  151. * <p>The modifiers are placed in canonical order as specified by
  152. * "The Java Language Specification". This is <tt>public</tt>,
  153. * <tt>protected</tt> or <tt>private</tt> first, and then other
  154. * modifiers in the following order: <tt>static</tt>, <tt>final</tt>,
  155. * <tt>transient</tt>, <tt>volatile</tt>.
  156. */
  157. public String toString() {
  158. int mod = getModifiers();
  159. return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
  160. + getTypeName(getType()) + " "
  161. + getTypeName(getDeclaringClass()) + "."
  162. + getName());
  163. }
  164. /**
  165. * Returns the value of the field represented by this <code>Field</code>, on
  166. * the specified object. The value is automatically wrapped in an
  167. * object if it has a primitive type.
  168. *
  169. * <p>The underlying field's value is obtained as follows:
  170. *
  171. * <p>If the underlying field is a static field, the <code>obj</code> argument
  172. * is ignored; it may be null.
  173. *
  174. * <p>Otherwise, the underlying field is an instance field. If the
  175. * specified <code>obj</code> argument is null, the method throws a
  176. * <code>NullPointerException.</code> If the specified object is not an
  177. * instance of the class or interface declaring the underlying
  178. * field, the method throws an <code>IllegalArgumentException</code>.
  179. *
  180. * <p>If this <code>Field</code> object enforces Java language access control, and
  181. * the underlying field is inaccessible, the method throws an
  182. * <code>IllegalAccessException</code>.
  183. * If the underlying field is static, the class that declared the
  184. * field is initialized if it has not already been initialized.
  185. *
  186. * <p>Otherwise, the value is retrieved from the underlying instance
  187. * or static field. If the field has a primitive type, the value
  188. * is wrapped in an object before being returned, otherwise it is
  189. * returned as is.
  190. *
  191. * <p>If the field is hidden in the type of <code>obj</code>,
  192. * the field's value is obtained according to the preceding rules.
  193. *
  194. * @param obj object from which the represented field's value is
  195. * to be extracted
  196. * @return the value of the represented field in object
  197. * <tt>obj</tt> primitive values are wrapped in an appropriate
  198. * object before being returned
  199. *
  200. * @exception IllegalAccessException if the underlying field
  201. * is inaccessible.
  202. * @exception IllegalArgumentException if the specified object is not an
  203. * instance of the class or interface declaring the underlying
  204. * field (or a subclass or implementor thereof).
  205. * @exception NullPointerException if the specified object is null
  206. * and the field is an instance field.
  207. * @exception ExceptionInInitializerError if the initialization provoked
  208. * by this method fails.
  209. */
  210. public Object get(Object obj)
  211. throws IllegalArgumentException, IllegalAccessException
  212. {
  213. return getFieldAccessor(obj).get(obj);
  214. }
  215. /**
  216. * Gets the value of a static or instance <code>boolean</code> field.
  217. *
  218. * @param obj the object to extract the <code>boolean</code> value
  219. * from
  220. * @return the value of the <code>boolean</code> field
  221. *
  222. * @exception IllegalAccessException if the underlying field
  223. * is inaccessible.
  224. * @exception IllegalArgumentException if the specified object is not
  225. * an instance of the class or interface declaring the
  226. * underlying field (or a subclass or implementor
  227. * thereof), or if the field value cannot be
  228. * converted to the type <code>boolean</code> by a
  229. * widening conversion.
  230. * @exception NullPointerException if the specified object is null
  231. * and the field is an instance field.
  232. * @exception ExceptionInInitializerError if the initialization provoked
  233. * by this method fails.
  234. * @see Field#get
  235. */
  236. public boolean getBoolean(Object obj)
  237. throws IllegalArgumentException, IllegalAccessException
  238. {
  239. return getFieldAccessor(obj).getBoolean(obj);
  240. }
  241. /**
  242. * Gets the value of a static or instance <code>byte</code> field.
  243. *
  244. * @param obj the object to extract the <code>byte</code> value
  245. * from
  246. * @return the value of the <code>byte</code> field
  247. *
  248. * @exception IllegalAccessException if the underlying field
  249. * is inaccessible.
  250. * @exception IllegalArgumentException if the specified object is not
  251. * an instance of the class or interface declaring the
  252. * underlying field (or a subclass or implementor
  253. * thereof), or if the field value cannot be
  254. * converted to the type <code>byte</code> by a
  255. * widening conversion.
  256. * @exception NullPointerException if the specified object is null
  257. * and the field is an instance field.
  258. * @exception ExceptionInInitializerError if the initialization provoked
  259. * by this method fails.
  260. * @see Field#get
  261. */
  262. public byte getByte(Object obj)
  263. throws IllegalArgumentException, IllegalAccessException
  264. {
  265. return getFieldAccessor(obj).getByte(obj);
  266. }
  267. /**
  268. * Gets the value of a static or instance field of type
  269. * <code>char</code> or of another primitive type convertible to
  270. * type <code>char</code> via a widening conversion.
  271. *
  272. * @param obj the object to extract the <code>char</code> value
  273. * from
  274. * @return the value of the field converted to type <code>char</code>
  275. *
  276. * @exception IllegalAccessException if the underlying field
  277. * is inaccessible.
  278. * @exception IllegalArgumentException if the specified object is not
  279. * an instance of the class or interface declaring the
  280. * underlying field (or a subclass or implementor
  281. * thereof), or if the field value cannot be
  282. * converted to the type <code>char</code> by a
  283. * widening conversion.
  284. * @exception NullPointerException if the specified object is null
  285. * and the field is an instance field.
  286. * @exception ExceptionInInitializerError if the initialization provoked
  287. * by this method fails.
  288. * @see Field#get
  289. */
  290. public char getChar(Object obj)
  291. throws IllegalArgumentException, IllegalAccessException
  292. {
  293. return getFieldAccessor(obj).getChar(obj);
  294. }
  295. /**
  296. * Gets the value of a static or instance field of type
  297. * <code>short</code> or of another primitive type convertible to
  298. * type <code>short</code> via a widening conversion.
  299. *
  300. * @param obj the object to extract the <code>short</code> value
  301. * from
  302. * @return the value of the field converted to type <code>short</code>
  303. *
  304. * @exception IllegalAccessException if the underlying field
  305. * is inaccessible.
  306. * @exception IllegalArgumentException if the specified object is not
  307. * an instance of the class or interface declaring the
  308. * underlying field (or a subclass or implementor
  309. * thereof), or if the field value cannot be
  310. * converted to the type <code>short</code> by a
  311. * widening conversion.
  312. * @exception NullPointerException if the specified object is null
  313. * and the field is an instance field.
  314. * @exception ExceptionInInitializerError if the initialization provoked
  315. * by this method fails.
  316. * @see Field#get
  317. */
  318. public short getShort(Object obj)
  319. throws IllegalArgumentException, IllegalAccessException
  320. {
  321. return getFieldAccessor(obj).getShort(obj);
  322. }
  323. /**
  324. * Gets the value of a static or instance field of type
  325. * <code>int</code> or of another primitive type convertible to
  326. * type <code>int</code> via a widening conversion.
  327. *
  328. * @param obj the object to extract the <code>int</code> value
  329. * from
  330. * @return the value of the field converted to type <code>int</code>
  331. *
  332. * @exception IllegalAccessException if the underlying field
  333. * is inaccessible.
  334. * @exception IllegalArgumentException if the specified object is not
  335. * an instance of the class or interface declaring the
  336. * underlying field (or a subclass or implementor
  337. * thereof), or if the field value cannot be
  338. * converted to the type <code>int</code> by a
  339. * widening conversion.
  340. * @exception NullPointerException if the specified object is null
  341. * and the field is an instance field.
  342. * @exception ExceptionInInitializerError if the initialization provoked
  343. * by this method fails.
  344. * @see Field#get
  345. */
  346. public int getInt(Object obj)
  347. throws IllegalArgumentException, IllegalAccessException
  348. {
  349. return getFieldAccessor(obj).getInt(obj);
  350. }
  351. /**
  352. * Gets the value of a static or instance field of type
  353. * <code>long</code> or of another primitive type convertible to
  354. * type <code>long</code> via a widening conversion.
  355. *
  356. * @param obj the object to extract the <code>long</code> value
  357. * from
  358. * @return the value of the field converted to type <code>long</code>
  359. *
  360. * @exception IllegalAccessException if the underlying field
  361. * is inaccessible.
  362. * @exception IllegalArgumentException if the specified object is not
  363. * an instance of the class or interface declaring the
  364. * underlying field (or a subclass or implementor
  365. * thereof), or if the field value cannot be
  366. * converted to the type <code>long</code> by a
  367. * widening conversion.
  368. * @exception NullPointerException if the specified object is null
  369. * and the field is an instance field.
  370. * @exception ExceptionInInitializerError if the initialization provoked
  371. * by this method fails.
  372. * @see Field#get
  373. */
  374. public long getLong(Object obj)
  375. throws IllegalArgumentException, IllegalAccessException
  376. {
  377. return getFieldAccessor(obj).getLong(obj);
  378. }
  379. /**
  380. * Gets the value of a static or instance field of type
  381. * <code>float</code> or of another primitive type convertible to
  382. * type <code>float</code> via a widening conversion.
  383. *
  384. * @param obj the object to extract the <code>float</code> value
  385. * from
  386. * @return the value of the field converted to type <code>float</code>
  387. *
  388. * @exception IllegalAccessException if the underlying field
  389. * is inaccessible.
  390. * @exception IllegalArgumentException if the specified object is not
  391. * an instance of the class or interface declaring the
  392. * underlying field (or a subclass or implementor
  393. * thereof), or if the field value cannot be
  394. * converted to the type <code>float</code> by a
  395. * widening conversion.
  396. * @exception NullPointerException if the specified object is null
  397. * and the field is an instance field.
  398. * @exception ExceptionInInitializerError if the initialization provoked
  399. * by this method fails.
  400. * @see Field#get
  401. */
  402. public float getFloat(Object obj)
  403. throws IllegalArgumentException, IllegalAccessException
  404. {
  405. return getFieldAccessor(obj).getFloat(obj);
  406. }
  407. /**
  408. * Gets the value of a static or instance field of type
  409. * <code>double</code> or of another primitive type convertible to
  410. * type <code>double</code> via a widening conversion.
  411. *
  412. * @param obj the object to extract the <code>double</code> value
  413. * from
  414. * @return the value of the field converted to type <code>double</code>
  415. *
  416. * @exception IllegalAccessException if the underlying field
  417. * is inaccessible.
  418. * @exception IllegalArgumentException if the specified object is not
  419. * an instance of the class or interface declaring the
  420. * underlying field (or a subclass or implementor
  421. * thereof), or if the field value cannot be
  422. * converted to the type <code>double</code> by a
  423. * widening conversion.
  424. * @exception NullPointerException if the specified object is null
  425. * and the field is an instance field.
  426. * @exception ExceptionInInitializerError if the initialization provoked
  427. * by this method fails.
  428. * @see Field#get
  429. */
  430. public double getDouble(Object obj)
  431. throws IllegalArgumentException, IllegalAccessException
  432. {
  433. return getFieldAccessor(obj).getDouble(obj);
  434. }
  435. /**
  436. * Sets the field represented by this <code>Field</code> object on the
  437. * specified object argument to the specified new value. The new
  438. * value is automatically unwrapped if the underlying field has a
  439. * primitive type.
  440. *
  441. * <p>The operation proceeds as follows:
  442. *
  443. * <p>If the underlying field is static, the <code>obj</code> argument is
  444. * ignored; it may be null.
  445. *
  446. * <p>Otherwise the underlying field is an instance field. If the
  447. * specified object argument is null, the method throws a
  448. * <code>NullPointerException</code>. If the specified object argument is not
  449. * an instance of the class or interface declaring the underlying
  450. * field, the method throws an <code>IllegalArgumentException</code>.
  451. *
  452. * <p>If this <code>Field</code> object enforces Java language access control, and
  453. * the underlying field is inaccessible, the method throws an
  454. * <code>IllegalAccessException</code>.
  455. *
  456. * <p>If the underlying field is final, the method throws an
  457. * <code>IllegalAccessException</code>.
  458. *
  459. * <p>If the underlying field is of a primitive type, an unwrapping
  460. * conversion is attempted to convert the new value to a value of
  461. * a primitive type. If this attempt fails, the method throws an
  462. * <code>IllegalArgumentException</code>.
  463. *
  464. * <p>If, after possible unwrapping, the new value cannot be
  465. * converted to the type of the underlying field by an identity or
  466. * widening conversion, the method throws an
  467. * <code>IllegalArgumentException</code>.
  468. *
  469. * <p>If the underlying field is static, the class that declared the
  470. * field is initialized if it has not already been initialized.
  471. *
  472. * <p>The field is set to the possibly unwrapped and widened new value.
  473. *
  474. * <p>If the field is hidden in the type of <code>obj</code>,
  475. * the field's value is set according to the preceding rules.
  476. *
  477. * @param obj the object whose field should be modified
  478. * @param value the new value for the field of <code>obj</code>
  479. * being modified
  480. *
  481. * @exception IllegalAccessException if the underlying field
  482. * is inaccessible.
  483. * @exception IllegalArgumentException if the specified object is not an
  484. * instance of the class or interface declaring the underlying
  485. * field (or a subclass or implementor thereof),
  486. * or if an unwrapping conversion fails.
  487. * @exception NullPointerException if the specified object is null
  488. * and the field is an instance field.
  489. * @exception ExceptionInInitializerError if the initialization provoked
  490. * by this method fails.
  491. */
  492. public void set(Object obj, Object value)
  493. throws IllegalArgumentException, IllegalAccessException
  494. {
  495. getFieldAccessor(obj).set(obj, value);
  496. }
  497. /**
  498. * Sets the value of a field as a <code>boolean</code> on the specified object.
  499. * This method is equivalent to
  500. * <code>set(obj, zObj)</code>,
  501. * where <code>zObj</code> is a <code>Boolean</code> object and
  502. * <code>zObj.booleanValue() == z</code>.
  503. *
  504. * @param obj the object whose field should be modified
  505. * @param z the new value for the field of <code>obj</code>
  506. * being modified
  507. *
  508. * @exception IllegalAccessException if the underlying field
  509. * is inaccessible.
  510. * @exception IllegalArgumentException if the specified object is not an
  511. * instance of the class or interface declaring the underlying
  512. * field (or a subclass or implementor thereof),
  513. * or if an unwrapping conversion fails.
  514. * @exception NullPointerException if the specified object is null
  515. * and the field is an instance field.
  516. * @exception ExceptionInInitializerError if the initialization provoked
  517. * by this method fails.
  518. * @see Field#set
  519. */
  520. public void setBoolean(Object obj, boolean z)
  521. throws IllegalArgumentException, IllegalAccessException
  522. {
  523. getFieldAccessor(obj).setBoolean(obj, z);
  524. }
  525. /**
  526. * Sets the value of a field as a <code>byte</code> on the specified object.
  527. * This method is equivalent to
  528. * <code>set(obj, bObj)</code>,
  529. * where <code>bObj</code> is a <code>Byte</code> object and
  530. * <code>bObj.byteValue() == b</code>.
  531. *
  532. * @param obj the object whose field should be modified
  533. * @param b the new value for the field of <code>obj</code>
  534. * being modified
  535. *
  536. * @exception IllegalAccessException if the underlying field
  537. * is inaccessible.
  538. * @exception IllegalArgumentException if the specified object is not an
  539. * instance of the class or interface declaring the underlying
  540. * field (or a subclass or implementor thereof),
  541. * or if an unwrapping conversion fails.
  542. * @exception NullPointerException if the specified object is null
  543. * and the field is an instance field.
  544. * @exception ExceptionInInitializerError if the initialization provoked
  545. * by this method fails.
  546. * @see Field#set
  547. */
  548. public void setByte(Object obj, byte b)
  549. throws IllegalArgumentException, IllegalAccessException
  550. {
  551. getFieldAccessor(obj).setByte(obj, b);
  552. }
  553. /**
  554. * Sets the value of a field as a <code>char</code> on the specified object.
  555. * This method is equivalent to
  556. * <code>set(obj, cObj)</code>,
  557. * where <code>cObj</code> is a <code>Character</code> object and
  558. * <code>cObj.charValue() == c</code>.
  559. *
  560. * @param obj the object whose field should be modified
  561. * @param c the new value for the field of <code>obj</code>
  562. * being modified
  563. *
  564. * @exception IllegalAccessException if the underlying field
  565. * is inaccessible.
  566. * @exception IllegalArgumentException if the specified object is not an
  567. * instance of the class or interface declaring the underlying
  568. * field (or a subclass or implementor thereof),
  569. * or if an unwrapping conversion fails.
  570. * @exception NullPointerException if the specified object is null
  571. * and the field is an instance field.
  572. * @exception ExceptionInInitializerError if the initialization provoked
  573. * by this method fails.
  574. * @see Field#set
  575. */
  576. public void setChar(Object obj, char c)
  577. throws IllegalArgumentException, IllegalAccessException
  578. {
  579. getFieldAccessor(obj).setChar(obj, c);
  580. }
  581. /**
  582. * Sets the value of a field as a <code>short</code> on the specified object.
  583. * This method is equivalent to
  584. * <code>set(obj, sObj)</code>,
  585. * where <code>sObj</code> is a <code>Short</code> object and
  586. * <code>sObj.shortValue() == s</code>.
  587. *
  588. * @param obj the object whose field should be modified
  589. * @param s the new value for the field of <code>obj</code>
  590. * being modified
  591. *
  592. * @exception IllegalAccessException if the underlying field
  593. * is inaccessible.
  594. * @exception IllegalArgumentException if the specified object is not an
  595. * instance of the class or interface declaring the underlying
  596. * field (or a subclass or implementor thereof),
  597. * or if an unwrapping conversion fails.
  598. * @exception NullPointerException if the specified object is null
  599. * and the field is an instance field.
  600. * @exception ExceptionInInitializerError if the initialization provoked
  601. * by this method fails.
  602. * @see Field#set
  603. */
  604. public void setShort(Object obj, short s)
  605. throws IllegalArgumentException, IllegalAccessException
  606. {
  607. getFieldAccessor(obj).setShort(obj, s);
  608. }
  609. /**
  610. * Sets the value of a field as an <code>int</code> on the specified object.
  611. * This method is equivalent to
  612. * <code>set(obj, iObj)</code>,
  613. * where <code>iObj</code> is a <code>Integer</code> object and
  614. * <code>iObj.intValue() == i</code>.
  615. *
  616. * @param obj the object whose field should be modified
  617. * @param i the new value for the field of <code>obj</code>
  618. * being modified
  619. *
  620. * @exception IllegalAccessException if the underlying field
  621. * is inaccessible.
  622. * @exception IllegalArgumentException if the specified object is not an
  623. * instance of the class or interface declaring the underlying
  624. * field (or a subclass or implementor thereof),
  625. * or if an unwrapping conversion fails.
  626. * @exception NullPointerException if the specified object is null
  627. * and the field is an instance field.
  628. * @exception ExceptionInInitializerError if the initialization provoked
  629. * by this method fails.
  630. * @see Field#set
  631. */
  632. public void setInt(Object obj, int i)
  633. throws IllegalArgumentException, IllegalAccessException
  634. {
  635. getFieldAccessor(obj).setInt(obj, i);
  636. }
  637. /**
  638. * Sets the value of a field as a <code>long</code> on the specified object.
  639. * This method is equivalent to
  640. * <code>set(obj, lObj)</code>,
  641. * where <code>lObj</code> is a <code>Long</code> object and
  642. * <code>lObj.longValue() == l</code>.
  643. *
  644. * @param obj the object whose field should be modified
  645. * @param l the new value for the field of <code>obj</code>
  646. * being modified
  647. *
  648. * @exception IllegalAccessException if the underlying field
  649. * is inaccessible.
  650. * @exception IllegalArgumentException if the specified object is not an
  651. * instance of the class or interface declaring the underlying
  652. * field (or a subclass or implementor thereof),
  653. * or if an unwrapping conversion fails.
  654. * @exception NullPointerException if the specified object is null
  655. * and the field is an instance field.
  656. * @exception ExceptionInInitializerError if the initialization provoked
  657. * by this method fails.
  658. * @see Field#set
  659. */
  660. public void setLong(Object obj, long l)
  661. throws IllegalArgumentException, IllegalAccessException
  662. {
  663. getFieldAccessor(obj).setLong(obj, l);
  664. }
  665. /**
  666. * Sets the value of a field as a <code>float</code> on the specified object.
  667. * This method is equivalent to
  668. * <code>set(obj, fObj)</code>,
  669. * where <code>fObj</code> is a <code>Float</code> object and
  670. * <code>fObj.floatValue() == f</code>.
  671. *
  672. * @param obj the object whose field should be modified
  673. * @param f the new value for the field of <code>obj</code>
  674. * being modified
  675. *
  676. * @exception IllegalAccessException if the underlying field
  677. * is inaccessible.
  678. * @exception IllegalArgumentException if the specified object is not an
  679. * instance of the class or interface declaring the underlying
  680. * field (or a subclass or implementor thereof),
  681. * or if an unwrapping conversion fails.
  682. * @exception NullPointerException if the specified object is null
  683. * and the field is an instance field.
  684. * @exception ExceptionInInitializerError if the initialization provoked
  685. * by this method fails.
  686. * @see Field#set
  687. */
  688. public void setFloat(Object obj, float f)
  689. throws IllegalArgumentException, IllegalAccessException
  690. {
  691. getFieldAccessor(obj).setFloat(obj, f);
  692. }
  693. /**
  694. * Sets the value of a field as a <code>double</code> on the specified object.
  695. * This method is equivalent to
  696. * <code>set(obj, dObj)</code>,
  697. * where <code>dObj</code> is a <code>Double</code> object and
  698. * <code>dObj.doubleValue() == d</code>.
  699. *
  700. * @param obj the object whose field should be modified
  701. * @param d the new value for the field of <code>obj</code>
  702. * being modified
  703. *
  704. * @exception IllegalAccessException if the underlying field
  705. * is inaccessible.
  706. * @exception IllegalArgumentException if the specified object is not an
  707. * instance of the class or interface declaring the underlying
  708. * field (or a subclass or implementor thereof),
  709. * or if an unwrapping conversion fails.
  710. * @exception NullPointerException if the specified object is null
  711. * and the field is an instance field.
  712. * @exception ExceptionInInitializerError if the initialization provoked
  713. * by this method fails.
  714. * @see Field#set
  715. */
  716. public void setDouble(Object obj, double d)
  717. throws IllegalArgumentException, IllegalAccessException
  718. {
  719. getFieldAccessor(obj).setDouble(obj, d);
  720. }
  721. // Convenience routine which performs security checks
  722. private FieldAccessor getFieldAccessor(Object obj)
  723. throws IllegalAccessException
  724. {
  725. doSecurityCheck(obj);
  726. if (fieldAccessor == null) {
  727. acquireFieldAccessor();
  728. }
  729. return fieldAccessor;
  730. }
  731. // NOTE that there is no synchronization used here. It is correct
  732. // (though not efficient) to generate more than one FieldAccessor
  733. // for a given Field. However, avoiding synchronization will
  734. // probably make the implementation more scalable.
  735. private void acquireFieldAccessor() {
  736. // First check to see if one has been created yet, and take it
  737. // if so
  738. FieldAccessor tmp = null;
  739. if (root != null) tmp = root.getFieldAccessor();
  740. if (tmp != null) {
  741. fieldAccessor = tmp;
  742. return;
  743. }
  744. // Otherwise fabricate one and propagate it up to the root
  745. tmp = reflectionFactory.newFieldAccessor(this);
  746. setFieldAccessor(tmp);
  747. }
  748. // Returns FieldAccessor for this Field object, not looking up
  749. // the chain to the root
  750. private FieldAccessor getFieldAccessor() {
  751. return fieldAccessor;
  752. }
  753. // Sets the FieldAccessor for this Field object and
  754. // (recursively) its root
  755. private void setFieldAccessor(FieldAccessor accessor) {
  756. fieldAccessor = accessor;
  757. // Propagate up
  758. if (root != null) {
  759. root.setFieldAccessor(accessor);
  760. }
  761. }
  762. // NOTE: be very careful if you change the stack depth of this
  763. // routine. The depth of the "getCallerClass" call is hardwired so
  764. // that the compiler can have an easier time if this gets inlined.
  765. private void doSecurityCheck(Object obj) throws IllegalAccessException {
  766. if (!override) {
  767. if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
  768. Class caller = Reflection.getCallerClass(4);
  769. Class targetClass = ((obj == null || !Modifier.isProtected(modifiers))
  770. ? clazz
  771. : obj.getClass());
  772. if (securityCheckCache != caller ||
  773. targetClass != securityCheckTargetClassCache) {
  774. Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
  775. securityCheckCache = caller;
  776. securityCheckTargetClassCache = targetClass;
  777. }
  778. }
  779. }
  780. }
  781. /*
  782. * Utility routine to paper over array type names
  783. */
  784. static String getTypeName(Class type) {
  785. if (type.isArray()) {
  786. try {
  787. Class cl = type;
  788. int dimensions = 0;
  789. while (cl.isArray()) {
  790. dimensions++;
  791. cl = cl.getComponentType();
  792. }
  793. StringBuffer sb = new StringBuffer();
  794. sb.append(cl.getName());
  795. for (int i = 0; i < dimensions; i++) {
  796. sb.append("[]");
  797. }
  798. return sb.toString();
  799. } catch (Throwable e) { /*FALLTHRU*/ }
  800. }
  801. return type.getName();
  802. }
  803. }