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 or false),来告诉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;
	}
}