KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfox > ioc > util > Classes


1 /* JFox, the OpenSource J2EE Application Server
2  *
3  * Distributable under GNU LGPL license by gun.org
4  * more details please visit http://www.huihoo.org/jfox
5  */

6
7 package org.jfox.ioc.util;
8
9 import java.lang.reflect.Array JavaDoc;
10 import java.lang.reflect.Constructor JavaDoc;
11 import java.lang.reflect.InvocationTargetException JavaDoc;
12 import java.lang.reflect.Method JavaDoc;
13 import java.lang.reflect.Field JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.Arrays JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.StringTokenizer JavaDoc;
21
22 /**
23  * @author <a HREF="mailto:young_yy@hotmail.com">Young Yang</a>
24  */

25
26 public class Classes {
27
28     public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
29     public final static Class JavaDoc[] EMPTY_CLASS_ARRAY = new Class JavaDoc[0];
30
31     /**
32      * <p>The inner class separator String: <code>"$"</code>.</p>
33      */

34     public static final String JavaDoc INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
35
36     /**
37      * Maps primitive <code>Class</code>es to their corresponding wrapper <code>Class</code>.
38      */

39     private static Map JavaDoc primitiveClassToWrapper = new HashMap JavaDoc();
40
41     static {
42         primitiveClassToWrapper.put(Boolean.TYPE, Boolean JavaDoc.class);
43         primitiveClassToWrapper.put(Byte.TYPE, Byte JavaDoc.class);
44         primitiveClassToWrapper.put(Character.TYPE, Character JavaDoc.class);
45         primitiveClassToWrapper.put(Short.TYPE, Short JavaDoc.class);
46         primitiveClassToWrapper.put(Integer.TYPE, Integer JavaDoc.class);
47         primitiveClassToWrapper.put(Long.TYPE, Long JavaDoc.class);
48         primitiveClassToWrapper.put(Double.TYPE, Double JavaDoc.class);
49         primitiveClassToWrapper.put(Float.TYPE, Float JavaDoc.class);
50     }
51
52     private static Map JavaDoc primitiveStringToClass = new HashMap JavaDoc();
53
54     static {
55         primitiveStringToClass.put(Boolean.TYPE.getName(), Boolean.TYPE);
56         primitiveStringToClass.put(Byte.TYPE.getName(), Byte.TYPE);
57         primitiveStringToClass.put(Character.TYPE.getName(), Character.TYPE);
58         primitiveStringToClass.put(Short.TYPE.getName(), Short.TYPE);
59         primitiveStringToClass.put(Integer.TYPE.getName(), Integer.TYPE);
60         primitiveStringToClass.put(Long.TYPE.getName(), Long.TYPE);
61         primitiveStringToClass.put(Double.TYPE.getName(), Double.TYPE);
62         primitiveStringToClass.put(Float.TYPE.getName(), Float.TYPE);
63     }
64
65     /**
66      * <p>ClassUtils instances should NOT be constructed in standard programming.
67      * Instead, the class should be used as
68      * <code>ClassUtils.getShortClassName(cls)</code>.</p>
69      * <p/>
70      * <p>This constructor is public to permit tools that require a JavaBean
71      * instance to operate.</p>
72      */

73     private Classes() {
74     }
75
76     /**
77      * <p>Gets a <code>List</code> of superclasses for the given class.</p>
78      *
79      * @param cls the class to look up, may be <code>null</code>
80      * @return the <code>List</code> of superclasses in order going up from this one
81      * <code>null</code> if null input
82      */

83     public static List JavaDoc getAllSuperclasses(Class JavaDoc cls) {
84         if(cls == null) {
85             return null;
86         }
87         List JavaDoc classes = new ArrayList JavaDoc();
88         Class JavaDoc superclass = cls.getSuperclass();
89         while(superclass != null) {
90             classes.add(superclass);
91             superclass = superclass.getSuperclass();
92         }
93         return classes;
94     }
95
96     /**
97      * <p>Gets a <code>List</code> of all interfaces implemented by the given
98      * class and its superclasses.</p>
99      * <p/>
100      * <p>The order is determined by looking through each interface in turn as
101      * declared in the source file and following its hierarchy up. Then each
102      * superclass is considered in the same way. Later duplicates are ignored,
103      * so the order is maintained.</p>
104      *
105      * @param cls the class to look up, may be <code>null</code>
106      * @return the <code>List</code> of interfaces in order,
107      * <code>null</code> if null input
108      */

109     public static List JavaDoc<Class JavaDoc> getAllInterfaces(Class JavaDoc cls) {
110         if(cls == null) {
111             return null;
112         }
113         List JavaDoc<Class JavaDoc> list = new ArrayList JavaDoc<Class JavaDoc>();
114         while(cls != null) {
115             Class JavaDoc[] interfaces = cls.getInterfaces();
116             for(int i = 0; i < interfaces.length; i++) {
117                 if(list.contains(interfaces[i]) == false) {
118                     list.add(interfaces[i]);
119                 }
120                 List JavaDoc superInterfaces = getAllInterfaces(interfaces[i]);
121                 for(Iterator JavaDoc it = superInterfaces.iterator(); it.hasNext();) {
122                     Class JavaDoc intface = (Class JavaDoc) it.next();
123                     if(list.contains(intface) == false) {
124                         list.add(intface);
125                     }
126                 }
127             }
128             cls = cls.getSuperclass();
129         }
130         return list;
131     }
132
133
134     /**
135      * <p>Checks if an array of Classes can be assigned to another array of Classes.</p>
136      * <p/>
137      * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each
138      * Class pair in the input arrays. It can be used to check if a set of arguments
139      * (the first parameter) are suitably compatible with a set of method parameter types
140      * (the second parameter).</p>
141      * <p/>
142      * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
143      * method takes into account widenings of primitive classes and
144      * <code>null</code>s.</p>
145      * <p/>
146      * <p>Primitive widenings allow an int to be assigned to a <code>long</code>,
147      * <code>float</code> or <code>double</code>. This method returns the correct
148      * result for these cases.</p>
149      * <p/>
150      * <p><code>Null</code> may be assigned to any reference type. This method will
151      * return <code>true</code> if <code>null</code> is passed in and the toClass is
152      * non-primitive.</p>
153      * <p/>
154      * <p>Specifically, this method tests whether the type represented by the
155      * specified <code>Class</code> parameter can be converted to the type
156      * represented by this <code>Class</code> object via an identity conversion
157      * widening primitive or widening reference conversion. See
158      * <em><a HREF="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
159      * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
160      *
161      * @param classArray the array of Classes to check, may be <code>null</code>
162      * @param toClassArray the array of Classes to try to assign into, may be <code>null</code>
163      * @return <code>true</code> if assignment possible
164      */

165     public static boolean isAssignable(Class JavaDoc[] classArray, Class JavaDoc[] toClassArray) {
166         if(classArray.length != toClassArray.length) {
167             return false;
168         }
169         if(classArray == null) {
170             classArray = EMPTY_CLASS_ARRAY;
171         }
172         if(toClassArray == null) {
173             toClassArray = EMPTY_CLASS_ARRAY;
174         }
175         for(int i = 0; i < classArray.length; i++) {
176             if(isAssignable(classArray[i], toClassArray[i]) == false) {
177                 return false;
178             }
179         }
180         return true;
181     }
182
183     /**
184      * <p>Checks if one <code>Class</code> can be assigned to a variable of
185      * another <code>Class</code>.</p>
186      * <p/>
187      * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
188      * this method takes into account widenings of primitive classes and
189      * <code>null</code>s.</p>
190      * <p/>
191      * <p>Primitive widenings allow an int to be assigned to a long, float or
192      * double. This method returns the correct result for these cases.</p>
193      * <p/>
194      * <p><code>Null</code> may be assigned to any reference type. This method
195      * will return <code>true</code> if <code>null</code> is passed in and the
196      * toClass is non-primitive.</p>
197      * <p/>
198      * <p>Specifically, this method tests whether the type represented by the
199      * specified <code>Class</code> parameter can be converted to the type
200      * represented by this <code>Class</code> object via an identity conversion
201      * widening primitive or widening reference conversion. See
202      * <em><a HREF="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
203      * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
204      *
205      * @param cls the Class to check, may be null
206      * @param toClass the Class to try to assign into, returns false if null
207      * @return <code>true</code> if assignment possible
208      */

209     public static boolean isAssignable(Class JavaDoc cls, Class JavaDoc toClass) {
210         if(toClass == null) {
211             return false;
212         }
213         // have to check for null, as isAssignableFrom doesn't
214
if(cls == null) {
215             return !(toClass.isPrimitive());
216         }
217         if(cls.equals(toClass)) {
218             return true;
219         }
220         if(cls.isPrimitive()) {
221             if(toClass.isPrimitive() == false) {
222                 return false;
223             }
224             if(Integer.TYPE.equals(cls)) {
225                 return Long.TYPE.equals(toClass)
226                         || Float.TYPE.equals(toClass)
227                         || Double.TYPE.equals(toClass);
228             }
229             if(Long.TYPE.equals(cls)) {
230                 return Float.TYPE.equals(toClass)
231                         || Double.TYPE.equals(toClass);
232             }
233             if(Boolean.TYPE.equals(cls)) {
234                 return false;
235             }
236             if(Double.TYPE.equals(cls)) {
237                 return false;
238             }
239             if(Float.TYPE.equals(cls)) {
240                 return Double.TYPE.equals(toClass);
241             }
242             if(Character.TYPE.equals(cls)) {
243                 return Integer.TYPE.equals(toClass)
244                         || Long.TYPE.equals(toClass)
245                         || Float.TYPE.equals(toClass)
246                         || Double.TYPE.equals(toClass);
247             }
248             if(Short.TYPE.equals(cls)) {
249                 return Integer.TYPE.equals(toClass)
250                         || Long.TYPE.equals(toClass)
251                         || Float.TYPE.equals(toClass)
252                         || Double.TYPE.equals(toClass);
253             }
254             if(Byte.TYPE.equals(cls)) {
255                 return Short.TYPE.equals(toClass)
256                         || Integer.TYPE.equals(toClass)
257                         || Long.TYPE.equals(toClass)
258                         || Float.TYPE.equals(toClass)
259                         || Double.TYPE.equals(toClass);
260             }
261             // should never get here
262
return false;
263         }
264         return toClass.isAssignableFrom(cls);
265     }
266
267     /**
268      * <p>Converts the specified primitive Class object to its corresponding
269      * wrapper Class object.</p>
270      *
271      * @param cls the class to convert, may be null
272      * @return the wrapper class for <code>cls</code> or <code>cls</code> if
273      * <code>cls</code> is not a primitive. <code>null</code> if null input.
274      */

275     public static Class JavaDoc primitiveToWrapper(Class JavaDoc cls) {
276         Class JavaDoc convertedClass = cls;
277         if(cls != null && cls.isPrimitive()) {
278             convertedClass = (Class JavaDoc) primitiveClassToWrapper.get(cls);
279         }
280         return convertedClass;
281     }
282
283     /**
284      * if is primitive class, get it's concrete class object
285      * else use reflect with a string paramter constructor
286      *
287      * @param clz
288      * @param value
289      * @return
290      */

291     public static Object JavaDoc newObject(Class JavaDoc clz, String JavaDoc value) throws NoSuchMethodException JavaDoc,
292                                                                    InstantiationException JavaDoc ,
293                                                                    IllegalAccessException JavaDoc,
294                                                                    InvocationTargetException JavaDoc {
295         Object JavaDoc obj = value;
296         if(clz.isPrimitive()) {
297             if(clz.equals(boolean.class) || clz.equals(Boolean JavaDoc.class)) {
298                 obj = Boolean.valueOf(value);
299             }
300             else if(clz.equals(char.class) || clz.equals(Character JavaDoc.class)) {
301                 obj = new Character JavaDoc(value.charAt(0));
302             }
303             else if(clz.equals(byte.class) || clz.equals(Byte JavaDoc.class)) {
304                 obj = Byte.valueOf(value);
305             }
306             else if(clz.equals(short.class) || clz.equals(Short JavaDoc.class)) {
307                 obj = Short.valueOf(value);
308             }
309             else if(clz.equals(int.class) || clz.equals(Integer JavaDoc.class)) {
310                 obj = Integer.valueOf(value);
311             }
312             else if(clz.equals(long.class) || clz.equals(Long JavaDoc.class)) {
313                 obj = Long.valueOf(value);
314             }
315             else if(clz.equals(float.class) || clz.equals(Float JavaDoc.class)) {
316                 obj = Float.valueOf(value);
317             }
318             else if(clz.equals(double.class) || clz.equals(Double JavaDoc.class)) {
319                 obj = Double.valueOf(value);
320             }
321
322         }
323         else if(clz.isArray()) {
324             Class JavaDoc originClass = clz.getComponentType();
325             StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(value);
326             int length = st.countTokens();
327             Object JavaDoc array = Array.newInstance(originClass, length);
328             for(int i = 0; st.hasMoreTokens(); i++) {
329                 Object JavaDoc param = newObject(originClass, st.nextToken());
330                 Array.set(array, i, param);
331             }
332             obj = array;
333         }
334         else {
335            obj = clz.getConstructor(new Class JavaDoc[]{String JavaDoc.class}).newInstance(new Object JavaDoc[]{value});
336         }
337         return obj;
338     }
339
340     /**
341      * <p>Is the specified class an inner class or static nested class.</p>
342      *
343      * @param cls the class to check, may be null
344      * @return <code>true</code> if the class is an inner or static nested class,
345      * false if not or <code>null</code>
346      */

347     public static boolean isInnerClass(Class JavaDoc cls) {
348         if(cls == null) {
349             return false;
350         }
351         return (cls.getName().indexOf(INNER_CLASS_SEPARATOR_CHAR) >= 0);
352     }
353
354     /**
355      * 可以处理传入的参数为定义参数的子类的情况
356      * @param clz
357      * @param methodName
358      * @param expectedTypes
359      * @return
360      * @throws NoSuchMethodException
361      */

362     public static Method JavaDoc getMethod(Class JavaDoc clz, String JavaDoc methodName, Class JavaDoc[] expectedTypes) throws NoSuchMethodException JavaDoc {
363         Method JavaDoc method = null;
364         try {
365             method = clz.getMethod(methodName, expectedTypes);
366         }
367         catch(NoSuchMethodException JavaDoc e) {
368             Method JavaDoc[] methods = clz.getMethods();
369             for(int i = 0; i < methods.length; i++) {
370                 Method JavaDoc _method = methods[i];
371                 if(_method.getName().equals(methodName)) {
372                     if(isAssignable(expectedTypes, _method.getParameterTypes())) {
373                         if(method == null) {
374                             method = _method;
375                         }
376                         else {
377                             // 找到最适合的方法
378
if(Classes.isAssignable(_method.getParameterTypes(), method.getParameterTypes())) {
379                                 method = _method;
380                             }
381                         }
382
383                     }
384                 }
385             }
386             if(method == null) throw e;
387         }
388         return method;
389     }
390
391     public static Constructor JavaDoc getConstructor(Class JavaDoc clz, Class JavaDoc[] expectedTypes) throws NoSuchMethodException JavaDoc {
392         Constructor JavaDoc constructor = null;
393         if(expectedTypes == null) {
394             expectedTypes = Classes.EMPTY_CLASS_ARRAY;
395         }
396         try {
397             constructor = clz.getConstructor(expectedTypes);
398         }
399         catch(NoSuchMethodException JavaDoc e) {
400             Constructor JavaDoc[] constructors = clz.getConstructors();
401             for(int i = 0; i < constructors.length; i++) {
402                 Constructor JavaDoc constr = constructors[i];
403                 if(Classes.isAssignable(expectedTypes, constr.getParameterTypes())) {
404                     if(constructor == null) {
405                         constructor = constr;
406                     }
407                     else {
408                         if(Classes.isAssignable(constr.getParameterTypes(), constructor.getParameterTypes())) {
409                             constructor = constr;
410                         }
411                     }
412                 }
413             }
414             if(constructor == null) throw e;
415         }
416         return constructor;
417     }
418
419     /**
420      * 取得该类申明的Field,包括在其超类中申明
421      *
422      * @param clz 类
423      * @param name 字段名
424      * @return
425      * @throws NoSuchFieldException
426      */

427     public static Field JavaDoc getDecaredField(Class JavaDoc clz, String JavaDoc name) throws NoSuchFieldException JavaDoc {
428         Class JavaDoc superClass = clz;
429         Field JavaDoc field = null;
430         while((field == null) && !superClass.equals(Object JavaDoc.class)) {
431             try {
432                 field = superClass.getDeclaredField(name);
433             }
434             catch(NoSuchFieldException JavaDoc e) {
435
436             }
437             superClass = superClass.getSuperclass();
438         }
439         if(field == null) {
440             throw new NoSuchFieldException JavaDoc("No such field " + name + " in " + clz);
441         }
442         return field;
443     }
444
445     /**
446      * 取得clz 所有的 Field
447      *
448      * @param clz
449      * @return
450      * @throws NoSuchFieldException
451      */

452     public static Field JavaDoc[] getDecaredFields(Class JavaDoc clz) {
453         List JavaDoc<Field JavaDoc> fields = new ArrayList JavaDoc<Field JavaDoc>();
454
455         Class JavaDoc superClass = clz;
456         while(!superClass.equals(Object JavaDoc.class)) {
457             fields.addAll(Arrays.asList(superClass.getDeclaredFields()));
458             superClass = superClass.getSuperclass();
459         }
460         return fields.toArray(new Field JavaDoc[fields.size()]);
461     }
462     
463     /**
464      * get the narrowest class from the types
465      *
466      * @param types
467      * @return
468      */

469     public static Class JavaDoc getNarrowestClass(Class JavaDoc[] types) {
470         if(types == null || types.length == 0) {
471             throw new IllegalArgumentException JavaDoc("types is null or empty.");
472         }
473         Class JavaDoc clz = types[0];
474         for(int i = 1; i < types.length; i++) {
475             if(clz.isAssignableFrom(types[i])) {
476                 clz = types[i];
477             }
478             else if(!types[i].isAssignableFrom(clz)) {
479                 throw new IllegalArgumentException JavaDoc(types[i].getName() + " not has assignable relation with " + clz.getName());
480             }
481         }
482         return clz;
483     }
484
485     public static boolean isPrimitiveClass(String JavaDoc primitiveClassName) {
486         return primitiveStringToClass.containsKey(primitiveClassName);
487     }
488
489     public static Class JavaDoc loadPrimitiveClass(String JavaDoc primitiveClassName) {
490         if(isPrimitiveClass(primitiveClassName)) {
491             return (Class JavaDoc) primitiveStringToClass.get(primitiveClassName);
492         }
493         return null;
494     }
495
496 /* 直接使用 JDK1.5 的 class.getComponentType()
497     public static Class getClassFromArrayClass(Class clz) {
498         if(!clz.isArray()) return clz;
499         // [Ljava.lang.String;
500         String name = clz.getName();
501         String className = name.substring(2, name.length() - 1);
502         Class _clz = null;
503         try {
504             _clz = Thread.currentThread().getContextClassLoader().loadClass(className);
505         }
506         catch(Exception e) {
507             e.printStackTrace();
508         }
509         return _clz;
510     }
511 */

512
513     public static String JavaDoc classNameWithoutPackage(Class JavaDoc objectClass){
514         return classNameWithoutPackage(objectClass.getName());
515
516     }
517
518     public static String JavaDoc classNameWithoutPackage(String JavaDoc fullClassName){
519         return fullClassName.substring(fullClassName.lastIndexOf(".")+1, fullClassName.length());
520     }
521
522     public static List JavaDoc<Method JavaDoc> introspectMethods(Class JavaDoc clz){
523         Method JavaDoc[] _methods = clz.getMethods();
524         return Arrays.asList(_methods);
525     }
526
527     public static void main(String JavaDoc[] args) throws Exception JavaDoc {
528         Object JavaDoc array = newObject(new String JavaDoc[]{}.getClass(), "a b cc ");
529         System.out.println(array);
530     }
531
532 }
533
534
Popular Tags