网站首页 > 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());
查看源码就可以发现,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() 方法的内部要做好判空的操作。
好了,各位读者朋友们,以上就是本文的全部内容了。能看到这里的都是最优秀的程序员,升职加薪就是你了。
作者:沉默王二
原文链接:https://juejin.im/post/5e09657af265da33a55fb19f
猜你喜欢
- 2024-11-06 35个编码小细节,助你有效提升Java代码的执行效率!网友:学到了
- 2024-11-06 35个Java 代码优化细节(seo 代码优化)
- 2024-11-06 Java 性能优化:35 个小细节,提升你的 Java 代码运行效率
- 2024-11-06 二十二、Java中的函数与方法(java 函数)
- 2024-11-06 java高级用法之:JNA类型映射应该注意的问题
- 2024-11-06 最全面的44个Java性能调优细节(四个全面中哪个最具有基础性)
- 2024-11-06 尚学堂知识整理:java可变长度数组
- 2024-11-06 阿里强制要求的21条Java开发规范,可以避免很多坑
- 2024-11-06 面试题:为什么 Java 中的 String 被设计为不可变类?
- 2024-11-06 第五章:Java方法和参数传递(java中方法的参数传递是什么调用)
你 发表评论:
欢迎- 最近发表
-
- Java常量定义防暴指南:从"杀马特"到"高富帅"的华丽转身
- Java接口设计原则与实践:优雅编程的艺术
- java 包管理、访问修饰符、static/final关键字
- Java工程师的代码规范与最佳实践:优雅代码的艺术
- 编写一个java程序(编写一个Java程序计算并输出1到n的阶乘)
- Mycat的搭建以及配置与启动(mycat部署)
- Weblogic 安装 -“不是有效的 JDK Java 主目录”解决办法
- SpringBoot打包部署解析:jar包的生成和结构
- 《Servlet》第05节:创建第一个Servlet程序(HelloSevlet)
- 你认为最简单的单例模式,东西还挺多
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)