1700441090
1700441091
/*进行监听动作*/
1700441092
1700441093
}
1700441094
1700441095
//由子类提供端口号,并做可用性检查
1700441096
1700441097
protected abstract int getPort();
1700441098
1700441099
}
1700441100
1700441101
class SimpleServer extends Server{
1700441102
1700441103
private int port=100;
1700441104
1700441105
//初始化传递一个端口号
1700441106
1700441107
public SimpleServer(int_port){
1700441108
1700441109
port=_port;
1700441110
1700441111
}
1700441112
1700441113
//检查端口号是否有效,无效则使用默认端口,这里使用随机数模拟
1700441114
1700441115
@Override
1700441116
1700441117
protected int getPort(){
1700441118
1700441119
return Math.random()>0.5?port:DEFAULT_PORT;
1700441120
1700441121
}
1700441122
1700441123
}
1700441124
1700441125
该代码是一个服务类的简单模拟程序,Server类实现了服务器的创建逻辑,子类只要在生成实例对象时传递一个端口号即可创建一个监听该端口的服务,该代码的意图如下:
1700441126
1700441127
通过SimpleServer的构造函数接收端口参数。
1700441128
1700441129
子类的构造函数默认调用父类的构造函数。
1700441130
1700441131
父类构造函数调用子类的getPort方法获得端口号。
1700441132
1700441133
父类构造函数建立端口监听机制。
1700441134
1700441135
对象创建完毕,服务监听启动,正常运行。
1700441136
1700441137
貌似很合理,再仔细看看代码,确实也和我们的意图相吻合,那我们尝试多次运行看看,输出结果要么是“端口号:40000”,要么是“端口号:0”,永远不会出现“端口号:100”或是“端口号:1000”,这就奇怪了,40000还好说,但那个0是怎么冒出来的呢?代码在什么地方出现问题了?
1700441138
1700441139
要解释这个问题,我们首先要说说子类是如何实例化的。子类实例化时,会首先初始化父类(注意这里是初始化,可不是生成父类对象),也就是初始化父类的变量,调用父类的构造函数,然后才会初始化子类的变量,调用子类自己的构造函数,最后生成一个实例对象。了解了相关知识,我们再来看上面的程序,其执行过程如下:
[
上一页 ]
[ :1.70044109e+09 ]
[
下一页 ]