001: /*
002: * @(#)Field.java 1.26 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.lang.reflect;
029:
030: /**
031: * A <code>Field</code> provides information about, and dynamic access to, a
032: * single field of a class or an interface. The reflected field may
033: * be a class (static) field or an instance field.
034: *
035: * <p>A <code>Field</code> permits widening conversions to occur during a get or
036: * set access operation, but throws an <code>IllegalArgumentException</code> if a
037: * narrowing conversion would occur.
038: *
039: * @see Member
040: * @see java.lang.Class
041: * @see java.lang.Class#getFields()
042: * @see java.lang.Class#getField(String)
043: * @see java.lang.Class#getDeclaredFields()
044: * @see java.lang.Class#getDeclaredField(String)
045: *
046: * @author Nakul Saraiya
047: */
048: public final class Field extends AccessibleObject implements Member {
049:
050: private Class clazz;
051: private int slot;
052: private String name;
053: private Class type;
054: private int modifiers;
055:
056: /**
057: * Constructor. Only the Java Virtual Machine may construct a Field.
058: */
059: private Field() {
060: }
061:
062: /**
063: * Returns the <code>Class</code> object representing the class or interface
064: * that declares the field represented by this <code>Field</code> object.
065: */
066: public Class getDeclaringClass() {
067: return clazz;
068: }
069:
070: /**
071: * Returns the name of the field represented by this <code>Field</code> object.
072: */
073: public String getName() {
074: return name;
075: }
076:
077: /**
078: * Returns the Java language modifiers for the field represented
079: * by this <code>Field</code> object, as an integer. The <code>Modifier</code> class should
080: * be used to decode the modifiers.
081: *
082: * @see Modifier
083: */
084: public int getModifiers() {
085: return modifiers;
086: }
087:
088: /**
089: * Returns a <code>Class</code> object that identifies the
090: * declared type for the field represented by this
091: * <code>Field</code> object.
092: *
093: * @return a <code>Class</code> object identifying the declared
094: * type of the field represented by this object
095: */
096: public Class getType() {
097: return type;
098: }
099:
100: /**
101: * Compares this <code>Field</code> against the specified object. Returns
102: * true if the objects are the same. Two <code>Field</code> objects are the same if
103: * they were declared by the same class and have the same name
104: * and type.
105: */
106: public boolean equals(Object obj) {
107: if (obj != null && obj instanceof Field) {
108: Field other = (Field) obj;
109: return (getDeclaringClass() == other.getDeclaringClass())
110: && (getName().equals(other.getName()))
111: && (getType() == other.getType());
112: }
113: return false;
114: }
115:
116: /**
117: * Returns a hashcode for this <code>Field</code>. This is computed as the
118: * exclusive-or of the hashcodes for the underlying field's
119: * declaring class name and its name.
120: */
121: public int hashCode() {
122: return getDeclaringClass().getName().hashCode()
123: ^ getName().hashCode();
124: }
125:
126: /**
127: * Returns a string describing this <code>Field</code>. The format is
128: * the access modifiers for the field, if any, followed
129: * by the field type, followed by a space, followed by
130: * the fully-qualified name of the class declaring the field,
131: * followed by a period, followed by the name of the field.
132: * For example:
133: * <pre>
134: * public static final int java.lang.Thread.MIN_PRIORITY
135: * private int java.io.FileDescriptor.fd
136: * </pre>
137: *
138: * <p>The modifiers are placed in canonical order as specified by
139: * "The Java Language Specification". This is <tt>public</tt>,
140: * <tt>protected</tt> or <tt>private</tt> first, and then other
141: * modifiers in the following order: <tt>static</tt>, <tt>final</tt>,
142: * <tt>transient</tt>, <tt>volatile</tt>.
143: */
144: public String toString() {
145: int mod = getModifiers();
146: return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
147: + getTypeName(getType()) + " "
148: + getTypeName(getDeclaringClass()) + "." + getName());
149: }
150:
151: /**
152: * Returns the value of the field represented by this <code>Field</code>, on
153: * the specified object. The value is automatically wrapped in an
154: * object if it has a primitive type.
155: *
156: * <p>The underlying field's value is obtained as follows:
157: *
158: * <p>If the underlying field is a static field, the <code>obj</code> argument
159: * is ignored; it may be null.
160: *
161: * <p>Otherwise, the underlying field is an instance field. If the
162: * specified <code>obj</code> argument is null, the method throws a
163: * <code>NullPointerException.</code> If the specified object is not an
164: * instance of the class or interface declaring the underlying
165: * field, the method throws an <code>IllegalArgumentException</code>.
166: *
167: * <p>If this <code>Field</code> object enforces Java language access control, and
168: * the underlying field is inaccessible, the method throws an
169: * <code>IllegalAccessException</code>.
170: * If the underlying field is static, the class that declared the
171: * field is initialized if it has not already been initialized.
172: *
173: * <p>Otherwise, the value is retrieved from the underlying instance
174: * or static field. If the field has a primitive type, the value
175: * is wrapped in an object before being returned, otherwise it is
176: * returned as is.
177: *
178: * <p>If the field is hidden in the type of <code>obj</code>,
179: * the field's value is obtained according to the preceding rules.
180: *
181: * @param obj object from which the represented field's value is
182: * to be extracted
183: * @return the value of the represented field in object
184: * <tt>obj</tt>; primitive values are wrapped in an appropriate
185: * object before being returned
186: *
187: * @exception IllegalAccessException if the underlying field
188: * is inaccessible.
189: * @exception IllegalArgumentException if the specified object is not an
190: * instance of the class or interface declaring the underlying
191: * field (or a subclass or implementor thereof).
192: * @exception NullPointerException if the specified object is null
193: * and the field is an instance field.
194: * @exception ExceptionInInitializerError if the initialization provoked
195: * by this method fails.
196: */
197: public native Object get(Object obj)
198: throws IllegalArgumentException, IllegalAccessException;
199:
200: /**
201: * Gets the value of a static or instance <code>boolean</code> field.
202: *
203: * @param obj the object to extract the <code>boolean</code> value
204: * from
205: * @return the value of the <code>boolean</code> field
206: *
207: * @exception IllegalAccessException if the underlying field
208: * is inaccessible.
209: * @exception IllegalArgumentException if the specified object is not
210: * an instance of the class or interface declaring the
211: * underlying field (or a subclass or implementor
212: * thereof), or if the field value cannot be
213: * converted to the type <code>boolean</code> by a
214: * widening conversion.
215: * @exception NullPointerException if the specified object is null
216: * and the field is an instance field.
217: * @exception ExceptionInInitializerError if the initialization provoked
218: * by this method fails.
219: * @see Field#get
220: */
221: public native boolean getBoolean(Object obj)
222: throws IllegalArgumentException, IllegalAccessException;
223:
224: /**
225: * Gets the value of a static or instance <code>byte</code> field.
226: *
227: * @param obj the object to extract the <code>byte</code> value
228: * from
229: * @return the value of the <code>byte</code> field
230: *
231: * @exception IllegalAccessException if the underlying field
232: * is inaccessible.
233: * @exception IllegalArgumentException if the specified object is not
234: * an instance of the class or interface declaring the
235: * underlying field (or a subclass or implementor
236: * thereof), or if the field value cannot be
237: * converted to the type <code>byte</code> by a
238: * widening conversion.
239: * @exception NullPointerException if the specified object is null
240: * and the field is an instance field.
241: * @exception ExceptionInInitializerError if the initialization provoked
242: * by this method fails.
243: * @see Field#get
244: */
245: public native byte getByte(Object obj)
246: throws IllegalArgumentException, IllegalAccessException;
247:
248: /**
249: * Gets the value of a static or instance field of type
250: * <code>char</code> or of another primitive type convertible to
251: * type <code>char</code> via a widening conversion.
252: *
253: * @param obj the object to extract the <code>char</code> value
254: * from
255: * @return the value of the field converted to type <code>char</code>
256: *
257: * @exception IllegalAccessException if the underlying field
258: * is inaccessible.
259: * @exception IllegalArgumentException if the specified object is not
260: * an instance of the class or interface declaring the
261: * underlying field (or a subclass or implementor
262: * thereof), or if the field value cannot be
263: * converted to the type <code>char</code> by a
264: * widening conversion.
265: * @exception NullPointerException if the specified object is null
266: * and the field is an instance field.
267: * @exception ExceptionInInitializerError if the initialization provoked
268: * by this method fails.
269: * @see Field#get
270: */
271: public native char getChar(Object obj)
272: throws IllegalArgumentException, IllegalAccessException;
273:
274: /**
275: * Gets the value of a static or instance field of type
276: * <code>short</code> or of another primitive type convertible to
277: * type <code>short</code> via a widening conversion.
278: *
279: * @param obj the object to extract the <code>short</code> value
280: * from
281: * @return the value of the field converted to type <code>short</code>
282: *
283: * @exception IllegalAccessException if the underlying field
284: * is inaccessible.
285: * @exception IllegalArgumentException if the specified object is not
286: * an instance of the class or interface declaring the
287: * underlying field (or a subclass or implementor
288: * thereof), or if the field value cannot be
289: * converted to the type <code>short</code> by a
290: * widening conversion.
291: * @exception NullPointerException if the specified object is null
292: * and the field is an instance field.
293: * @exception ExceptionInInitializerError if the initialization provoked
294: * by this method fails.
295: * @see Field#get
296: */
297: public native short getShort(Object obj)
298: throws IllegalArgumentException, IllegalAccessException;
299:
300: /**
301: * Gets the value of a static or instance field of type
302: * <code>int</code> or of another primitive type convertible to
303: * type <code>int</code> via a widening conversion.
304: *
305: * @param obj the object to extract the <code>int</code> value
306: * from
307: * @return the value of the field converted to type <code>int</code>
308: *
309: * @exception IllegalAccessException if the underlying field
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>int</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 int getInt(Object obj)
324: throws IllegalArgumentException, IllegalAccessException;
325:
326: /**
327: * Gets the value of a static or instance field of type
328: * <code>long</code> or of another primitive type convertible to
329: * type <code>long</code> via a widening conversion.
330: *
331: * @param obj the object to extract the <code>long</code> value
332: * from
333: * @return the value of the field converted to type <code>long</code>
334: *
335: * @exception IllegalAccessException if the underlying field
336: * is inaccessible.
337: * @exception IllegalArgumentException if the specified object is not
338: * an instance of the class or interface declaring the
339: * underlying field (or a subclass or implementor
340: * thereof), or if the field value cannot be
341: * converted to the type <code>long</code> by a
342: * widening conversion.
343: * @exception NullPointerException if the specified object is null
344: * and the field is an instance field.
345: * @exception ExceptionInInitializerError if the initialization provoked
346: * by this method fails.
347: * @see Field#get
348: */
349: public native long getLong(Object obj)
350: throws IllegalArgumentException, IllegalAccessException;
351:
352: /**
353: * Gets the value of a static or instance field of type
354: * <code>float</code> or of another primitive type convertible to
355: * type <code>float</code> via a widening conversion.
356: *
357: * @param obj the object to extract the <code>float</code> value
358: * from
359: * @return the value of the field converted to type <code>float</code>
360: *
361: * @exception IllegalAccessException if the underlying field
362: * is inaccessible.
363: * @exception IllegalArgumentException if the specified object is not
364: * an instance of the class or interface declaring the
365: * underlying field (or a subclass or implementor
366: * thereof), or if the field value cannot be
367: * converted to the type <code>float</code> by a
368: * widening conversion.
369: * @exception NullPointerException if the specified object is null
370: * and the field is an instance field.
371: * @exception ExceptionInInitializerError if the initialization provoked
372: * by this method fails.
373: * @see Field#get
374: */
375: public native float getFloat(Object obj)
376: throws IllegalArgumentException, IllegalAccessException;
377:
378: /**
379: * Gets the value of a static or instance field of type
380: * <code>double</code> or of another primitive type convertible to
381: * type <code>double</code> via a widening conversion.
382: *
383: * @param obj the object to extract the <code>double</code> value
384: * from
385: * @return the value of the field converted to type <code>double</code>
386: *
387: * @exception IllegalAccessException if the underlying field
388: * is inaccessible.
389: * @exception IllegalArgumentException if the specified object is not
390: * an instance of the class or interface declaring the
391: * underlying field (or a subclass or implementor
392: * thereof), or if the field value cannot be
393: * converted to the type <code>double</code> by a
394: * widening conversion.
395: * @exception NullPointerException if the specified object is null
396: * and the field is an instance field.
397: * @exception ExceptionInInitializerError if the initialization provoked
398: * by this method fails.
399: * @see Field#get
400: */
401: public native double getDouble(Object obj)
402: throws IllegalArgumentException, IllegalAccessException;
403:
404: /**
405: * Sets the field represented by this <code>Field</code> object on the
406: * specified object argument to the specified new value. The new
407: * value is automatically unwrapped if the underlying field has a
408: * primitive type.
409: *
410: * <p>The operation proceeds as follows:
411: *
412: * <p>If the underlying field is static, the <code>obj</code> argument is
413: * ignored; it may be null.
414: *
415: * <p>Otherwise the underlying field is an instance field. If the
416: * specified object argument is null, the method throws a
417: * <code>NullPointerException</code>. If the specified object argument is not
418: * an instance of the class or interface declaring the underlying
419: * field, the method throws an <code>IllegalArgumentException</code>.
420: *
421: * <p>If this <code>Field</code> object enforces Java language access control, and
422: * the underlying field is inaccessible, the method throws an
423: * <code>IllegalAccessException</code>.
424: *
425: * <p>If the underlying field is final, the method throws an
426: * <code>IllegalAccessException</code>.
427: *
428: * <p>If the underlying field is of a primitive type, an unwrapping
429: * conversion is attempted to convert the new value to a value of
430: * a primitive type. If this attempt fails, the method throws an
431: * <code>IllegalArgumentException</code>.
432: *
433: * <p>If, after possible unwrapping, the new value cannot be
434: * converted to the type of the underlying field by an identity or
435: * widening conversion, the method throws an
436: * <code>IllegalArgumentException</code>.
437: *
438: * <p>If the underlying field is static, the class that declared the
439: * field is initialized if it has not already been initialized.
440: *
441: * <p>The field is set to the possibly unwrapped and widened new value.
442: *
443: * <p>If the field is hidden in the type of <code>obj</code>,
444: * the field's value is set according to the preceding rules.
445: *
446: * @param obj the object whose field should be modified
447: * @param value the new value for the field of <code>obj</code>
448: * being modified
449: *
450: * @exception IllegalAccessException if the underlying field
451: * is inaccessible.
452: * @exception IllegalArgumentException if the specified object is not an
453: * instance of the class or interface declaring the underlying
454: * field (or a subclass or implementor thereof),
455: * or if an unwrapping conversion fails.
456: * @exception NullPointerException if the specified object is null
457: * and the field is an instance field.
458: * @exception ExceptionInInitializerError if the initialization provoked
459: * by this method fails.
460: */
461: public native void set(Object obj, Object value)
462: throws IllegalArgumentException, IllegalAccessException;
463:
464: /**
465: * Sets the value of a field as a <code>boolean</code> on the specified object.
466: * This method is equivalent to
467: * <code>set(obj, zObj)</code>,
468: * where <code>zObj</code> is a <code>Boolean</code> object and
469: * <code>zObj.booleanValue() == z</code>.
470: *
471: * @param obj the object whose field should be modified
472: * @param z the new value for the field of <code>obj</code>
473: * being modified
474: *
475: * @exception IllegalAccessException if the underlying field
476: * is inaccessible.
477: * @exception IllegalArgumentException if the specified object is not an
478: * instance of the class or interface declaring the underlying
479: * field (or a subclass or implementor thereof),
480: * or if an unwrapping conversion fails.
481: * @exception NullPointerException if the specified object is null
482: * and the field is an instance field.
483: * @exception ExceptionInInitializerError if the initialization provoked
484: * by this method fails.
485: * @see Field#set
486: */
487: public native void setBoolean(Object obj, boolean z)
488: throws IllegalArgumentException, IllegalAccessException;
489:
490: /**
491: * Sets the value of a field as a <code>byte</code> on the specified object.
492: * This method is equivalent to
493: * <code>set(obj, bObj)</code>,
494: * where <code>bObj</code> is a <code>Byte</code> object and
495: * <code>bObj.byteValue() == b</code>.
496: *
497: * @param obj the object whose field should be modified
498: * @param b the new value for the field of <code>obj</code>
499: * being modified
500: *
501: * @exception IllegalAccessException if the underlying field
502: * is inaccessible.
503: * @exception IllegalArgumentException if the specified object is not an
504: * instance of the class or interface declaring the underlying
505: * field (or a subclass or implementor thereof),
506: * or if an unwrapping conversion fails.
507: * @exception NullPointerException if the specified object is null
508: * and the field is an instance field.
509: * @exception ExceptionInInitializerError if the initialization provoked
510: * by this method fails.
511: * @see Field#set
512: */
513: public native void setByte(Object obj, byte b)
514: throws IllegalArgumentException, IllegalAccessException;
515:
516: /**
517: * Sets the value of a field as a <code>char</code> on the specified object.
518: * This method is equivalent to
519: * <code>set(obj, cObj)</code>,
520: * where <code>cObj</code> is a <code>Character</code> object and
521: * <code>cObj.charValue() == c</code>.
522: *
523: * @param obj the object whose field should be modified
524: * @param c the new value for the field of <code>obj</code>
525: * being modified
526: *
527: * @exception IllegalAccessException if the underlying field
528: * is inaccessible.
529: * @exception IllegalArgumentException if the specified object is not an
530: * instance of the class or interface declaring the underlying
531: * field (or a subclass or implementor thereof),
532: * or if an unwrapping conversion fails.
533: * @exception NullPointerException if the specified object is null
534: * and the field is an instance field.
535: * @exception ExceptionInInitializerError if the initialization provoked
536: * by this method fails.
537: * @see Field#set
538: */
539: public native void setChar(Object obj, char c)
540: throws IllegalArgumentException, IllegalAccessException;
541:
542: /**
543: * Sets the value of a field as a <code>short</code> on the specified object.
544: * This method is equivalent to
545: * <code>set(obj, sObj)</code>,
546: * where <code>sObj</code> is a <code>Short</code> object and
547: * <code>sObj.shortValue() == s</code>.
548: *
549: * @param obj the object whose field should be modified
550: * @param s the new value for the field of <code>obj</code>
551: * being modified
552: *
553: * @exception IllegalAccessException if the underlying field
554: * is inaccessible.
555: * @exception IllegalArgumentException if the specified object is not an
556: * instance of the class or interface declaring the underlying
557: * field (or a subclass or implementor thereof),
558: * or if an unwrapping conversion fails.
559: * @exception NullPointerException if the specified object is null
560: * and the field is an instance field.
561: * @exception ExceptionInInitializerError if the initialization provoked
562: * by this method fails.
563: * @see Field#set
564: */
565: public native void setShort(Object obj, short s)
566: throws IllegalArgumentException, IllegalAccessException;
567:
568: /**
569: * Sets the value of a field as an <code>int</code> on the specified object.
570: * This method is equivalent to
571: * <code>set(obj, iObj)</code>,
572: * where <code>iObj</code> is a <code>Integer</code> object and
573: * <code>iObj.intValue() == i</code>.
574: *
575: * @param obj the object whose field should be modified
576: * @param i the new value for the field of <code>obj</code>
577: * being modified
578: *
579: * @exception IllegalAccessException if the underlying field
580: * is inaccessible.
581: * @exception IllegalArgumentException if the specified object is not an
582: * instance of the class or interface declaring the underlying
583: * field (or a subclass or implementor thereof),
584: * or if an unwrapping conversion fails.
585: * @exception NullPointerException if the specified object is null
586: * and the field is an instance field.
587: * @exception ExceptionInInitializerError if the initialization provoked
588: * by this method fails.
589: * @see Field#set
590: */
591: public native void setInt(Object obj, int i)
592: throws IllegalArgumentException, IllegalAccessException;
593:
594: /**
595: * Sets the value of a field as a <code>long</code> on the specified object.
596: * This method is equivalent to
597: * <code>set(obj, lObj)</code>,
598: * where <code>lObj</code> is a <code>Long</code> object and
599: * <code>lObj.longValue() == l</code>.
600: *
601: * @param obj the object whose field should be modified
602: * @param l the new value for the field of <code>obj</code>
603: * being modified
604: *
605: * @exception IllegalAccessException if the underlying field
606: * is inaccessible.
607: * @exception IllegalArgumentException if the specified object is not an
608: * instance of the class or interface declaring the underlying
609: * field (or a subclass or implementor thereof),
610: * or if an unwrapping conversion fails.
611: * @exception NullPointerException if the specified object is null
612: * and the field is an instance field.
613: * @exception ExceptionInInitializerError if the initialization provoked
614: * by this method fails.
615: * @see Field#set
616: */
617: public native void setLong(Object obj, long l)
618: throws IllegalArgumentException, IllegalAccessException;
619:
620: /**
621: * Sets the value of a field as a <code>float</code> on the specified object.
622: * This method is equivalent to
623: * <code>set(obj, fObj)</code>,
624: * where <code>fObj</code> is a <code>Float</code> object and
625: * <code>fObj.floatValue() == f</code>.
626: *
627: * @param obj the object whose field should be modified
628: * @param f the new value for the field of <code>obj</code>
629: * being modified
630: *
631: * @exception IllegalAccessException if the underlying field
632: * is inaccessible.
633: * @exception IllegalArgumentException if the specified object is not an
634: * instance of the class or interface declaring the underlying
635: * field (or a subclass or implementor thereof),
636: * or if an unwrapping conversion fails.
637: * @exception NullPointerException if the specified object is null
638: * and the field is an instance field.
639: * @exception ExceptionInInitializerError if the initialization provoked
640: * by this method fails.
641: * @see Field#set
642: */
643: public native void setFloat(Object obj, float f)
644: throws IllegalArgumentException, IllegalAccessException;
645:
646: /**
647: * Sets the value of a field as a <code>double</code> on the specified object.
648: * This method is equivalent to
649: * <code>set(obj, dObj)</code>,
650: * where <code>dObj</code> is a <code>Double</code> object and
651: * <code>dObj.doubleValue() == d</code>.
652: *
653: * @param obj the object whose field should be modified
654: * @param d the new value for the field of <code>obj</code>
655: * being modified
656: *
657: * @exception IllegalAccessException if the underlying field
658: * is inaccessible.
659: * @exception IllegalArgumentException if the specified object is not an
660: * instance of the class or interface declaring the underlying
661: * field (or a subclass or implementor thereof),
662: * or if an unwrapping conversion fails.
663: * @exception NullPointerException if the specified object is null
664: * and the field is an instance field.
665: * @exception ExceptionInInitializerError if the initialization provoked
666: * by this method fails.
667: * @see Field#set
668: */
669: public native void setDouble(Object obj, double d)
670: throws IllegalArgumentException, IllegalAccessException;
671:
672: /*
673: * Utility routine to paper over array type names
674: */
675: static String getTypeName(Class type) {
676: if (type.isArray()) {
677: try {
678: Class cl = type;
679: int dimensions = 0;
680: while (cl.isArray()) {
681: dimensions++;
682: cl = cl.getComponentType();
683: }
684: StringBuffer sb = new StringBuffer();
685: sb.append(cl.getName());
686: for (int i = 0; i < dimensions; i++) {
687: sb.append("[]");
688: }
689: return sb.toString();
690: } catch (Throwable e) { /*FALLTHRU*/
691: }
692: }
693: return type.getName();
694: }
695:
696: }
|