001: /*
002: * JFox - The most lightweight Java EE Application Server!
003: * more details please visit http://www.huihoo.org/jfox or http://www.jfox.org.cn.
004: *
005: * JFox is licenced and re-distributable under GNU LGPL.
006: */
007: package org.jfox.util;
008:
009: import java.lang.reflect.Array;
010: import java.lang.reflect.Constructor;
011: import java.lang.reflect.Field;
012: import java.lang.reflect.InvocationTargetException;
013: import java.lang.reflect.Method;
014: import java.util.ArrayList;
015: import java.util.Arrays;
016: import java.util.HashMap;
017: import java.util.List;
018: import java.util.Map;
019: import java.util.StringTokenizer;
020:
021: /**
022: *
023: * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
024: */
025:
026: public class ClassUtils {
027:
028: public static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
029:
030: public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
031:
032: private static Map<String, Class> primitiveStringToClass = new HashMap<String, Class>();
033:
034: static {
035: primitiveStringToClass.put(boolean.class.getName(),
036: Boolean.class);
037: primitiveStringToClass.put(byte.class.getName(), Byte.class);
038: primitiveStringToClass.put(char.class.getName(),
039: Character.class);
040: primitiveStringToClass.put(short.class.getName(), Short.class);
041: primitiveStringToClass.put(int.class.getName(), Integer.class);
042: primitiveStringToClass.put(long.class.getName(), Long.class);
043: primitiveStringToClass
044: .put(double.class.getName(), Double.class);
045: primitiveStringToClass.put(float.class.getName(), Float.class);
046: }
047:
048: private ClassUtils() {
049: }
050:
051: public static Class[] getAllSuperclasses(Class cls) {
052: if (cls == null) {
053: return new Class[0];
054: }
055: List<Class> classList = new ArrayList<Class>();
056: Class super Class = cls;
057: while (super Class != null && !Object.class.equals(super Class)
058: && !Class.class.equals(super Class)) { // java.lang.Object �算为超类
059: classList.add(super Class);
060: super Class = super Class.getSuperclass();
061: }
062: return classList.toArray(new Class[classList.size()]);
063: }
064:
065: public static Class[] getAllInterfaces(Class clazz) {
066: if (clazz == null) {
067: return new Class[0];
068: }
069: List<Class> classList = new ArrayList<Class>();
070: while (clazz != null) {
071: Class[] interfaces = clazz.getInterfaces();
072: for (Class interf : interfaces) {
073: if (!classList.contains(interf)) {
074: classList.add(interf);
075: }
076: Class[] super Interfaces = getAllInterfaces(interf);
077: for (Class super Intf : super Interfaces) {
078: if (!classList.contains(super Intf)) {
079: classList.add(super Intf);
080: }
081: }
082: }
083: clazz = clazz.getSuperclass();
084: }
085: return classList.toArray(new Class[classList.size()]);
086: }
087:
088: public static boolean isAssignable(Class clazz, Class toClass) {
089: if (clazz == null || toClass == null) {
090: return false;
091: }
092: if (clazz.equals(toClass)) {
093: return true;
094: }
095:
096: Class newClazz = clazz;
097: Class newToClass = toClass;
098: if (clazz.isPrimitive()) {
099: newClazz = primitiveStringToClass.get(clazz.getName());
100: }
101: if (toClass.isPrimitive()) {
102: newToClass = primitiveStringToClass.get(toClass.getName());
103: }
104: return newToClass.isAssignableFrom(newClazz);
105: }
106:
107: public static boolean isAssignable(Class[] classArray,
108: Class[] toClassArray) {
109: if (classArray == null || toClassArray == null) {
110: return false;
111: }
112: if (classArray.length != toClassArray.length) {
113: return false;
114: }
115:
116: for (int i = 0; i < classArray.length; i++) {
117: if (!isAssignable(classArray[i], toClassArray[i])) {
118: return false;
119: }
120: }
121: return true;
122: }
123:
124: /**
125: * if is primitive class, get it's concrete class object else use reflect
126: * with a string paramter constructor
127: *
128: * @param clazz class
129: * @param value value
130: * @return Object
131: * @throws NoSuchMethodException e
132: * @throws InstantiationException e
133: * @throws IllegalAccessException e
134: * @throws java.lang.reflect.InvocationTargetException e
135: */
136: public static <T> T newObject(Class<T> clazz, String value)
137: throws NoSuchMethodException, InstantiationException,
138: IllegalAccessException, InvocationTargetException {
139: Object obj;
140: if (clazz.isArray()) { // 数组
141: Class<?> elementClass = clazz.getComponentType();
142: StringTokenizer st = new StringTokenizer(value);
143: int length = st.countTokens();
144: Object array = Array.newInstance(elementClass, length);
145: for (int i = 0; st.hasMoreTokens(); i++) {
146: Object param = newObject(elementClass, st.nextToken());
147: Array.set(array, i, param);
148: }
149: obj = array;
150: } else {
151: Class<T> clz = clazz;
152: if (clazz.isPrimitive()) {
153: clz = primitiveStringToClass.get(clazz.getName());
154: }
155: if (clz.equals(String.class)) {
156: obj = value;
157: } else {
158: // 使用 String æž„é€ å™¨
159: obj = clz.getConstructor(String.class).newInstance(
160: value);
161: }
162: }
163: return (T) obj;
164: }
165:
166: public static boolean isInnerClass(Class cls) {
167: return (cls == null) ? false : (cls.getName().indexOf(
168: INNER_CLASS_SEPARATOR_CHAR) >= 0);
169: }
170:
171: public static Class getClass(String className)
172: throws ClassNotFoundException {
173: Class clazz;
174: if (isPrimitiveClass(className)) {
175: return primitiveStringToClass.get(className);
176: } else {
177: clazz = Class.forName(className);
178: }
179: return clazz;
180: }
181:
182: public static Class getClass(ClassLoader classLoader,
183: String className) throws ClassNotFoundException {
184: Class clazz;
185: if (isPrimitiveClass(className)) {
186: return primitiveStringToClass.get(className);
187: } else {
188: clazz = classLoader.loadClass(className);
189: }
190: return clazz;
191: }
192:
193: /**
194: * å?¯ä»¥å¤„ç?†ä¼ 入的å?‚数为定义å?‚æ•°çš„å?类的情况
195: *
196: * @param clazz class
197: * @param methodName method name
198: * @param expectedTypes parameter types
199: * @throws NoSuchMethodException if not found such method
200: */
201: public static Method getCompatibleMethod(Class clazz,
202: String methodName, Class[] expectedTypes)
203: throws NoSuchMethodException {
204: Method theMethod = null;
205: try {
206: theMethod = clazz.getMethod(methodName, expectedTypes);
207: } catch (NoSuchMethodException e) {
208: Method[] methods = clazz.getMethods();
209: for (Method method : methods) {
210: if (method.getName().equals(methodName)) {
211: if (isAssignable(expectedTypes, method
212: .getParameterTypes())) {
213: if (theMethod == null) {
214: theMethod = method;
215: } else {
216: // 找到最适�的方法
217: if (isAssignable(
218: method.getParameterTypes(),
219: theMethod.getParameterTypes())) {
220: theMethod = method;
221: }
222: }
223: }
224: }
225: }
226: if (theMethod == null)
227: throw e;
228: }
229: return theMethod;
230: }
231:
232: public static <T> Constructor<T> getConstructor(Class<T> clazz,
233: Class[] expectedTypes) throws NoSuchMethodException {
234: Constructor<T> constructor = null;
235: if (expectedTypes == null) {
236: expectedTypes = EMPTY_CLASS_ARRAY;
237: }
238: try {
239: constructor = clazz.getConstructor(expectedTypes);
240: } catch (NoSuchMethodException e) {
241: Constructor[] constructors = clazz.getConstructors();
242: for (Constructor constr : constructors) {
243: if (isAssignable(expectedTypes, constr
244: .getParameterTypes())) {
245: if (constructor == null) {
246: constructor = (Constructor<T>) constr;
247: } else {
248: if (isAssignable(constr.getParameterTypes(),
249: constructor.getParameterTypes())) {
250: constructor = (Constructor<T>) constr;
251: }
252: }
253: }
254: }
255: if (constructor == null)
256: throw e;
257: }
258: return constructor;
259: }
260:
261: /**
262: * å?–得该类申明的Field,包括在其超类ä¸ç”³æ˜Ž
263: *
264: * @param clazz class
265: * @param name field name
266: * @throws NoSuchFieldException if not found such field
267: */
268: public static Field getDecaredField(Class clazz, String name)
269: throws NoSuchFieldException {
270: Field field = null;
271: Class[] super Classes = getAllSuperclasses(clazz);
272: for (Class super Class : super Classes) {
273: try {
274: field = super Class.getDeclaredField(name);
275: break;
276: } catch (NoSuchFieldException e) {
277: // ignore
278: }
279: }
280: if (field == null) {
281: throw new NoSuchFieldException("No such declared field "
282: + name + " in " + clazz);
283: }
284: return field;
285: }
286:
287: /**
288: * �得clz 所有的 Field
289: *
290: * @param clazz class
291: */
292: public static Field[] getAllDecaredFields(Class clazz) {
293: List<Field> fields = new ArrayList<Field>();
294: // fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
295:
296: Class[] super Classes = getAllSuperclasses(clazz);
297: for (Class super Class : super Classes) {
298: fields
299: .addAll(Arrays.asList(super Class
300: .getDeclaredFields()));
301: }
302: return fields.toArray(new Field[fields.size()]);
303: }
304:
305: /**
306: * get the narrowest class from the given types
307: *
308: * @param types class array
309: */
310: public static Class getNarrowestClass(Class[] types) {
311: if (types == null || types.length == 0) {
312: throw new IllegalArgumentException(
313: "types is null or empty.");
314: }
315: Class clz = types[0];
316: for (int i = 1; i < types.length; i++) {
317: if (clz.isAssignableFrom(types[i])) {
318: clz = types[i];
319: } else if (!types[i].isAssignableFrom(clz)) {
320: throw new IllegalArgumentException(types[i].getName()
321: + " not has assignable relation with "
322: + clz.getName());
323: }
324: }
325:
326: return clz;
327: }
328:
329: public static boolean isPrimitiveClass(String primitiveClassName) {
330: return primitiveStringToClass.containsKey(primitiveClassName);
331: }
332:
333: public static boolean isPrimitiveClass(Class primitiveClass) {
334: return primitiveStringToClass.containsKey(primitiveClass
335: .getName());
336: }
337:
338: public static boolean isPrimitiveWrapperClass(
339: Class primitiveWrapperClass) {
340: return primitiveStringToClass.values().contains(
341: primitiveWrapperClass);
342: }
343:
344: public static void main(String[] args) throws Exception {
345: String[] strArray = newObject((new String[0]).getClass(),
346: "1 2 3");
347: System.out.println(Arrays.toString(strArray));
348: System.out.println(newObject(boolean.class, "true"));
349: System.out.println(Arrays
350: .toString(getAllSuperclasses(ClassUtils.class)));
351: }
352:
353: }
|