Java可变长参数的定义及使用
作者:郎佳星
什么是可变长参数:
可变长参数是一种参数集合,在集合中参数的数量的不确定的,可能为一个或者多个,也可能没有参数;在这个参数集合中的每个参数类型是不确定的,我们将这个参数集合称之为可变的长参数。
关于可变长参数的方法定义:
我们在实际的开发中,通常会遇到参数可半场参数的方法,例如求几个数的最大值或者最小值,那么在这种情况在我们该如何定义呢?
由于参数的类型不是固定的,那么我们就用Object类型来接收参数,Object参数是所有类型的父类,定义方法为:
private static void function(Object...obj);
对于可变参数的定义方法而言,它表示在方法名为function中有不确定数量的、类型为Object的多个或0个参数的方法,obj表示为参数集合的名字,类似于数组的用法。
定义中利用“...”来表示不确定数量和类型的参数集合。
为了方便理解,我们写一个函数体,其具体功能为:判断方法中是否有参数,如果没有打印输出提示信息,可以识别参数的个数以及类型,并且把他们打印输出
public class Action {
/**
* 该方法是用以遍历参数集obj
* @parm obj 参数集
*
*/
private static void function(Object...obj){
//判断是否有参数传入该方法,如果没有则输出提示信息。
if (obj.length != 0) {
System.out.println("参数的个数为:" + obj.length);
}else{
System.out.println("未检测到参数,请输入参数!");
}
//遍历参数的值和参数的参数的类型
for (int i = 0; i < obj.length; i++) {
System.out.println("参数" + (i + 1) + “的值为:” + obj[i]);
System.out.println("参数类型为:" + obj[i].getClass().getSimpleName());
}
}
并在主函数中传入可变长参数给function方法并运行用function方法
//主函数,调用function方法并执行。
public static void main(String[] args) {
function(1,1,3.3,4,5);
}
}
1)可变长参数中的参数数量识别:
在以上的方法中对于长参数数量是用obj.lenght方法来识别的,代表在obj参数集合中的参数数量。类似于数组的使用方法。
2)可变长参数中的参数类型识别:
在以上的方法中对于长参数类型识别是在对参数集合的遍历的过程中对于每一个参数执行obj[i].getClass().getSimpleName()方法(后面会详细讲解该方法),来获取参数集合中的每一个参数的类型。
关于可变长参数的方法调用:
再调用带有长参数的方法时和普通的调用方法几乎相同,但是参数的数目是不确定的,可以是多个参数:
如:function(”参数1”,...,”参数n”);
或者没有参数直接调用也是可以的。
如:function();
*关于可变参数的定义的注意事项如下:
1.在调用时可变参数的方法和固定参数的方法如果同时匹配,那么固定参数的方法优先,调用固定参数的方法而不调用可变参数的方法。
例:
执行之后后台输出的结果为:
2.两个相同类型的不定参数方法隶属于同一方法。
3.可变参数可以和固定参数搭配使用,但是可变参数一定要是所有参数中的最后一个参数。
function(String str,int i,List ls,Object...obj);
关于getClass()方法解析:
面对参数类型和参数个数未知的函数并非束手无策,首先对与参数的类型的不确定我们可以设置参数集合的类型为Object类型来解决问题,由于Object是所有类型的父类,可以包含所有的类型,至于原来参数的类型可以在参数遍历中使用方法obj[i].getClass().getSimpleName();来获得参数的原本类型。
getClass()方法属于Object的一部分,他将打印输出对象所在的类。
getClass()常用的方法有:
1)getClass().getName()获得所在的类的准确路径名称,如:java.lang.Integer
2)getClass().getSimpleName()获得所在的类的最简名称,如:Integer
自定义的类也是可以的。
我们新建一个java类:
调用该类方法如下:
function(new Type());
执行结果为:
图中发现参数类型类Type,是我们自定义的类型,可是可以进行类型识别的。
由于getClass()方法是属于Object的一部分,因此在Object的范围中都适用,
不属于Object类型的有:
基本类型:
shot(短整型) int(整型) long(长整型) float(浮点型) double(双精度) char(字符型) boolean(布尔型) byte(字节) void(任意类)
基本类型不可以直接进行使用,但是可以用基本类型包装器进行替代使用。
替代之后的基本类型包装器如下:
Shot(短整型) Integer(整型) Long(长整型) Float(浮点型) Double(双精度) Character(字符型) Boolean(布尔型) Byte(字节) Void(任意类)
在java可变参数方法中的参数适用于所有的类型:(Object)
基本类型包装器调用方法如下:
function(1,1.2,3.14,true,123456789,"456");
调用之后的控制台输出产物为:
还有另一种参数输入方法,前文说到基本类型不属于Object类型,与要用今本类型的包装器来替代基本类型来使用,那么此方法也可以写成
function(new Integer(1),new Double(1.2),new Float(3.14),new Boolean(true),new Long(123456789),new String(“456”));
调用之后的控制台输出产物为:
和上一种参数输入方法的控制台输出相对比,我们发现有一些小小的不同,对于字段123456789,在自动识别类型的方法中判定该字段的类型为int整型变量,而在手动定义参数类型的方法中,该字段的类型为我们手动定义的类型,即long长整型,由于第一种自动识别是按照占用空间大小来自动识别,相比第二种节省内存空间,因此在没有特殊需求下我们常用第一种方法。
自定义类(Class)的传入:
比如前文提到的Type类型调用方法为function(new Type());执行之后在可变长参数function方法中可以使用Type类里面的所有方法和所有字段。
比如在在function方法中使用getName方法,就可以获得字段Name的值。
可变参数方法的应用:(取得最大值方法)
目标程序的功能如下:
1.对主函数传过来的数据进行处理从众多的参数中取得最大值。
2.把取得的最大值放入到function方法中判断最后输出的最大值的数据类型。
根据以上的讲解,要想做一个取得一些数据的最大值,要先进行从众多参数中取得最大值的方法的构造,由于比较大小只能用于少部分的数据类型,因此在这里我们以Integer(整型)、Double(双精度型)、Float(浮点型)这三个类型作为要进行处理的函数类型。
首先创建一个类,并且构造max方法。
该方法对于传过来的参数进行Integer、Double、Float类型的判断,遍历参数集合中的参数,两个两个进行比较,第一个和第二个比较取得最大值,再利用这个最大值和第三个参数进行比较,以此类推......
定义一个双精度参数d作为容器,将参数转换为双精度类型并赋值到d。
不能够进行直接强制转换原因如下:
类型转换异常,Object类型转换为Double类型溢出异常。
return d;
方法返回到参数d。
/**
* 取得最大值的方法
*
* @param in 需要取得最大值的参数集合
*/
public Object max(Object... in) {
double n = 0.0;
// 定义一个双精度的n作为局部变量,用以表示in[i - 1]。
Boolean bInteger = false;
/*
* 设置布尔值bInteger,用以表示原数据类型(Integer)。
* 在数据全都变为双精度类型的时候,在取得最大值时,可以返还原数据类型(Integer)。
*/
Boolean bFloat = false;
/*
* 设置布尔值bFloat,用以表示原数据类型(Float)。
* 在数据全都变为双精度类型的时候,在取得最大值时,可以返还原数据类型(Float)。
*/
Boolean bDouble = false;
/*
* 设置布尔值bFloat,用以表示原数据类型(Float)。
* 在数据全都变为双精度类型的时候,在取得最大值时,可以返还原数据类型(Float)。
*/
/*
* 开始遍历。
*/
for (int i = 0; i < in.length; i++) {
if (i == 0) {
/*
* 先低一个数据参数进行处理,不做任何比较,直接转换类型。 因为第一个参数之前没有参数了,不能和前一个进行比较。
*/
n = dou(in[i]);
// 利用dou方法将数据参数转成双精度型。
} else {
/*
* 非第一项的情况
*/
if (in[i].getClass().getSimpleName().equals("Integer")) {
// 原参数数据类型判断,是哪个类型就把相对性的布尔值bInteger设置为真值。
bInteger = true;
} else if (in[i].getClass().getSimpleName().equals("Float")) {
// 原参数数据类型判断,是哪个类型就把相对性的布尔值bFloat设置为真值。
bFloat = true;
} else if (in[i].getClass().getSimpleName().equals("Double")) {
// 原参数数据类型判断,是哪个类型就把相对性的布尔值bDouble设置为真值。
bFloat = true;
}
double n1 = dou(in[i]);
// 将非第一项的参数传入到dou方法中,转换成双精度类型,并赋值为n1
/*
* 正在遍历循环的这一项和上一项进行比较大小 如果本次遍历项的数值大于上一遍历的数值
* 那么把本项赋值给n,使得在遍历中n永远是最大的
*/
if (n1 > n || n1 == n) {
n = n1;
}
}
}
/*
* 根据原参数数据类型还原
* 根据参数等级进行返回,由高级到低级
* 如果高级是真低级也是真,那么返回高级
* 例如参数中有双精度有单精度,那么返回双精度
* 因此无需初始化布尔值,并且打印输出最大值
*/
if (bDouble) {
double e = (double) n;
System.out.println("最大值为:" + e);
return e;
}else if (bFloat) {
float e = (float) n;
System.out.println("最大值为:" + e);
return e;
} else if (bInteger) {
int e = (int) n;
System.out.println("最大值为:" + e);
return e;
}
System.out.println(n);
return n;
}
}
另新建java文件,创建主类。在主类中构造方法,用以识别max方法传过来的最大值的数据类型。
先对传过来的参数数量进行判断,如果没有任何的参数传入,则输出一条提示信息,如果有参数则输出参数的数量。对传过来的参数进行遍历,对每个参数通过getClass().getSimpleName()方法进行类型分析判断,取得该参数的类型,通过遍历所有参数,取得所有参数的类型,并且打印输出。
主函数如下:
public static void main(String[] args) {
function(new Max().max(3,5,7));
}
分别对上面的数据进行最大值分析,并将结果传入到function方法中进行类型分析。
最终控制台执行结果为:
以上为我对不定参数方法的定义和使用的相关理解与开发应用。
本人原创,转载请表明出处,侵权必究!