37-参数和返回值是怎么传递的
原创2025年1月6日大约 6 分钟...约 1727 字
1. 参数和返回值是怎么传递的
- 参数和方法里的局部变量可以认为是一样的东西。只是在方法调用之前,会用实参给参数的形参赋值;
- 发生在代码块里的,就让它留在代码块里。方法执行完毕,参数和方法的局部变量的数据就会被删除回收。就好像演草纸,作用是计算一个值,算好之后,演草纸就可以扔了;
- 调用一个有返回值的方法时,就好像访问一个成员变量;
- 看代码,学习参数传递;
- 看代码,学习返回值的传递;
2. 代码示例
RunLittleSupperMarketAppMainV2
package com.geekbang;
import com.geekbang.supermarket.LittleSuperMarket;
import com.geekbang.supermarket.MerchandiseV2;
public class RunLittleSupperMarketAppMainV2 {
public static void main(String[] args) {
// 创建一个小超市类
LittleSuperMarket littleSuperMarket = new LittleSuperMarket();
// 依次给超市的名字,地址,停车位赋值
littleSuperMarket.superMarketName = "有家小超市";
littleSuperMarket.address = "浦东新区世纪大道666号";
littleSuperMarket.parkingCount = 100;
// 给超市200种商品
littleSuperMarket.merchandises = new MerchandiseV2[3];
// 统计用的数组
littleSuperMarket.merchandiseSold = new int[littleSuperMarket.merchandises.length];
// 为了使用方便,创建一个商品数组引用,和littleSuperMarket.merchandises指向同一个数组对象
MerchandiseV2[] all = littleSuperMarket.merchandises;
MerchandiseV2 giftNoodle = new MerchandiseV2();
giftNoodle.name = "赠品-面条";
giftNoodle.count = 2000;
giftNoodle.purchasePrice = 5;
giftNoodle.soldPrice = 0.05;
giftNoodle.id = "GIFT001";
MerchandiseV2 giftBowl = new MerchandiseV2();
giftBowl.name = "赠品-碗";
giftBowl.count = 2000;
giftBowl.purchasePrice = 8;
giftBowl.soldPrice = 0.08;
giftBowl.id = "GIFT002";
// 遍历并给200种商品赋值
for (int i = 0; i < all.length; i++) {
// 创建并给商品的属性赋值
MerchandiseV2 m = new MerchandiseV2();
m.name = "商品" + i;
m.count = 200;
m.purchasePrice = (i + 1) * 100;
m.soldPrice = m.purchasePrice * (1 + Math.random());
m.id = "ID" + i;
m.gift = giftNoodle;
// 用创建的商品,给商品数组的第i个引用赋值,all和小超市的商品数组引用指向的是同一个数组对象
all[i] = m;
m.describe();
}
int index = 0;
MerchandiseV2 m = littleSuperMarket.merchandises[index];
int c = 7;
// --------- 参数 ---------
// >> TODO 参数的传递,其实就是赋值。左边是形参,右边是括号里的实参。
// TODO 类似于buy(int countToBuy = (c + 2) * 5)
// >> TODO 参数本身可以是一个表达式,只要表达式的值类型可以和参数类型匹配就可以
double totalCost = m.buy((c + 2) * 5);
System.out.println("商品总价为:" + totalCost);
// >> TODO 对于引用类型,参数同样是一个表达式
boolean biggerThan = m.totalValueBiggerThan(littleSuperMarket.merchandises[index + 1]);
System.out.println(biggerThan);
// >> TODO 方法里的代码并不能改变实参的值。
// TODO 方法里使用的参数相当于一个局部变量。使用方法前,会用实参给局部变量赋值。
MerchandiseV2 paramRef = littleSuperMarket.merchandises[2];
int paramPrime = 7;
System.out.println("调用前");
System.out.println(paramPrime);
System.out.println(paramRef);
m.willOutsideValueChangeIfParameterValueChangeHerePrime(paramPrime);
// 效果类似如下代码
// 形参实参赋值:int intVal = paramPrime;
// 方法里执行:intVal = 99999999;
m.willOutsideValueChangeIfParameterValueChangeHereRef(paramRef);
// 效果类似如下代码
// 形参实参赋值:MerchandiseV2 m2 = paramRef;
// 方法里执行:m2 = gift;
System.out.println("调用后");
System.out.println(paramPrime);
System.out.println(paramRef);
// ------ 返回值 -------
// >> TODO 可以把有返回值的方法,当成一个成员变量,当成一个类型为返回值类型的成员变量
// TODO 关注于返回值并忽略方法执行的部分,使用返回值,就好像在使用一个成员变量
double soldPrice = m.getSoldPrice();
System.out.println(soldPrice);
m.describe();
// >> TODO 给返回值赋值,并不会影响用来充当返回值的变量
System.out.println("调用getGiftAndHowCanOutsideChangeIt和getSoldPrice之前");
m.describe();
MerchandiseV2 giftOfM = m.getGiftAndHowCanOutsideChangeIt();
giftOfM = giftBowl;
double mSoldPrice = m.getSoldPrice();
mSoldPrice = 9999999;
System.out.println("能改变m本身的gift吗?能改变m的soldPrice吗?");
m.describe();
}
}
MerchandiseV2
package com.geekbang.supermarket;
public class MerchandiseV2 {
public String name;
public String id;
public int count;
public double soldPrice;
public double purchasePrice;
// describe方法变了一下
public void describe() {
System.out.println("商品名字叫做" + name + ",id是" + id + "。 商品售价是" + soldPrice
+ "。商品进价是" + purchasePrice + "。赠品是" + gift.name + "。价值" + gift.purchasePrice);
}
public double calculateProfit() {
double profit = soldPrice - purchasePrice;
if (profit <= 0) {
return 0;
}
return profit;
}
// >> TODO 参数是定义在方法名字后面的括号里的
// >> TODO 参数定义的规范和变量一样,都是类型名字加标识符,这里的标识符我们叫做参数名。
// >> TODO 方法体中的代码可以使用参数
// >> TODO 参数的值在调用方法的时候需要给出,有的资料叫做实参(实际参数)
// >> TODO 对应的,方法定义这里的参数,叫做形参(形式参数)
public double buy(int countToBuy) {
if (count < countToBuy) {
System.out.println("商品库存不够");
return -1;
}
System.out.println("商品单价为" + purchasePrice);
int fullPriceCount = countToBuy / 2 + countToBuy % 2;
int halfPriceCount = countToBuy - fullPriceCount;
double totalCost = purchasePrice * fullPriceCount + halfPriceCount * purchasePrice / 2;
count -= countToBuy;
return totalCost;
}
// >> TODO 一个方法可以有多个参数,多个参数之间用逗号隔开
public double buyAndPrintLeft(int countToBuy, boolean printLeft) {
if (count < countToBuy) {
System.out.println("商品库存不够");
if (printLeft) {
System.out.println("商品剩余库存为" + count);
}
return -1;
}
System.out.println("商品单价为" + purchasePrice);
int fullPriceCount = countToBuy / 2 + countToBuy % 2;
int halfPriceCount = countToBuy - fullPriceCount;
double totalCost = purchasePrice * fullPriceCount + halfPriceCount * purchasePrice / 2;
count -= countToBuy;
if (printLeft) {
System.out.println("商品剩余库存为:" + printLeft);
}
return totalCost;
}
// >> TODO 参数可以是任何类型,包括自定义类型,甚至是自己的类型都没问题
public boolean totalValueBiggerThan(MerchandiseV2 merchandiseV2) {
return count * purchasePrice > merchandiseV2.purchasePrice * merchandiseV2.count;
}
// >> TODO 参数可以是任何类型,包括自定义类型,甚至是自己的类型都没问题
public boolean isTheBiggestTotalValueOne(LittleSuperMarket littleSuperMarket) {
double totalValue = count * purchasePrice;
for (int i = 0; i < littleSuperMarket.merchandises.length; i++) {
MerchandiseV2 m = littleSuperMarket.merchandises[i];
double newTotalValue = m.count * m.purchasePrice;
if (totalValue < newTotalValue) {
// >> TODO 执行到return的时候,方法直接结束,不管是不是在循环中,是在第几层循环中。
return false;
}
}
return true;
}
// ---------------------------新增加的内容---------------------------
public MerchandiseV2 gift;
public double getSoldPrice() {
return soldPrice;
}
public String getName() {
return name;
}
public MerchandiseV2 getGiftAndHowCanOutsideChangeIt() {
return gift;
}
public void willOutsideValueChangeIfParameterValueChangeHereRef(MerchandiseV2 m2) {
m2 = gift;
}
public void willOutsideValueChangeIfParameterValueChangeHerePrime(int intVal) {
intVal = 99999999;
}
public void changeToTheSameGift(MerchandiseV2 m2) {
m2.gift = gift;
}
}
LittleSuperMarket
package com.geekbang.supermarket;
public class LittleSuperMarket {
public String superMarketName;
public String address;
public int parkingCount;
public double incomingSum;
public MerchandiseV2[] merchandises;
public int[] merchandiseSold;
public MerchandiseV2 getBiggestProfitMerchandise() {
MerchandiseV2 curr = null;
for (int i = 0; i < merchandises.length; i++) {
MerchandiseV2 m = merchandises[i];
// 这个逻辑有问题吗?相同的利润怎么判断?
if (curr == null || curr.calculateProfit() < m.calculateProfit()) {
curr = m;
}
}
return curr;
}
}
欢迎关注我公众号:AI悦创,有更多更好玩的等你发现!
公众号:AI悦创【二维码】

AI悦创·编程一对一
AI悦创·推出辅导班啦,包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然,还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线,随时响应!微信:Jiabcdefh
C++ 信息奥赛题解,长期更新!长期招收一对一中小学信息奥赛集训,莆田、厦门地区有机会线下上门,其他地区线上。微信:Jiabcdefh
方法一:QQ
方法二:微信:Jiabcdefh
