java变参是通过数组来实现的
Object[] addAll(Object[] array1, Object... array2)和Object[] addAll(Object[] array1, Object[] array2)签名应该一致的。
public class ArrayUtils { // Clone // ----------------------------------------------------------------------- /** * <p> * Shallow clones an array returning a typecast result and handling <code>null</code>. * </p> * * <p> * The objects in the array are not cloned, thus there is no special handling for multi-dimensional arrays. * </p> * * <p> * This method returns <code>null</code> for a <code>null</code> input array. * </p> * * @param array * the array to shallow clone, may be <code>null</code> * @return the cloned array, <code>null</code> if <code>null</code> input */ public static Object[] clone(Object[] array) { if (array == null) { return null; } return array.clone(); } /** * <p> * Adds all the elements of the given arrays into a new array. * </p> * <p> * The new array contains all of the element of <code>array1</code> followed by all of the elements <code>array2</code>. * When an array is returned, it is always a new array. * </p> * * <pre> * ArrayUtils.addAll(null, null) = null * ArrayUtils.addAll(array1, null) = cloned copy of array1 * ArrayUtils.addAll(null, array2) = cloned copy of array2 * ArrayUtils.addAll([], []) = [] * ArrayUtils.addAll([null], [null]) = [null, null] * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"] * </pre> * * @param array1 * the first array whose elements are added to the new array, may be <code>null</code> * @param array2 * the second array whose elements are added to the new array, may be <code>null</code> * @return The new array, <code>null</code> if <code>null</code> array inputs. The type of the new array is the type of the * first array. * @since 2.1 */ public static Object[] addAll(Object[] array1, Object... array2) { if (array1 == null) { return clone(array2); } else if (array2 == null) { return clone(array1); } Object[] joinedArray = (Object[]) Array .newInstance(array1.getClass().getComponentType(), array1.length + array2.length); System.arraycopy(array1, 0, joinedArray, 0, array1.length); System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); return joinedArray; } /** * Swaps the two specified elements in the specified array. * * @param arr * @param i * @param j */ public static void swap(Object[] arr, int i, int j) { Object tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } }
测试变参
public static void main(String[] args) { String[] array = { "22", "66" }; // The argument of type String[] should explicitly be cast to Object[] for the invocation of the varargs method // addAll(Object[], Object...) from type ArrayUtils. It could alternatively be cast to Object for a varargs invocation System.out.println(Arrays.toString(ArrayUtils.addAll(array, new String[] { "2", "6" }))); // Compile warning System.out.println(Arrays.toString(ArrayUtils.addAll(array, "2", "6"))); // OK System.out.println(Arrays.toString(ArrayUtils.addAll(array, (Object[]) new String[] { "2", "6" }))); // OK System.out.println(Arrays.toString(ArrayUtils.addAll(array, (Object) new String[] { "2", "6" })));// java.lang.ArrayStoreException }
自动包装
Object[] addAll(Object[] array1, Object... array2)
--> 传参:Object[] addAll(Object[] array1, Object array2_0, Object array2_1, Object array2_2, ...)
--> 变长参数包装:Object[] array2 = new Object[]{array2_0, array2_1, array2_2};
--> 编译后实际的:Object[] addAll(Object[] array1, Object[] array2)
由于实际函数是Object[] addAll(Object[] array1, Object[] array2),则在变长参数位置直接传递数组时,编译器给出警告。
- 默认的数组直接作为实际函数Object[] addAll(Object[] array1, Object[] array2)的第二参数,
- 消除警告可以添加强制转换,规定是(Object[])和默认方式相同;(Object)则作为变长参数的一项,自动包装为new Object[]{(Object) new String[] { "2", "6" }},变成了二维数组,String型数组不能存储元素String[]的对象(String[] joinedArray; joinedArray[0] = new String[] { "2", "6" }是不正确的),则在第二个System.arraycopy发生存储异常
另外的消除编译警告还可以这样,通过泛型:
public static <T> Object[] addAll(Object[] array1, T... array2) { if (array1 == null) { return clone(array2); } else if (array2 == null) { return clone(array1); } Object[] joinedArray = (Object[]) Array .newInstance(array1.getClass().getComponentType(), array1.length + array2.length); System.arraycopy(array1, 0, joinedArray, 0, array1.length); System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); return joinedArray; }
缺点是编译时如果array2类型不是全部一样,会被检查,如
String[] array = { "22", "66" };
System.out.println(Arrays.toString(ArrayUtils.addAll(array, new Object[] { "2", "6", 2 })));
System.out.println(Arrays.toString(ArrayUtils.addAll(array, "2", "6", 2)));
继续执行,只会得到java.lang.ArrayStoreException。除非第一参数是Object[] array = { "22", "66" };才能即能存储String又能存储Integer(上面的2)
继续改造(版本高的ArrayUtils@github.com或ArrayUtils@grepcode.com貌似更好,但这里和它有点区别,使用两个泛型帮助严格类型检查):
/** * <p> * Shallow clones an array returning a typecast result and handling * {@code null}. * </p> * * <p> * The objects in the array are not cloned, thus there is no special * handling for multi-dimensional arrays. * </p> * * <p> * This method returns {@code null} for a {@code null} input array. * </p> * * @param <T> the component type of the array * @param array the array to shallow clone, may be {@code null} * @return the cloned array, {@code null} if {@code null} input */ public static <T> T[] clone(final T[] array) { if (array == null) { return null; } return array.clone(); } /** * <p> * Adds all the elements of the given arrays into a new array. * </p> * <p> * The new array contains all of the element of {@code array1} followed by * all of the elements {@code array2}. When an array is returned, it is * always a new array. * </p> * * <pre> * ArrayUtils.addAll(null, null) = null * ArrayUtils.addAll(array1, null) = cloned copy of array1 * ArrayUtils.addAll(null, array2) = cloned copy of array2 * ArrayUtils.addAll([], []) = [] * ArrayUtils.addAll([null], [null]) = [null, null] * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"] * * ArrayUtils.addAll(new Number[] { 1, 2 }, new Byte[] { 22 }) = Number[]{1, 2, 22}; * </pre> * * @param <T> the component type of the first array * @param <E> the component type of the second array * * @param array1 the first array whose elements are added to the new array, * may be {@code null} * @param array2 the second array whose elements are added to the new array, * may be {@code null} * @return The new array, {@code null} if both arrays are {@code null}. The * type of the new array is the type of the first array, unless the * first array is null, in which case the type is the same as the * second array. * @since 2.1 * @throws IllegalArgumentException if the array types are incompatible */ @SafeVarargs public static <T, E extends T> T[] addAll(T[] array1, E... array2) { if (array1 == null) { return clone(array2); } else if (array2 == null) { return clone(array1); } final Class<?> type1 = array1.getClass().getComponentType(); @SuppressWarnings("unchecked") // OK, because array is of type T final T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length); System.arraycopy(array1, 0, joinedArray, 0, array1.length); try { System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); } catch (final ArrayStoreException ase) { // Check if problem was due to incompatible types /* * We do this here, rather than before the copy because: - it would * be a wasted check most of the time - safer, in case check turns * out to be too strict */ final Class<?> type2 = array2.getClass().getComponentType(); if (!type1.isAssignableFrom(type2)) { throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of " + type1.getName(), ase); } throw ase; // No, so rethrow original } return joinedArray; }
缺点是有警告,当参数为null
// The argument of type null should explicitly be cast to Number[] for // the invocation of the varargs method addAll(Number[], Number...) from // type ArrayUtils. It could alternatively be cast to Number for a // varargs invocation Number[] nums = ArrayUtils.addAll(new Number[] { 1, 2, 3 }, null); System.out.println(Arrays.toString(nums)); nums = ArrayUtils.addAll(new Number[] { 1, 2, 3 }, (Byte[]) null); // OK System.out.println(Arrays.toString(nums)); String[] strs = ArrayUtils.addAll(null, new String[] { "22", "66", "88" });// OK System.out.println(Arrays.toString(strs));
instanceof, isinstance,isAssignableFrom
1 Class<?> thisClass = Number.class; 2 Class<? extends Number> cls = Integer.class; 3 4 System.out.println(thisClass.isAssignableFrom(cls)); // true 5 System.out.println(cls.isAssignableFrom(thisClass));// false 6 7 Integer integer = Integer.valueOf(1); 8 Number number = integer; 9 Object objNumber = number; 10 System.out.println(integer instanceof Number); // true 11 // ERROR: Incompatible conditional operand types Integer and String 12 // System.out.println(integer instanceof String); 13 System.out.println(objNumber instanceof String);// false
instanceof
使用:AA instanceof BB,检查左边是否是右边的实例而返回boolean值。注意编译前会预判是否合法而提示Incompatible conditional operand types AA and BB。
请查看上例,number和integer以及objNumber都是指向同一个实例,而后两个检查是否是String类实例前者却报错。
boolean java.lang.Class.isAssignableFrom(Class<?> cls)
Determines if the class or interface represented by this
Classobject is either the same as, or is a superclass or superinterface of, the class or interface represented by the specifiedClassparameter. It returnstrueif so; otherwise it returnsfalse. If thisClassobject represents a primitive type, this method returnstrueif the specifiedClassparameter is exactly thisClassobject; otherwise it returnsfalse.Specifically, this method tests whether the type represented by the specified
Classparameter can be converted to the type represented by thisClassobject via an identity conversion or via a widening reference conversion. See The Java Language Specification, sections 5.1.1 and 5.1.4 , for details.
- Parameters:
- cls the
Classobject to be checked- Returns:
- the
booleanvalue indicating whether objects of the typeclscan be assigned to objects of this class- Throws:
- NullPointerException - if the specified Class parameter is null.
- Since:
- JDK1.1
中文
isAssignableFrom
public boolean isAssignableFrom(Class<?> cls)
- 判定此
Class对象所表示的类或接口与指定的Class参数所表示的类或接口是否相同,或是否是其超类或超接口。如果是则返回true;否则返回false。如果该Class表示一个基本类型,且指定的Class参数正是该Class对象,则该方法返回true;否则返回false。特别地,通过身份转换或扩展引用转换,此方法能测试指定
Class参数所表示的类型能否转换为此Class对象所表示的类型。有关详细信息,请参阅 Java Language Specification 的第 5.1.1 和 5.1.4 节。
- 参数:
cls- 要检查的Class对象- 返回:
- 表明
cls类型的对象能否赋予此类对象的boolean值- 抛出:
NullPointerException- 如果指定的 Class 参数为 null。- 从以下版本开始:
- JDK1.1
如果把一个超类和子类有继承实现关系看作有上下大小关系,则isAssignableFrom左边是上型超类右边是下型子类才返回true,被测对象类是入参对象类的超类,入参类的实例可以向上转型给被测对象类的实力。。。
中文
isInstance
public boolean isInstance(Object obj)
- 判定指定的
Object是否与此Class所表示的对象赋值兼容。此方法是 Java 语言instanceof运算符的动态等效方法。如果指定的Object参数非空,且能够在不引发ClassCastException的情况下被强制转换成该Class对象所表示的引用类型,则该方法返回 true;否则返回false。特别地,当该
Class对象表示一个已声明的类时,若指定的Object参数是所表示类(或其任一子类)的一个实例,则此方法返回true;否则返回false。如果此Class对象表示一个数组类,且通过身份转换或扩展引用转换,指定的Object参数能转换为一个数组类的对象,则返回true;否则返回false。如果此Class对象表示一个接口,且指定Object参数的类或任一超类实现了此接口,则此方法返回true;否则返回false。如果此Class对象表示一个基本类型,则此方法返回false。
- 参数:
obj- 要检查的对象- 返回:
- 如果
obj是此类的实例,则返回 true- 从以下版本开始:
- JDK1.1
字段隐藏,反射获取同名字段成员,getDeclaringClass得到字段所属声明类
public static void main(String[] args) throws Exception { class A { private String prifA; public String pubfA; @Override public String toString() { return "A [prifA=" + prifA + ", pubfA=" + pubfA + "]"; } } class B extends A { public String pubfA; public void setPubfA(String pubfA) { super.pubfA = pubfA; } @Override public String toString() { return "B [pubfA=" + pubfA + ", toString()=" + super.toString() + "]"; } } B b = new B(); b.pubfA = "B's filed"; b.setPubfA("A's filed"); // B [pubfA=B's filed, toString()=A [prifA=null, pubfA=A's filed]] System.out.println(b); // // To get the public fields including the inherited fields from the recursively traversed parents. // //[public java.lang.String Test$1B.pubfA, public java.lang.String Test$1A.pubfA] System.out.println(Arrays.toString(B.class.getFields())); System.out.println(B.class.getFields()[1].getDeclaringClass()); //class Test$1A System.out.println(B.class.getField("pubfA").getDeclaringClass()); //class Test$1B // // To get the fields indirectly declared by the class regardless of its modifier. // System.out.println(Arrays.toString(B.class.getDeclaredFields())); }