Java tutorial
/* * Copyright 2002-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.beans.Introspector; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.Assert; import sun.rmi.runtime.Log; /** * Utility to work with Java 5 generic type parameters. * Mainly for internal use within the framework. * * @author Ramnivas Laddad * @author Juergen Hoeller * @since 2.0.7 */ public abstract class TypeUtils { /** * Check if the right-hand side type may be assigned to the left-hand side * type following the Java generics rules. * @param lhsType the target type * @param rhsType the value type that should be assigned to the target type * @return true if rhs is assignable to lhs */ public static boolean isAssignable(Type lhsType, Type rhsType) { if (lhsType.equals(rhsType)) { return true; } if (lhsType instanceof Class && rhsType instanceof Class) { return ClassUtils.isAssignable((Class) lhsType, (Class) rhsType); } if (lhsType instanceof ParameterizedType && rhsType instanceof ParameterizedType) { return isAssignable((ParameterizedType) lhsType, (ParameterizedType) rhsType); } if (lhsType instanceof WildcardType) { return isAssignable((WildcardType) lhsType, rhsType); } return false; } private static boolean isAssignable(ParameterizedType lhsType, ParameterizedType rhsType) { if (lhsType.equals(rhsType)) { return true; } Type[] lhsTypeArguments = lhsType.getActualTypeArguments(); Type[] rhsTypeArguments = rhsType.getActualTypeArguments(); if (lhsTypeArguments.length != rhsTypeArguments.length) { return false; } for (int size = lhsTypeArguments.length, i = 0; i < size; ++i) { Type lhsArg = lhsTypeArguments[i]; Type rhsArg = rhsTypeArguments[i]; if (!lhsArg.equals(rhsArg) && !(lhsArg instanceof WildcardType && isAssignable((WildcardType) lhsArg, rhsArg))) { return false; } } return true; } private static boolean isAssignable(WildcardType lhsType, Type rhsType) { Type[] upperBounds = lhsType.getUpperBounds(); Type[] lowerBounds = lhsType.getLowerBounds(); for (int size = upperBounds.length, i = 0; i < size; ++i) { if (!isAssignable(upperBounds[i], rhsType)) { return false; } } for (int size = lowerBounds.length, i = 0; i < size; ++i) { if (!isAssignable(rhsType, lowerBounds[i])) { return false; } } return true; } } /* * Copyright 2002-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Miscellaneous class utility methods. Mainly for internal use within the * framework; consider Jakarta's Commons Lang for a more comprehensive suite * of class utilities. * * @author Keith Donald * @author Rob Harrop * @author Juergen Hoeller * @since 1.1 * @see TypeUtils * @see ReflectionUtils */ abstract class ClassUtils { /** Suffix for array class names: "[]" */ public static final String ARRAY_SUFFIX = "[]"; /** Prefix for internal array class names: "[L" */ private static final String INTERNAL_ARRAY_PREFIX = "[L"; /** The package separator character '.' */ private static final char PACKAGE_SEPARATOR = '.'; /** The inner class separator character '$' */ private static final char INNER_CLASS_SEPARATOR = '$'; /** The CGLIB class separator character "$$" */ public static final String CGLIB_CLASS_SEPARATOR = "$$"; /** The ".class" file suffix */ public static final String CLASS_FILE_SUFFIX = ".class"; /** * Map with primitive wrapper type as key and corresponding primitive * type as value, for example: Integer.class -> int.class. */ private static final Map primitiveWrapperTypeMap = new HashMap(8); /** * Map with primitive type name as key and corresponding primitive * type as value, for example: "int" -> "int.class". */ private static final Map primitiveTypeNameMap = new HashMap(16); static { primitiveWrapperTypeMap.put(Boolean.class, boolean.class); primitiveWrapperTypeMap.put(Byte.class, byte.class); primitiveWrapperTypeMap.put(Character.class, char.class); primitiveWrapperTypeMap.put(Double.class, double.class); primitiveWrapperTypeMap.put(Float.class, float.class); primitiveWrapperTypeMap.put(Integer.class, int.class); primitiveWrapperTypeMap.put(Long.class, long.class); primitiveWrapperTypeMap.put(Short.class, short.class); Set primitiveTypeNames = new HashSet(16); primitiveTypeNames.addAll(primitiveWrapperTypeMap.values()); primitiveTypeNames.addAll(Arrays.asList(new Class[] { boolean[].class, byte[].class, char[].class, double[].class, float[].class, int[].class, long[].class, short[].class })); for (Iterator it = primitiveTypeNames.iterator(); it.hasNext();) { Class primitiveClass = (Class) it.next(); primitiveTypeNameMap.put(primitiveClass.getName(), primitiveClass); } } /** * Check if the right-hand side type may be assigned to the left-hand side * type, assuming setting by reflection. Considers primitive wrapper * classes as assignable to the corresponding primitive types. * @param lhsType the target type * @param rhsType the value type that should be assigned to the target type * @return if the target type is assignable from the value type * @see TypeUtils#isAssignable */ public static boolean isAssignable(Class lhsType, Class rhsType) { return (lhsType.isAssignableFrom(rhsType) || lhsType.equals(primitiveWrapperTypeMap.get(rhsType))); } }