Java对象间通信原理及转账服务代码实现疑问
我刚学完Java方法相关课程,现在在做转账服务程序的作业。我定义了CurrencyConverter和MoneyTransferService两个类,其中MoneyTransferService需要复用CurrencyConverter的功能。我在MoneyTransferService的main方法里创建了该类的对象,想让它调用CurrencyConverter对象的服务,但搞不懂Java里对象之间的通信机制。另外,注释掉的代码能正常运行,但我不明白为什么必须创建对象才能调用另一个对象的服务。
我的代码
MoneyTransferService.java
class MoneyTransferService { public static void main(String[] args) { CurrencyConverter cc = new CurrencyConverter(); /*double amount = cc.computeTransferAmount(0, 1000); double fee = cc.computeTransferFee(0, 1000); System.out.println("Transfer Amount: " + amount); System.out.println("Transfer Fee: " + fee);*/ MoneyTransferService transferService = new MoneyTransferService(); double transferAmount = transferService.computeTransferAmount(0, 1000); double transferFee = transferService.computeTransferFee(0, 1000); System.out.println("Transfer Amount: " + transferAmount); System.out.println("Transfer Fee: " + transferFee); } }
CurrencyConverter.java
public class CurrencyConverter { // 不同货币相对于1美元的汇率 double[] exchangeRates = new double[] {63.0, 3.0, 3.0, 595.5, 18.0, 107.0, 2.0}; void setExchangeRates(double[] rates) { exchangeRates = rates; } void updateExchangeRate(int countryIndex, double newVal) { exchangeRates[countryIndex] = newVal; } double getExchangeRate(int countryIndex) { return exchangeRates[countryIndex]; } double computeTransferAmount(int countryIndex, double amount) { return amount * getExchangeRate(countryIndex); } double computeTransferFee (int countryIndex, double amount) { return computeTransferAmount(countryIndex, amount) * 0.02; } void printCurrencies() { System.out.println("\nrupee: " + exchangeRates[0]); System.out.println("dirham: " + exchangeRates[1]); System.out.println("real: " + exchangeRates[2]); System.out.println("chilean_peso: " + exchangeRates[3]); System.out.println("mexican_peso: " + exchangeRates[4]); System.out.println("_yen: " + exchangeRates[5]); System.out.println("$australian: " + exchangeRates[exchangeRates.length-1]); } }
问题解答
1. 为什么必须创建对象才能调用另一个对象的服务?
Java是面向对象编程语言,类相当于一个“模板”,对象才是这个模板实例化出的“实体”。CurrencyConverter里的exchangeRates是实例变量(非static),每个CurrencyConverter对象都有自己的汇率数组副本,而computeTransferAmount这类方法依赖这个数组运行。如果不创建对象,实例变量不会在内存中生成,依赖它们的实例方法自然无法调用。
你注释掉的代码能运行,正是因为创建了CurrencyConverter的对象cc,通过这个对象才能访问它的实例方法。而你当前写的transferService.computeTransferAmount(...)会直接报错——MoneyTransferService类里根本没定义这个方法,你想复用CurrencyConverter的功能,但写法上没建立两者的关联。
2. MoneyTransferService如何复用CurrencyConverter的功能?
要实现复用,最常用的方式是组合(Composition):在MoneyTransferService内部持有CurrencyConverter的对象,通过这个引用调用对方的方法。修改后的代码如下:
class MoneyTransferService { // 持有CurrencyConverter对象,作为依赖服务 private CurrencyConverter converter; // 构造方法初始化依赖 public MoneyTransferService() { this.converter = new CurrencyConverter(); } // 对外提供统一接口,内部复用CurrencyConverter的功能 public double computeTransferAmount(int countryIndex, double amount) { return converter.computeTransferAmount(countryIndex, amount); } public double computeTransferFee(int countryIndex, double amount) { return converter.computeTransferFee(countryIndex, amount); } public static void main(String[] args) { MoneyTransferService transferService = new MoneyTransferService(); double transferAmount = transferService.computeTransferAmount(0, 1000); double transferFee = transferService.computeTransferFee(0, 1000); System.out.println("Transfer Amount: " + transferAmount); System.out.println("Transfer Fee: " + transferFee); } }
3. 简单理解Java对象间的通信机制
对象间通信的本质就是一个对象持有另一个对象的引用,通过这个引用调用对方的方法或访问属性。就像现实中你要找银行换汇,得先找到银行(持有银行对象的引用),再告诉银行换汇需求(调用换汇方法),最后拿到结果。
在上面的修改代码里,MoneyTransferService持有CurrencyConverter的引用converter,当调用transferService的方法时,它会通过这个引用调用converter的方法,完成功能复用,这就是Java对象间通信的基本逻辑。
内容的提问来源于stack exchange,提问作者Kekicbj

