zoukankan      html  css  js  c++  java
  • java变参

    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)

    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 specified Class parameter. It returns true if so; otherwise it returns false. If this Class object represents a primitive type, this method returns true if the specified Class parameter is exactly this Class object; otherwise it returns false.

    Specifically, this method tests whether the type represented by the specified Class parameter can be converted to the type represented by this Class 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 type cls 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()));
        }
  • 相关阅读:
    [BJOI2012]最多的方案(记忆化搜索)
    our happy ending(状压dp)
    [NOI2005]聪聪与可可(期望dp)
    CF983A Finite or not?(数学)
    [POI2012]STU-Well(二分答案+神仙操作)
    作诗2(玄学)
    IncDec Sequence(差分)
    [Vani有约会]雨天的尾巴(树上差分+线段树合并)
    合法括号序列(dp+组合数学)
    [SHOI2014]概率充电器(概率+换根dp)
  • 原文地址:https://www.cnblogs.com/Fang3s/p/4828390.html
Copyright © 2011-2022 走看看