java使用省略号代替多参数(参数类型... 参数名)

【嵌入式面经】上海 70迈 线上笔试 “关注|点赞|收藏” 福利干货第一时间送达!最近在做免费的嵌入式知识分享,帮助对嵌入式感兴趣的同学学习嵌入式、做项目、找工作! 阅读详情
J2SE 1.5提供了“Varargs”机制。借助这一机制,可以定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。本文介绍这一机制的使用方法,以及这一机制与数组、泛型、重载之间的相互作用时的若干问题。

到J2SE 1.4为止,一直无法在Java程序里定义实参个数可变的方法——因为Java要求实参(Arguments)和形参(Parameters)的数量和类型都必须逐一匹配,而形参的数目是在定义方法时就已经固定下来了。尽管可以通过重载机制,为同一个方法提供带有不同数量的形参的版本,但是这仍然不能达到让实参数量任意变化的目的。

然而,有些方法的语义要求它们必须能接受个数可变的实参——例如著名的main方法,就需要能接受所有的命令行参数为实参,而命令行参数的数目,事先根本无法确定下来。

对于这个问题,传统上一般是采用“利用一个数组来包裹要传递的实参”的做法来应付。

1. 用数组包裹实参

“用数组包裹实参”的做法可以分成三步:首先,为这个方法定义一个数组型的参数;然后在调用时,生成一个包含了所有要传递的实参的数组;最后,把这个数组作为一个实参传递过去。

这种做法可以有效的达到“让方法可以接受个数可变的参数”的目的,只是调用时的形式不够简单。

J2SE 1.5中提供了Varargs机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。

2. 定义实参个数可变的方法

只要在一个形参的“类型”与“参数名”之间加上三个连续的“.”(即“...”,英文里的句中省略号),就可以让它和不确定个实参相匹配。而一个带有这样的形参的方法,就是一个实参个数可变的方法。

清单1:一个实参个数可变的方法

private static int sumUp(  int... values) { 
} 

注意,只有最后一个形参才能被定义成“能和不确定个实参相匹配”的。因此,一个方法里只能有一个这样的形参。另外,如果这个方法还有其它的形参,要把它们放到前面的位置上。

编译器会在背地里把这最后一个形参转化为一个数组形参,并在编译出的class文件里作上一个记号,表明这是个实参个数可变的方法。

清单2:实参个数可变的方法的秘密形态

private static int sumUp(  int[] values) { 
} 

由于存在着这样的转化,所以不能再为这个类定义一个和转化后的方法签名一致的方法。

清单3:会导致编译错误的组合

private static int sumUp(  int... values) { 
} 
private static int sumUp(  int[] values) { 
} 

3. 调用实参个数可变的方法

只要把要传递的实参逐一写到相应的位置上,就可以调用一个实参个数可变的方法。不需要其它的步骤。

清单4:可以传递若干个实参

sumUp(  1, 3, 5, 7);

在背地里,编译器会把这种调用过程转化为用“数组包裹实参”的形式:

清单5:偷偷出现的数组创建

sumUp(  new int[]{1, 2, 3, 4}); 

另外,这里说的“不确定个”也包括零个,所以这样的调用也是合乎情理的:

清单6:也可以传递零个实参

sumUp  (); 

这种调用方法被编译器秘密转化之后的效果,则等同于这样:

清单7:零实参对应空数组

sumUp(new int[]  {}); 

注意这时传递过去的是一个空数组,而不是null。这样就可以采取统一的形式来处理,而不必检测到底属于哪种情况。

4. 处理个数可变的实参

处理个数可变的实参的办法,和处理数组实参的办法基本相同。所有的实参,都被保存到一个和形参同名的数组里。根据实际的需要,把这个数组里的元素读出之后,要蒸要煮,就可以随意了。

清单8:处理收到的实参们

private static int sumUp(int...   values) { 
    int sum = 0; 
    for (int i = 0; i <   values.length; i++) { 
        sum +=   values[i]; 
    } 
    return sum; 
} 

5. 转发个数可变的实参

有时候,在接受了一组个数可变的实参之后,还要把它们传递给另一个实参个数可变的方法。因为编码时无法知道接受来的这一组实参的数目,所以“把它们逐一写到该出现的位置上去”的做法并不可行。不过,这并不意味着这是个不可完成的任务,因为还有另外一种办法,可以用来调用实参个数可变的方法。

在J2SE 1.5的编译器的眼中,实参个数可变的方法是最后带了一个数组形参的方法的特例。因此,事先把整组要传递的实参放到一个数组里,然后把这个数组作为最后一个实参,传递给一个实参个数可变的方法,不会造成任何错误。借助这一特性,就可以顺利的完成转发了。

