五分钟学Java:可变参数究竟是怎么一回事?
在逛 programcreek 的时候,我发现了一些专注基础但不容忽视的主题。比如说:java 的可变参数究竟是怎么一回事?像这类灵魂拷问的主题,非常值得深入地研究一下。
我以前很不重视基础,觉得不就那么回事嘛,会用就行了。就比如说今天这个主题,管它可变不可变呢,不就是个参数嘛,还能有多大学问——抱着这种态度,我一直横行江湖近十载(苦笑)。可等到读者找我提一些基础的问题时,我几乎回答不上来,感觉知识是散的,或者是浮于表面的。幸好最近一段时间,我开始幡然醒悟,开始不放过任何一个细节,渐渐地,有点“知识储备”了。
好了,牛逼吹完,让我们来步入正题。java 的可变参数究竟是怎么一回事?
可变参数是 java 1.5 的时候引入的功能,它允许方法使用任意多个、类型相同(is-a
)的值作为参数。就像下面这样。
public static void main(string[] args) {
print("沉");
print("沉", "默");
print("沉", "默", "王");
print("沉", "默", "王", "二");
}
public static void print(string... strs) {
for (string s : strs)
system.out.print(s);
system.out.println();
}
静态方法 print()
就使用了可变参数,所以 print("沉")
可以,print("沉", "默")
也可以,甚至 3 个、 4 个或者更多个字符串都可以作为参数传递给 print()
方法。
说到可变参数,我想起来阿里巴巴开发手册上有这样一条规约。
意思就是尽量不要使用可变参数,如果要用的话,可变参数必须要在参数列表的最后一位。既然坑位有限,只能在最后,那么可变参数就只能有一个(悠着点,悠着点)。如果可变参数不在最后一位,ide 就会提示对应的错误,如下图所示。
那可变参数是怎么工作的呢?
原理也很简单。当使用可变参数的时候,实际上是先创建了一个数组,该数组的大小就是可变参数的个数,然后将参数放入数组当中,再将数组传递给被调用的方法。
这就是为什么可以使用数组作为参数来调用带有可变参数的方法的根本原因。代码如下所示。
public static void main(string[] args) {
print(new string[]{"沉"});
print(new string[]{"沉", "默"});
print(new string[]{"沉", "默", "王"});
print(new string[]{"沉", "默", "王", "二"});
}
public static void print(string... strs) {
for (string s : strs)
system.out.print(s);
system.out.println();
}
那如果方法的参数是一个数组,然后像使用可变参数那样去调用方法的时候,能行得通吗?大家感兴趣的话,不妨试一试(行不通,嘘)。
那一般什么时候使用可变参数呢?
可变参数,可变参数,顾名思义,当一个方法需要处理任意多个相同类型的对象时,就可以定义可变参数。java 中有一个很好的例子,就是 string 类的 format()
方法,就像下面这样。
system.out.println(string.format("年纪是: %d", 18));
system.out.println(string.format("年纪是: %d 名字是: %s", 18, "沉默王二"));
ps:%d
表示将整数格式化为 10 进制整数,%s
表示输出字符串。
如果不使用可变参数,那需要格式化的参数就必须使用“+”号操作符拼接起来了。麻烦也就惹祸上身了。
在实际的项目代码中,开源包 slf4j.jar 的日志输出就经常要用到可变参数(log4j 就没法使用可变参数,日志中需要记录多个参数时就痛苦不堪了)。就像下面这样。
protected logger logger = loggerfactory.getlogger(getclass());
logger.debug("名字是{}", mem.getname());
logger.debug("名字是{},年纪是{}", mem.getname(), mem.getage());
查看源码就可以发现,debug()
方法使用的可变参数。
public void debug(string format, object... arguments);
那在使用可变参数的时候有什么注意事项吗?
有的,有的。我们要避免重载带有可变参数的方法——这样很容易让编译器陷入自我怀疑中。
public static void main(string[] args) {
print(null);
}
public static void print(string... strs) {
for (string a : strs)
system.out.print(a);
system.out.println();
}
public static void print(integer... ints) {
for (integer i : ints)
system.out.print(i);
system.out.println();
}
这时候,编译器完全不知道该调用哪个 print()
方法,print(string... strs)
还是 print(integer... ints)
,傻傻分不清。
假如真的需要重载带有可变参数的方法,就必须在调用方法的时候给出明确的指示,不要让编译器去猜。
public static void main(string[] args) {
string [] strs = null;
print(strs);
integer [] ints = null;
print(ints);
}
public static void print(string... strs) {
}
public static void print(integer... ints) {
}
上面这段代码是可以编译通过的。因为编译器知道是 string 类型还是 integer 类型,只不过为了运行时不抛出 nullpointerexception
,两个 print()
方法的内部要做好判空的操作。
好了,各位读者朋友们,以上就是本文的全部内容了。能看到这里的都是最优秀的程序员,升职加薪就是你了
相关文章:
-
-
Java是一种区分字母的大小写的语言,所以我们在定义变量名的时候应该注意区分大小写的使用和一些规范,接下来我们简单的来讲讲Java语言中包、类、变量... [阅读全文]
-
本笔记摘抄自:https://www.cnblogs.com/solan/archive/2012/08/01/CSharp06.html,记录一下... [阅读全文]
-
首先创建tomcat的文件夹 , 为了方便docker的配置 我这里直接在根目录中创建 第一步:创建文件夹:发布文件夹 mkdir -p /dock... [阅读全文]
-
苹果是我们日常生活中吃得最多的一种水果了,因为苹果一年四季都有,而且价格低廉,营养价值丰富,但是有一点大家平日里可能比较的困惑,就是在吃苹果的时候到底要不要削皮... [阅读全文]
-
1.引言 上一篇博文关于浅拷贝和深拷贝 https://www.cnblogs.com/zhaoyixiang/p/12116203.html 我们... [阅读全文]
-
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论