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, , joinedArray, , array1.length);
System.arraycopy(array2, , 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 = { "", "" };
// 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[] { "", "" }))); // Compile warning
System.out.println(Arrays.toString(ArrayUtils.addAll(array, "", ""))); // OK
System.out.println(Arrays.toString(ArrayUtils.addAll(array, (Object[]) new String[] { "", "" }))); // OK
System.out.println(Arrays.toString(ArrayUtils.addAll(array, (Object) new String[] { "", "" })));// 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

         Class<?> thisClass = Number.class;
Class<? extends Number> cls = Integer.class; System.out.println(thisClass.isAssignableFrom(cls)); // true
System.out.println(cls.isAssignableFrom(thisClass));// false Integer integer = Integer.valueOf(1);
Number number = integer;
Object objNumber = number;
System.out.println(integer instanceof Number); // true
// ERROR: Incompatible conditional operand types Integer and String
// System.out.println(integer instanceof String);
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()));
}

java变参的更多相关文章

  1. Java 变参函数的实现

      Java的变参函数实现实际上参数是一个数组,其简单用法如下 public class variableParamTest { private static void variableParam(O ...

  2. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  3. [转载]一个标准java程序员的进阶过程

    第一阶段:Java程序员 技术名称 内                 容 说明 Java语法基础 基本语法.数组.类.继承.多态.抽象类.接口.object对象.常用类(Math\Arrarys\S ...

  4. n维数组实现(可变参数表的使用)

    首先先介绍一下可变参数表需要用到的宏: 头文件:#include<cstdarg> void va_start( va_list arg_ptr, prev_param ); type v ...

  5. Java的多线程机制系列:(一)总述及基础概念

    前言 这一系列多线程的文章,一方面是个人对Java现有的多线程机制的学习和记录,另一方面是希望能给不熟悉Java多线程机制.或有一定基础但理解还不够深的读者一个比较全面的介绍,旨在使读者对Java的多 ...

  6. 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)

    这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...

  7. Java Web指导方向

    第一阶段 第二阶段 第三阶段 第四阶段 第五阶段 第六阶段 第七阶段 第一阶段:Java程序员 技术名称 内                 容 说明 Java语法基础 基本语法.数组.类.继承.多态 ...

  8. java effective 读书笔记

    java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...

  9. Java中main方面面试题

    1.不用main方法如何定义一个类? 不行,没有main方法我们不能运行Java类. 在Java 7之前,你可以通过使用静态初始化运行Java类.但是,从Java 7开始就行不通了. 2.main() ...

随机推荐

  1. 关于 react state的改变数据上面的一点问题

    在react当中 比如说 this.state = { loginInfo: { account: "...", password: "..." } } thi ...

  2. js数据类型判断

    在一般情况下使用typeof 但是有时候typeof返回的结果都是object,比如数组和json对象的时候,这个时候需要用到 instanceof了 还有一个更好得办法,Object.prototy ...

  3. iOS 初始化(init、initWithNibName、initWithCoder、initWithFrame)

    很多朋友如果是初学iOS开发,可能会被其中的几个加载方法给搞得晕头转向的,但是这几个方法又是作为iOS程序员必须要我们掌握的方法,下面我将对这几个方法做一下分析和对比,看看能不能增加大家对几个方法的理 ...

  4. SPOJ HIGH Highways

    In some countries building highways takes a lot of time... Maybe that's because there are many possi ...

  5. mysql启动错误1067的解决

    安装后MYSQL5后,发现启动出错,有时启动正常,但加接时马上出错. 出错代码:1067 解决办法如下: 删除%windows%/my.ini    删除其它地方的my.ini    在mysql安装 ...

  6. 【XPButton类】美化MFC button (转)

    从网上找到别人写的一个XPButton类,利用XPButton类实现XP风格的按钮.百度一下即可找到这个类,接下来具体的步骤如下: 1.创建基于对话框的MFC工程假设命名为:XPButtonTest, ...

  7. AC日记——N的倍数 51nod 1103

    1103 N的倍数 思路: 先计算出前缀和: 然后都%n: 因为有n个数,所以如果没有sum[i]%n==0的化,一定有两个取模后的sum相等: 输出两个sum中间的数就好: 来,上代码: #incl ...

  8. [Machine Learning with Python] Cross Validation and Grid Search: An Example of KNN

    Train model: from sklearn.model_selection import GridSearchCV param_grid = [ # try 6 (3×2) combinati ...

  9. Ansible之常用模块介绍

    环境 ansible HOST-PATTERN -m MOD_NAME -a MOD_ARGS -C -f forks ssh-keygen -t rsa -P "" ssh-co ...

  10. Java编程经验汇总

    JDK和JRE 大家肯定在安装JDK的时候会有选择是否安装单独的jre,一般都会一起安装,我也建议大家这样做.因为这样更能帮助大家弄清楚它们的区别: Jre 是java runtime environ ...