清单9:转发收到的实参们

public class PrintfSample { 
    public static void main(String[] args) { 
        //打印出“Pi:3.141593 E:2.718282” 
        printOut("Pi:%f E:%f/n", Math.PI, Math.E); 
    } 
    private static void printOut(String format,   Object... args) { 
        //J2SE 1.5里PrintStream新增的printf(String format, Object... args)方法 
        System.out.printf(format,   args); 
    } 
} 

6. 是数组?不是数组?

尽管在背地里,编译器会把能匹配不确定个实参的形参,转化为数组形参;而且也可以用数组包了实参,再传递给实参个数可变的方法;但是,这并不表示“能匹配不确定个实参的形参”和“数组形参”完全没有差异。

一个明显的差异是,如果按照调用实参个数可变的方法的形式,来调用一个最后一个形参是数组形参的方法,只会导致一个“cannot be applied to”的编译错误。

清单10:一个“cannot be applied to”的编译错误

private static void testOverloading(  int[] i) { 
    System.out.println("A"); 
} 
public static void main(String[] args) { 
    testOverloading(  1, 2, 3);//编译出错 
} 

由于这一原因,不能在调用只支持用数组包裹实参的方法的时候(例如在不是专门为J2SE 1.5设计第三方类库中遗留的那些),直接采用这种简明的调用方式。

如果不能修改原来的类,为要调用的方法增加参数个数可变的版本,而又想采用这种简明的调用方式,那么可以借助“引入外加函数(Introduce Foreign Method)”和“引入本地扩展(Intoduce Local Extension)”的重构手法来近似的达到目的。

7. 当个数可变的实参遇到泛型

J2SE 1.5中新增了“泛型”的机制,可以在一定条件下把一个类型参数化。例如,可以在编写一个类的时候,把一个方法的形参的类型用一个标识符(如T)来代表,至于这个标识符到底表示什么类型,则在生成这个类的实例的时候再行指定。这一机制可以用来提供更充分的代码重用和更严格的编译时类型检查。

不过泛型机制却不能和个数可变的形参配合使用。如果把一个能和不确定个实参相匹配的形参的类型,用一个标识符来代表,那么编译器会给出一个“generic array creation”的错误。

清单11:当Varargs遇上泛型

private static   <T> void testVarargs(  T... args) {//编译出错 
} 

造成这个现象的原因在于J2SE 1.5中的泛型机制的一个内在约束——不能拿用标识符来代表的类型来创建这一类型的实例。在出现支持没有了这个约束的Java版本之前,对于这个问题,基本没有太好的解决办法。

不过,传统的“用数组包裹”的做法,并不受这个约束的限制。

清单12:可以编译的变通做法

private static   <T> void testVarargs(  T[] args) { 
    for (int i = 0; i < args.length; i++) { 
        System.out.println(args[i]); 
    } 
} 

8. 重载中的选择问题

Java支持“重载”的机制,允许在同一个类拥有许多只有形参列表不同的方法。然后,由编译器根据调用时的实参来选择到底要执行哪一个方法。

传统上的选择,基本是依照“特殊者优先”的原则来进行。一个方法的特殊程度,取决于为了让它顺利运行而需要满足的条件的数目,需要条件越多的越特殊。

在引入Varargs机制之后,这一原则仍然适用,只是要考虑的问题丰富了一些——传统上,一个重载方法的各个版本之中,只有形参数量与实参数量正好一致的那些有被进一步考虑的资格。但是Varargs机制引入之后,完全可以出现两个版本都能匹配,在其它方面也别无二致,只是一个实参个数固定,而一个实参个数可变的情况。

遇到这种情况时,所用的判定规则是“实参个数固定的版本优先于实参个数可变的版本”。

清单13:实参个数固定的版本优先

public class OverloadingSampleA { 
    public static void main(String[] args) { 
        testOverloading(  1);//打印出A 
        testOverloading(  1, 2);//打印出B 
        testOverloading(  1, 2, 3);//打印出C 
    } 
    private static void testOverloading(  int i) { 
        System.out.println("A"); 
    } 
    private static void testOverloading(  int i, int j) { 
        System.out.println("B"); 
    } 
    private static void testOverloading(  int i, int... more) { 
        System.out.println("C"); 
    } 
} 

