原文转自:http://www.cnblogs.com/lanxuezaipiao/p/3190673.html

在Java5 中提供了变长参数(varargs),也就是在方法定义中可以使用个数不确定的参数,对于同一方法可以使用不同个数的参数调用。

例如print("hello");print("hello","lisi");print("hello","张三", "alexia");

下面介绍如何定义可变长参数 以及如何使用可变长参数。

1. 可变长参数的定义

使用...表示可变长参数,例如:

print(String... args){
...
}

在具有可变长参数的方法中可以把参数当成数组使用,例如可以循环输出所有的参数值。

print(String... args){
for(String temp:args)
System.out.println(temp);
}

2. 可变长参数的方法的调用

调用的时候可以给出任意多个参数也可不给参数,例如:

print();
print("hello");
print("hello","lisi");
print("hello","张三", "alexia")

3. 可变长参数的使用规则

3.1 在调用方法的时候,如果能够和固定参数的方法匹配,也能够与可变长参数的方法匹配,则选择固定参数的方法。看下面代码的输出:

import static java.lang.System.out;

public class VarArgsTest {
//1.可变长参数的方法匹配,如果能够和固定参数的方法匹配,也能够与可变长参数的方法匹配,则选择固定参数的方法.
public void print(String test) {
out.println("1. "+test);
} public void print(String... args) {
out.print("2.");
for (int i = 0; i < args.length; i++) {
out.print(" "+args[i]);
}
} public static void main(String[] args) {
VarArgsTest test = new VarArgsTest();
test.print("hello");
test.print("hello", "alexia");
}
}

输出显示:

1. hello

2. hello alexia

3.2 如果要调用的方法可以和两个可变参数匹配,则出现错误,例如下面的代码:

import static java.lang.System.out;

public class VarArgsTest {
//2.如果要调用的方法可以和两个可变参数匹配,则出现错误。
public void print(String... args) {
out.print("1.");
for (int i = 0; i < args.length; i++) {
out.print(" "+args[i]);
}
} public void print(String test,String...args ){
out.print("2. "+test);
for (int i = 0; i < args.length; i++) {
out.print(" "+args[i]);
}
} public static void main(String[] args) {
VarArgsTest test = new VarArgsTest();
test.print("hello");
test.print("hello", "alexia");
}
}

对于上面的代码,main方法中的两个调用都不能编译通过,因为编译器不知道该选哪个方法调用,提示错误如下所示:

如果这两个带可变长参数的方法只留其一,则可正常显示。

3.3 一个方法只能有一个可变长参数,并且这个可变长参数必须是该方法的最后一个参数

以下两种方法定义都是错误的。

public void test(String... strs,ArrayList list){

}

public void test(String... strs,ArrayList... list){

}

4. 可变长参数的使用规范

4.1 避免带有可变长参数的方法重载:如3.1中,编译器虽然知道怎么调用,但人容易陷入调用的陷阱及误区

4.2 别让null值和空值威胁到变长方法,如3.2中所示,为了说明null值的调用,重新给出一个例子:

import static java.lang.System.out;

public class VarArgsTest {
public void print(String test,Integer... is) {
out.print("1.");
for (int i = 0; i < is.length; i++) {
out.print(" "+is[i]);
}
} public void print(String test,String...args ){
out.print("2. "+test);
for (int i = 0; i < args.length; i++) {
out.print(" "+args[i]);
}
} public static void main(String[] args) {
VarArgsTest test = new VarArgsTest();
test.print("hello","oweio","deg");
test.print("hello", 4,5,4); test.print("hello");
test.print("hello",null);
}
}

这时会发现两个调用编译都不通过:



因为两个方法都匹配,编译器不知道选哪个,于是报错了。

这里同时还有个非常不好的编码习惯,即调用者隐藏了实参类型,这是非常危险的,不仅仅调用者需要“猜测”该调用哪个方法,而且被调用者也可能产生内部逻辑混乱的情况。

对于本例来说应该做如下修改:

     VarArgsTest test = new VarArgsTest();
String[] strs = null;
test.print("hello",strs);
}

此时,编译通过,但是在读取元素值时,还是会有空指针异常。

4.3 覆写变长方法也要循规蹈矩

下面看一个例子,大家猜测下程序能不能编译通过:

public class VarArgsTest{
public static void main(String[] args) {
// 向上转型
Base base = new Sub();
base.print("hello"); // 不转型
Sub sub = new Sub();
sub.print("hello");
}
} // 基类
class Base {
void print(String... args) {
System.out.println("Base......test");
}
} // 子类,覆写父类方法
class Sub extends Base {
void print(String[] args) {
System.out.println("Sub......test");
}
}

答案当然是编译不通过,是不是觉得很奇怪?

第一个能编译通过,这是为什么呢?事实上,base对象把子类对象sub做了向上转型,形参列表是由父类决定的,当然能通过。

而看看子类直接调用的情况,这时编译器看到子类覆写了父类的print方法,因此肯定使用子类重新定义的print方法,尽管参数列表不匹配也不会跑到父类再去匹配下,因为找到了就不再找了,因此有了类型不匹配的错误。

这是个特例,覆写的方法参数列表竟然可以与父类不相同,这违背了覆写的定义,并且会引发莫名其妙的错误。

这里,总结下覆写必须满足的条件:

