Java方法的进一步讲解
1. Java方法:分解和委派任务的艺术
考虑下面的Java代码
例1. 第一个method程序:创建和调用方法
TheFirstMethod.java
public class TheFirstMethod {
public static void main(String[] args) {
sing(); // 调用singASong()方法:Hey那个叫sing的,该你运行了
}
static void sing() { //这里的void表示执行完后不需要返回任何数据
System.out.println("There's a calm surrender\n"
+ "To the rush of day\n"
+ "When the heat of a rolling wind\n"
+ "Can be turned away... \n");
}
}
可以看到,main()函数不想自己唱歌,于是把唱歌的任务委派给了叫sing()
的方法。static void sing()
里的void
表示这个方法执行完后,不需要交付给main()
方法任何数据。
这样做的好处在于:如果想多唱几首,我们只需要在main()
方法里多次调用这个方法即可:
例2. 第一个method程序:多次调用方法
public class TheFirstMethod {
public static void main(String[] args) {
sing(); // 调用sing()方法:Hey那个叫sing的,该你运行了
sing(); // 再运行一次
sing(); // 再来一首
}
static void sing() { //这里的void表示执行完后不需要返回任何值
System.out.println("There's a calm surrender\n"
+ "To the rush of day\n"
+ "When the heat of a rolling wind\n"
+ "Can be turned away... \n");
}
}
但是很遗憾,在这个简单的例子中,singASong()
这个方法只会唱同一首歌 :( 。
当然,构建方法,把部分任务分配出去可以让程序结构井然有序。比如现在有一台演出,有两个节目,先唱一首歌,后跳一支舞。那么,我们可以分别构建唱歌和跳舞的方法,用main函数控制整个流程。代码如下: 例3. 第一个method程序:流程化调用多个方法
public class TheFirstMethod {
public static void main(String[] args) {
sing(); // 调用sing()方法:Hey那个叫sing的,该你运行了
System.out.println("A break.\n");
dance(); //调用dance()方法:现在轮到你运行了
}
static void sing() { //这里的void表示执行完后不需要返回任何值
System.out.println("There's a calm surrender\n"
+ "To the rush of day\n"
+ "When the heat of a rolling wind\n"
+ "Can be turned away... \n");
}
static void dance(){
System.out.println("Da Da Da...\n");
}
}
当导演改了想法,想把dance放到sing之前,只需要把main()
方法里的sing()
和dance()
交换顺序就好。
2. 传入参数:告知任务需要的信息
有时候,我们在分派一个任务给其他人的时候,需要告诉他一个消息作为指引,比如:你是一个boss,现在安排部下给客户发送祝福短信,当然你需要告诉你的部下给谁发。我们可以写如下Java代码:
(1) 传入单个参数
例4. 向方法传递一个参数
MethodWithArguments.java
public class MethodWithArguments {
public static void main(String[] args) {
sendGreetingsTo("L. Zhang"); //调用sentGreetingsTo()方法,并传入参数"L. Zhang"
}
static void sendGreetingsTo(String customer) {
String greetingString = String.format("Dear %s, wish you have a happy TU year.", customer);
// 模板化字符串,""里是一个模板,%s为字符串占位符,Java会将后面的参数customer替换%s,得到最终字符串
System.out.println(greetingString);
}
}
- 上面的代码中,
main()
方法通过给sendGreetingsTo()
方法传递一个参数"L. Zhang",通知其给谁发祝福信息。sendGreetingsTo()
方法定义它需要什么类型的参数,这里是一个字符串。 sendGreetingsTo()
获取到传入的参数后,将其编入祝福短信中,并且显示给客户。- 这样做的好处是:如果需要给多个customers发送祝福短信,我们只需要反复调用
sendGreetingsTo()
方法,通过传入不同的参数,给不同的customer发送消息。例如:
例5. 向方法传递一个参数:循环调用方法
public class MethodWithArguments {
public static void main(String[] args) {
String[] customers = {"L. Zhang", "Dr. Dong", "Dr. Huang"}; //创建一个包含多个customer的数组
for(String customer : customers) { //对每个customer
sendGreetingsTo(customer); //调用发送祝福短信的方法
}
}
static void sendGreetingsTo(String customer) {
String greetingString = String.format("Dear %s, wish you have a happy TU year.", customer);
System.out.println(greetingString);
}
}
(2) 传入多个参数
在上面的例子中,如果main()
方法不仅要通知发送greetings的方法要给谁发greetings,同时需要告诉他落款是什么(比如*公司),那么发送greetings的方法就需要接受两个参数,一个是customer,另一个是落款。
我们在上面的例子添加一个新的方法sendGreetingsWithSuffix()
方法来实现这一点。(以下代码忽略了sendGreetingsTo()
方法,以使得代码简洁)
例6. 向方法传递多个参数
public class MethodWithArguments {
public static void main(String[] args) {
String mySuffix = "RIEM .SWUFE .EDU";
String myCustomer = "L. Zhang";
sendGreetingsWithSuffix(myCustomer, mySuffix); //调用发送消息的方法,并传入给谁发(第一个参数),和落款(第二个参数)
}
static void sendGreetingsWithSuffix(String customer, String suffix) {
String greetingString = String.format("Dear %s, wish you have a happy TU year\n"
+ "\tGreetings from %s \n", customer, suffix);
System.out.println(greetingString);
}
}
我们甚至可以传入更多参数,只需要在实际执行发送greetings的方法里,定义相应的参数需求。
3. 返回值:通知结果
在上面的例子中,如果main()
给sendGreetings()
安排任务后,想要知道greetings的发送结果,那么就需要sendGreetings()
返回给main()
一个东西,通知结果。这个返回的东西,就是返回值。
以下的例子在例1的基础上进行改进:
- 发送greetings的方法名修改为
sendGreetings()
,以便和例1中的的方法区分; - 发送greetings的方法在执行完后,将给
main()
方法返回一个布尔值(true
orfalse
),来告诉main()
方法发送的结果。
例7. 方法返回一个值
public class MethodWithArguments {
public static void main(String[] args) {
String myCustomer = "L Zhang";
boolean isGreetingsSent = sendGreetings(myCustomer);
System.out.printf("main(): Is greeting message sent to %s? %b", myCustomer, isGreetingsSent);
//printf() 为模板化打印,String.format(),%s 为字符串占位符,%b为布尔值占位符,打印的时候会被后面的参数myCustomer, isGreetingsSent替换。
}
/*
* sendGreetings()方法负责发送greetings消息;
* 需要一个参数:uname,这里是客户的名字, String类型;
* 执行完返回一个布尔值:通知调用它的方法是否成功发送。
*/
static boolean sendGreetings(String uname) {
String greetingString = String.format("sendGreetings(): Dear %s,"
+ "wish you have a happy TU year\n", uname);
System.out.println(greetingString);
return true; //return 后就是要返回的数值,需要和方法定义的返回值一致,此处为boolean值
}
}
4. 广阔天地:具有返回值的方法
方法的返回值赋予了方法灵魂。通常我们调用一个方法,是因为我们想要一个结果,而返回值就是那个我们想要得到的结果。
比如:我们需要一个方法,来计算投资者赎回投资的时候,连本带息需要给TA多少钱。
例8. 具有返回值的方法:给你一个结果
RedemptionManager.java
public class RedemptionManager {
public static void main(String[] args) {
/*
* 指派calculateRedemption来计算总赎回金额,
* 提供其需要的参数principal和return rate,
* 然后将其返回值存储在变量totalMoneyForInvestor中
*/
double totalMoneyForInvestor = calculateRedemption(1000000., 0.04);
System.out.println("Total amount of redemption is " + totalMoneyForInvestor);
}
/*
* calculate the total amount for a redemption
* Inputs: principal:double; returnRate:double
* Output: total amount to be redeemed.
*/
static double calculateRedemption(double principal, double interestRate) {
double totalAmount = principal * (1 + interestRate);
return totalAmount;
}
}
以上例子中,通常principal和returnRate是从数据库读出来的,我们可以模拟这个过程。
public class RedemptionManager {
public static void main(String[] args) {
// 先定义两个变量,来存储从其他地方获取到的本金和利率;此处直接给值来模拟
double customerPrincipal = 1000000.;
double currentReturnRate = 0.04;
//将上面两个变量(的值)传入calculateRedemption()方法,来计算总额
double totalMoneyForInvestor = calculateRedemption(customerPrincipal, currentReturnRate);
System.out.println("Total amount of redemption is " + totalMoneyForInvestor);
}
static double calculateRedemption(double principal, double interestRate) {
double totalAmount = principal * (1 + interestRate);
return totalAmount;
}
}