如果在编译器看来,同时有多个方法具有相同的优先权,它就会陷入无法就到底调用哪个方法作出一个选择的状态。在这样的时候,它就会产生一个“reference to 被调用的方法名 is ambiguous”的编译错误,并耐心的等候作了一些修改,足以免除它的迷惑的新源代码的到来。

在引入了Varargs机制之后,这种可能导致迷惑的情况,又增加了一些。例如现在可能会有两个版本都能匹配,在其它方面也如出一辙,而且都是实参个数可变的冲突发生。

清单14:左右都不是,为难了编译器

public class OverloadingSampleB { 
    public static void main(String[] args) { 
        testOverloading(1, 2, 3);//编译出错 
    } 
    private static void testOverloading(  Object... args) { 
    } 
    private static void testOverloading(  Object o, Object... args) { 
    } 
} 

另外,因为J2SE 1.5中有“Autoboxing/Auto-Unboxing”机制的存在,所以还可能发生两个版本都能匹配,而且都是实参个数可变,其它方面也一模一样,只是一个能接受的实参是基本类型,而另一个能接受的实参是包裹类的冲突发生。

清单15:Autoboxing/Auto-Unboxing带来的新问题

public class OverloadingSampleC { 
    public static void main(String[] args) { 
        /* 编译出错 */ 
        testOverloading(  1, 2); 
        /* 还是编译出错 */ 
        testOverloading(  new Integer(1), new Integer(2)); 
    } 
    private static void testOverloading(  int... args) { 
    } 
    private static void testOverloading(  Integer... args) { 
    } 
} 

9. 归纳总结

和“用数组包裹”的做法相比,真正的实参个数可变的方法,在调用时传递参数的操作更为简单,含义也更为清楚。不过,这一机制也有它自身的局限,并不是一个完美无缺的解决方案。

参考资源

中科蓝讯蓝牙开发:从源码到固件的自动化构建链路解析 本文详细解析了中科蓝讯AB530X蓝牙芯片从源码到最终固件的完整自动化构建链路。通过剖析prebuild.bat、GCC编译、postbuild.bat等关键环节,阐述了资源打包、配置生成、代码编译与固件合成的全过程,并重点介绍了如何实现一键编译与自动下载,为开发者高效进行嵌入式蓝牙开发提供清晰指南。 阅读详情

相关推荐

手把手教你用ComfyUI搭建高效AI绘画工作流:从基础到高级技巧

本文详细介绍了如何使用ComfyUI构建高效的AI绘画工作流,从基础配置到高级技巧全面覆盖。通过模块化设计,ComfyUI显著提升显存利用率和创作灵活性,适合从新手到专业用户。文章包含部署指南、工作流搭建、性能优化及行业应用案例,帮助读者快速掌握AI绘画核心技术。

7up55的博客 719

关于 method (Object ... params )

