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
Class
object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specifiedClass
parameter. It returnstrue
if so; otherwise it returnsfalse
. If thisClass
object represents a primitive type, this method returnstrue
if the specifiedClass
parameter is exactly thisClass
object; otherwise it returnsfalse
.Specifically, this method tests whether the type represented by the specified
Class
parameter can be converted to the type represented by thisClass
object 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
Class
object to be checked- Returns:
- the
boolean
value indicating whether objects of the typecls
can 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())); }