(1)重写方法不能缩小访问权限;

(2)参数列表必须与被重写方法相同(包括显示形式);

(3)返回类型必须与被重写方法的相同或是其子类;

(4)重写方法不能抛出新的异常,或者超过了父类范围的异常,但是可以抛出更少、更有限的异常,或者不抛出异常。

最后,给出一个有陷阱的例子,大家应该知道输出结果:

public class VarArgsTest {
public void print(String s, String... ss) {
System.out.print(s+" ");
for (int i = 0; i < ss.length; i++) {
System.out.println(ss[i]);
}
System.out.println();
} public static void main(String[] args) {
VarArgsTest test = new VarArgsTest();
test.print("");
test.print("aaa");
//test.print("aaa",null);//编译通过,但是读取元素时空指针异常
test.print("aaa", "bbb");
}
}

输出显示:

 

aaa  

aaa  bbb

Java中可变长参数的方法的更多相关文章

  1. java中可变长参数

    ** * Created by Lenovo on 2017/12/10. * java中可变长参数 */ public class reflect04 { //m1有一个int类型的可比变长参数 / ...

  2. java中可变长参数的定义及使用方法

    JAVA中可以为方法定义可变长参数( Varargs)来匹配不确定数量的多个参数,其定义用“...”表示.其实,这类似于为方法传了一个数组,且在使用方法上也和数组相同,如下: public void ...

  3. Java中可变长参数的使用及注意事项

    在Java5 中提供了变长参数(varargs),也就是在方法定义中可以使用个数不确定的参数,对于同一方法可以使用不同个数的参数调用,例如print("hello");print( ...

  4. Java 数组 可变长参数 实例

    可以把类型相同但个数可变的参数传递给方法,方法中的参数声明如下: typeName...parameterName (类型名...参数名) 在方法声明中,指定类型后紧跟着省略号...,只能给方法指定一 ...

  5. 关于C中可变长参数

    前言 可变长参数指函数的参数个数在调用时才能确定的函数参数.基本上各种语言都支持可变长参数,在特定情形下,可变长参数使用起来非常方便.c语言中函数可变长参数使用“...”来表示,同时可变长参数只能位于 ...

  6. 巩固java(六)----java中可变参数方法(非常实用哦)

    java提供了可变参数的方法,即方法的参数个数可以不确定,用"..."定义. import java.util.ArrayList; import java.util.List; ...

  7. Java中的可变长参数

    可变长参数的定义 与一般方法没多大差别,只不过形参多了...(三个点) 方法名(数据类型 ... 变量名){} 小案例: public class ParamDemo { public static ...

  8. Java 可变长参数列表

    Java中定义了变长参数,允许在调用方法时传入不定长度的参数. 定义及调用 在定义方法时,在最后一个形参后加上三点 …,就表示该形参可以接受多个参数值,多个参数值被当成数组传入.上述定义有几个要点需要 ...

  9. 方法的可变长参数 传入参数个数不确定可用(Type ... values)

    /** * 可变长的参数. * 有时候,我们传入到方法的参数的个数是不固定的,为了解决这个问题,我们一般采用下面的方法: * 1. 重载,多重载几个方法,尽可能的满足参数的个数.显然这不是什么好办法. ...

随机推荐

  1. jquery.cookie用法详细解析

    本篇文章主要是对jquery.cookie的用法进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助 Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将 ...

  2. c#隐式转换之有符号位转换

    有符号位类型的转换,额外的高位用源表达式的符号位填充.这样就维持了被转换的值的正确符号和大小. 特别注意的是负数的转换,额外的高位用1填充,因为负数的二进制表示是对应正数的二进制取反加1,所以高位用1 ...

  3. Hive学习之三 《Hive的表的详解和应用案例详解》

    一.Hive的表 Hive的表分为内部表.外部表和分区表. 1.内部表,为托管表. 2.外部表,external. 3.分区表. 详解: 内部表,删除表的时候,数据会跟着删除. 外部表,在删除表的时候 ...

  4. MPICH2在两台Ubuntu上安装

    本文在经过大量的实验终于不负众望成功的在两台Ubuntu 12.04上部署MPI的一个小型集群,MPICH2所用版本为mpich2-1.4.1,下载地址:http://www.mcs.anl.gov/ ...

  5. Google Calendar(日历)设置农历生日提醒

    Generate birthday dates base on lunar birthdays for google calendar import Can be used for notifying ...

  6. Google jQuery URL

    Query 在线地址:https://developers.google.com/speed/libraries/devguide?hl=zh-CN#jquery此地址里还包含了很多的JS框架.

  7. 关于jQuery表单校验的应用

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  8. HTML5 QQ登录背景动态图片

    预览效果如图所示: 代码如下: <!DOCTYPE html> <head> <meta http-equiv="Content-Type" cont ...

  9. Websocket 与代理服务器如何交互? How HTML5 Web Sockets Interact With Proxy Servers

    How HTML5 Web Sockets Interact With Proxy Servers Posted by Peter Lubberson Mar 16, 2010 With the re ...

  10. C++学习笔记3——类的封装(1)

    封装: 1.把属性和方法进行封装. 2.对属性和方法进行访问控制. class和struct的区别: class和struct的唯一区别是默认的访问权限不一样.struct的默认访问权限是public ...