看公司的平台代码,看到这样一个方法 public DataSet query(String sql, Object... para){ //opreation }   Object... param 第一次看到这样的用法,难道这是公司自定义的数据类型? 在群里问了句谁知道? 一个新人过来,给我做了个事例,说这是java的新特性== 变长数组。 直接让我汗颜,自认为对java基础有较高掌...

qdpurple 619

菲涅尔波带片

菲涅尔波带片的简介,以及matlab绘制

Bestchinese的博客 1万+

java使用省略号代替多参数(参数类型... 参数名)

定义参数个数可变的方法 public class StringTest { public static void main(String[] args) { //test1(); //test1("a"); test1("C","B"); } public static void test1(String... args) { System.out.println("le...

expect521的博客 1252

十二、基于FPGA实现slave SelectMAP配置逻辑

slave SelectMAP配置

weixin_41838250的博客 8755

推荐系统公平性之流行度偏差(fairness in recommender systems -- popularity bias)

主要参考论文:《The Unfairness of Popularity Bias in Recommendation》 RMSE@RecSys 2019 流行度偏差是什么 先定义流行物品和非流行物品。下图是(Movielens 1M)数据集中物品的评分情况。 图的横坐标表示不同物品,纵坐标表示物品的评分次数。可以看出只有少部分物品得到了很多的评分,大部分曲线尾部的物品都只有少量的评分,我们也把这部分物品称为长尾物品。在本文中,我们取曲线的前20%对应的物品为流行物品,剩余的为非流行物品(长尾物品)。 然

beilizhang的博客 5277

[J2SE 1.5]逐渐挖掘Varargs

.article {padding:1em;background:white;}.abstract {padding:1em 1ex 1em 2em;}.author, .date {padding:0.5ex 0 0 0;}h1.title, h2.major, h3.minor, h3.listing { margin:1ex 2px 1ex;color:#0066CC

孙海涛的谈笑间 1万+

NVIDIA 2025 Board Design Engineer 校招笔试全解析:从基础门电路到理想放大器设计

本文详细解析了NVIDIA 2025届板级设计工程师校招笔试的核心考点与解题策略。内容涵盖从基础门电路、CMOS实现NOR门,到开关电源CCM/DCM模式波形分析与效率计算,以及理想运放电路设计与稳定性优化。旨在帮助考生构建硬件知识体系,掌握工程思维,顺利通过NVIDIA Board Design Engineer校招笔试。

weixin_29172201的博客 196

java可变参数省略号…

一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法。在方法声明中,在指定参数类型后加一个省略号(…

budaoweng0609的博客 1209

【WorkBuddy专栏25】如何选择大模型——积分消耗、用途场景、选型决策全指南

【WorkBuddy专栏25】如何选择大模型——积分消耗、用途场景、选型决策全指南

AI人人懂 940

OpenClaw进阶实战(十二):电商比价工作流(一)——数据采集与竞品监控

本文介绍了基于OpenClaw的电商比价系统实现方案。该系统可自动化监控淘宝、京东、拼多多等平台的竞品价格波动,包含以下核心功能: 多平台价格采集:通过各平台官方API(淘宝客、京东联盟、多多进宝)获取商品价格,并提供模拟数据模式便于测试 数据存储与分析:使用SQLite存储历史价格数据,支持查询最近价格和价格变化趋势 模块化设计:采用技能化架构,分离了平台适配层(淘宝/京东/拼多多)、数据存储层和核心业务逻辑 扩展性:预留了价格波动告警接口(钉钉通知),为后续动态调价提供数据支撑 系统特点: 支持真实AP

PeterPan的博客 214

可变参数,例如:Object... params

参考链接:https://blog.csdn.net/yuming226/article/details/80558469

细水长流 2802

《Android系统开发中高级定制专栏导读》

欢迎来到【Android 中高级系统定制】专栏!在这里,将深入探讨Android系统开发与定制的方方面面,涵盖从权限管理、驱动开发到系统应用配置等多个领域。

我其实什么都不会 1579

java函数参数 省略号_[转] java使用省略号代替多参数.pdf

[转] java使用省略号代替多参数.pdf还剩7页未读,继续阅读下载文档到电脑,马上远离加班熬夜!亲,喜欢就下载吧,价低环保!内容要点:J2SE 1.5提供了“Varargs”机制。借助这一机制,可以定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。本文介绍这一机制的使用方法,以及这一机制与数组、泛型、重载之间的相互作用时的若干问题。到J2SE 1.4为止,一直无...

weixin_33603813的博客 459

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

java学习---java使用省略号代替多个参数

J2SE 1.5提供了“Varargs”机制。借助这一机制,可以定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。本文介绍这一机制的使用方法,以及这一机制与数组、泛型、重载之间的相互作用时的若干问题。 到J2SE 1.4为止,一直无法在Java程序里定义实参个数可变的方法——因为Java要求实参(Arguments)和形参(Parameters)的数量和类型都必须逐...

ihan.的博客 457

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

java使用省略号代替多参数

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34005042的博客 136

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

java函数形参之 ... 省略号

补发:2019-7-30 学习日记之Java基础 java函数形参之 … 省略号 有看过java反射相关一些源码的同学应该会看到这样的形参 public static void method(String... str){// ... 是什么意思?有什么用呢? } 写个demo public static void main(String[] args) { String[]...

博客 2150

java 使用省略号 代替多个相同类型的参数 重载方法 Varargs

发现很多牛人写出来的工具类,都有 xxx(String... s){} 这样的方法,简单学了一下,下面是测试的代码,最简单的例子: public class TestVarargs { public static void s(int[] vs) { System.out.println("s(int[] vs)"); for(int i : vs) { System.out...

u013276512的博客 2630

java 参数代替所有类_廖雪峰JAVA课程中涉及的类定义用省略号代替参数

public class Main {public static void main(String[] args) {// 给一个有普通收入、工资收入和享受国务院特殊津贴的小伙伴算税:Income[] incomes = new Income[] {new Income(3000),new Salary(7500),new StateCouncilSpecialAllowance(15000)};...

weixin_39556064的博客 192

java语法

省略号代替多参数(参数类型... 参数名)

Osborn的博客 217
上一篇: Android之SurfaceView
下一篇: Server at localhost was unable to start within 45 seconds解决办法
hxwhou
博客等级 码龄16年 100粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值