嗨,我有一个基本的代码特性问题,如下所示。当我更改代码时,我得到了特殊的输出。下面的程序给出了正确的输出,因为我们知道Java默认情况下不支持Double Dispatch。请求您查看以下代码并查看输出。之后我修改了代码并获得了奇怪的输出。
import java.util.ArrayList;
import java.util.List;
class SavingAccount {
}
class DematAccount extends SavingAccount {
}
class Bank {
public void open(SavingAccount act ) {
System.out.println("... Opening Saving Account ...");
}
public void open(DematAccount act ) {
System.out.println("... Opening Demat Account ...");
}
}
public class Test {
public static void main(String[] args) {
List<SavingAccount> actList = new ArrayList<SavingAccount>();
Bank bank = new Bank();
actList.add( new SavingAccount());
actList.add( new DematAccount());
for( SavingAccount act : actList ) {
bank.open(act);
}
}
}
这里的输出如下。 ...打开储蓄帐户... ...开立储蓄账户......
现在让我修改代码并查看下面的输出。
import java.util.ArrayList;
import java.util.List;
class SavingAccount {
public void open() {
System.out.println("... Opened Saving Account Successfully ...");
}
}
class DematAccount extends SavingAccount {
public void open() {
System.out.println("... Opened Demat Account Successfully ...");
}
}
class Bank {
public void open(SavingAccount act ) {
System.out.println("... Opening Saving Account ...");
act.open();
}
public void open(DematAccount act ) {
System.out.println("... Opening Demat Account ...");
act.open();
}
}
public class Test {
public static void main(String[] args) {
List<SavingAccount> actList = new ArrayList<SavingAccount>();
Bank bank = new Bank();
actList.add( new SavingAccount());
actList.add( new DematAccount());
for( SavingAccount act : actList ) {
bank.open(act);
}
}
}
这里的输出是 ...打开储蓄账户...... ...成功开立储蓄账户...... ...打开储蓄账户...... ...成功开设了Demat账户......
现在我的问题是我得到的结果是我期待的,为什么我应该去访问模式,在上面的代码中,即使它显示“保存帐户”,但它正确执行“Demat帐户代码”部分。 / p>
请解释一下,问题出在哪里? 在此先感谢。
答案 0 :(得分:1)
简短回答:Java没有运行时参数多态(在运行时选择基于参数类型的方法)。
编译器将在对象上多态调用子类方法,因此如果 act 是,act.open()
将调用 DematAccount 的实现DematAccount 即可。但是,Java的多态性不适用于参数,因此如果 act 是 SavingAccount 类型的变量,bank.open(act)
将始终调用open(SavingAccount)
它的运行时类型。
编译器在呼叫站点知道的相关事项是行为是 SavingAccount 而银行的方法是打开( SavingAccount)作为最接近的逆变匹配:
for(SavingAccount act : actList ) {
bank.open(act);
}
您可以使用 instanceof 进行类型套管并将 act 强制转换为子类以解决此问题,或者您可以在银行>中执行该类型套管强>上课。
for(SavingAccount act : actList ) {
if (act instanceof DematAccount) {
bank.open((DematAccount) act);
} else {
bank.open(act);
}
}
这种丑陋并意味着将此代码与各种帐户相关联,并在每次更改时对其进行更改。
更改银行操作系统更好,因为银行已经承担了了解所有 SavingAccount 子类的责任。
class Bank {
public void open(SavingAccount act ) {
if (act instanceof DematAccount) {
open((DematAccount) act);
} else {
System.out.println("... Opening Saving Account ...");
act.open();
}
}
public void open(DematAccount act ) {
System.out.println("... Opening Demat Account ...");
act.open();
}
}
在这种情况下银行仅在控制台输出中有所不同,您可以轻松地将该控制台输出移至 SavingAccount 和 DematAccount 并移除从银行开启(DematAccount)。