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, , 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)
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()));
}
java变参的更多相关文章
- Java 变参函数的实现
Java的变参函数实现实际上参数是一个数组,其简单用法如下 public class variableParamTest { private static void variableParam(O ...
- Spark案例分析
一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...
- [转载]一个标准java程序员的进阶过程
第一阶段:Java程序员 技术名称 内 容 说明 Java语法基础 基本语法.数组.类.继承.多态.抽象类.接口.object对象.常用类(Math\Arrarys\S ...
- n维数组实现(可变参数表的使用)
首先先介绍一下可变参数表需要用到的宏: 头文件:#include<cstdarg> void va_start( va_list arg_ptr, prev_param ); type v ...
- Java的多线程机制系列:(一)总述及基础概念
前言 这一系列多线程的文章,一方面是个人对Java现有的多线程机制的学习和记录,另一方面是希望能给不熟悉Java多线程机制.或有一定基础但理解还不够深的读者一个比较全面的介绍,旨在使读者对Java的多 ...
- 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)
这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...
- Java Web指导方向
第一阶段 第二阶段 第三阶段 第四阶段 第五阶段 第六阶段 第七阶段 第一阶段:Java程序员 技术名称 内 容 说明 Java语法基础 基本语法.数组.类.继承.多态 ...
- java effective 读书笔记
java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...
- Java中main方面面试题
1.不用main方法如何定义一个类? 不行,没有main方法我们不能运行Java类. 在Java 7之前,你可以通过使用静态初始化运行Java类.但是,从Java 7开始就行不通了. 2.main() ...
随机推荐
- react-router 4.0版本学习笔记
Router 所有路由组件的底层接口,一般情况都不使用,而是使用更加高级的路由. 最常用的有两种<BrowserRouter>.<HashRouter> <Browser ...
- IDA 调试 Android
最近都在学一些反编译安卓相关的东西,其实网上有很多教程关于用 IDA 调试 Android 的过程,主要记录一下我遇到的坑 首先 Android手机要是root过的 还要注意的一点是apk中的 And ...
- c++ 中 define
1.简单的define定义 #define MAXTIME 1000 一个简单的MAXTIME就定义好了,它代表1000,如果在程序里面写 if(i<MAXTIME){.........} 编译 ...
- updatepanel中使用alert弹出框方法
原文发布时间为:2009-05-17 -- 来源于本人的百度文章 [由搬家工具导入] ScriptManager.RegisterStartupScript(this.UpdatePa ...
- sql联合主键,用于多对多,关系映射
如题.记录下. 复合主键,由多个字段共同确定一行信息 composite key, containing multi cols to fix one element.
- wxformbuilder
1.打开wxFormBuilder,按开始一个空项目.您也可以执行File|New来创建新项目2.从Object Properties(对象属性)面板配置项目的设置A.选择产生什么类型的代码. 现在你 ...
- LeetCode OJ--Word Break II ***@
https://oj.leetcode.com/problems/word-break-ii/ class Solution { public: unordered_set<string> ...
- (4)JavaScript引用类型
Object类 创建object实例的方式有两种 1.第一种是使用 new 操作符后跟 Object 构造函数 var person = new Object(); person.name = &qu ...
- 2016集训测试赛(二十一)Problem C: 虫子
题目大意 给你一棵树, 每个点有一个点权. 有两种操作: link / cut 修改某个点的点权 每次操作后, 你要输出以下答案: 在整棵树中任意选两个点, 这两个点的LCA的期望权值. Soluti ...
- 网络安全---大学霸_ITDaren
http://blog.csdn.net/u014621518/article/category/2191665