Java方法参数、可变参数、参数绑定

📅 2026/8/13 10:07:28
Java方法参数、可变参数、参数绑定
方法参数方法可以包含 0 个或任意个参数。方法参数用于接收传递给方法的变量值。调用方法时必须严格按照参数的定义一一传递。例如classPerson{// ... 其他代码publicvoidsetNameAndAge(Stringname,intage){// ... 方法体}}调用这个setNameAndAge()方法时必须有两个参数且第一个参数必须为String第二个参数必须为intPersonmingnewPerson();ming.setNameAndAge(Xiao Ming);// 编译错误参数个数不对ming.setNameAndAge(12,Xiao Ming);// 编译错误参数类型不对可变参数1. 场景请客吃饭点菜传姓名列表背景你写了一个Dinner类要邀请朋友来吃饭。1.1 用数组写法繁琐classDinner{privateString[]guests;publicvoidsetGuests(String[]guests){this.guestsguests;}}publicclassMain{publicstaticvoidmain(String[]args){DinnerdinnernewDinner();// 请3个人必须手动 new String[]dinner.setGuests(newString[]{张三,李四,王五});// 请2个人还是得 new String[]dinner.setGuests(newString[]{赵六,孙七});// 就请1个人依然要 new String[]dinner.setGuests(newString[]{周八});// 谁也不请空桌还是得 new String[0]dinner.setGuests(newString[0]);}}痛点每次都要写new String[]{}请 3 个人要写请 1 个人也要写代码冗余。1.2 用可变参数简洁classDinner{privateString[]guests;publicvoidsetGuests(String...guests){// 参数类型后加 ...this.guestsguests;}}publicclassMain{publicstaticvoidmain(String[]args){DinnerdinnernewDinner();// 请3个人直接传名字dinner.setGuests(张三,李四,王五);// 请2个人直接传名字dinner.setGuests(赵六,孙七);// 请1个人直接传名字dinner.setGuests(周八);// 谁也不请括号里留空即可dinner.setGuests();// 代码简洁}}参数绑定调用方把参数传递给实例方法时调用时传递的值会按参数位置一一绑定。2.1 基本类型参数绑定我们先观察一个基本类型参数的传递// 基本类型参数绑定publicclassMain{publicstaticvoidmain(String[]args){PersonpnewPerson();intn15;// 在 main 方法的栈帧中变量 n 存储值 15p.setAge(n);// 传入 n 的值将 n 的副本 15 赋值给参数 ageSystem.out.println(p.getAge());// 15n20;// 将 n 的值改为 20System.out.println(p.getAge());// 输出是 15 还是 20?}}classPerson{privateintage;publicintgetAge(){returnthis.age;}publicvoidsetAge(intage){this.ageage;}}运行代码从结果可知修改外部的局部变量n不影响实例p的age字段。原因setAge()方法获得的参数复制了n的值因此p.age和局部变量n互不影响。核心结论基本类型参数的传递是调用方值的复制。双方各自的后续修改互不影响。通俗比喻“按值传递”相当于传递复印件的复印件。外面n是原件值 15里面age是复印件值 15。你后来把原件涂改成 20复印件依然是 15两者独立。2.2 引用类型参数绑定另一个传递引用参数的例子// 引用类型参数绑定publicclassMain{publicstaticvoidmain(String[]args){PersonpnewPerson();String[]fullnamenewString[]{Homer,Simpson};p.setName(fullname);// 传入 fullname 数组的引用System.out.println(p.getName());// Homer Simpsonfullname[0]Bart;// 修改 fullname 数组的第一个元素为 BartSystem.out.println(p.getName());// 输出是 Homer Simpson 还是 Bart Simpson?}}classPerson{privateString[]name;publicStringgetName(){returnthis.name[0] this.name[1];}publicvoidsetName(String[]name){this.namename;}}注意到setName()的参数是一个数组。一开始把fullname数组传进去然后修改fullname数组的内容结果发现实例p的字段p.name也被修改了核心结论引用类型参数的传递调用方的变量和接收方的参数变量指向的是同一个对象。双方任意一方对这个对象的修改都会影响对方。2.3 深入理解String 类型的特殊情况有了上面的结论我们再看一个特殊的例子// 引用类型参数绑定String 类型publicclassMain{publicstaticvoidmain(String[]args){PersonpnewPerson();StringbobBob;p.setName(bob);// 传入 bob 变量引用System.out.println(p.getName());// BobbobAlice;// 将 bob 变量重新赋值System.out.println(p.getName());// 输出是 Bob 还是 Alice?}}classPerson{privateStringname;publicStringgetName(){returnthis.name;}publicvoidsetName(Stringname){this.namename;}}不要怀疑引用参数绑定的机制请解释为什么上面的代码两次输出都是Bob。bobAlice;// 关键这句话不是去修改 Bob 这个字符串对象String 是不可变的// 它是在堆中创建了一个新的字符串对象 Alice假设地址 0x300// 然后把 main 方法里的变量 bob从指向 0x200 (Bob) 改为指向 0x300 (Alice)// 此时bob 指向 0x300 (Alice)但 p.name 依然指向 0x200 (Bob)// 因此p.getName() 仍然返回 Bob// 若想修改 p.name需要调用p.setName(Alice);3. 练习给Person类增加getAge/setAge方法publicclassMain{publicstaticvoidmain(String[]args){PersonmingnewPerson();ming.setName(小明);System.out.println(ming.getName());ming.setAge(12);System.out.println(ming.getAge());}}classPerson{privateStringname;privateintage;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.namename;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.ageage;}}声明本文内容为本人基于 廖雪峰 Java 教程 进行实操学习后的个人笔记与代码实践记录。文中所有知识点、代码示例及讲解均源自上述网站著作权归原作者廖雪峰及其团队所有。本文仅用于个人学习总结与知识分享不涉及任何商业用途。如涉及侵权请联系删除。