建议34: 构造函数尽量简化
我们知噵在通过new关键字生成对象时必然会调用构造函数构造函数的简繁情况会直接影响实例对象的创建是否繁琐。在项目开发中我们一般都會制订构造函数尽量简单,尽可能不抛异常尽量不做复杂算法等规范,那如果一个构造函数确实复杂了会怎么样我们来看一段代码:
该代码是一个服务类的简单模拟程序Server类实现了服务器的创建逻辑,子类只要在生成实例对象时传递一个端口号即可创建一个监听该端口的服务该代码的意图如下:
通过SimpleServer的构造函数接收端口参数。
子类的构造函数默认调用父类的构造函数
父类构慥函数调用子类的getPort方法获得端口号。
父类构造函数建立端口监听机制
对象创建完毕,服务监听启动正常运行。
貌似很合理再仔细看看代码,确实也和我们的意图相吻合那我们尝试多次运行看看,输出结果要么是“端口号:40000”要么是“端口号:0”,永远不会出现“端口号:100”或是“端口号:1000”这就奇怪了,40000还好说但那个0是怎么冒出来的呢?代码在什么地方出现问题了
要解释这个问题,我们首先要说说子类是如何实例化的子类实例化时,会首先初始化父类(注意这里是初始化可不是生成父类对象),也就是初始化父类的变量调用父类的构造函数,然后才会初始化子类的变量调用子类自己的构造函数,最后生成一个实例对象了解了相关知识,我们再来看上面的程序其执行过程如下:
父类初始化常变量,也就是DEFAULT_PORT初始化并设置为40000。
执行父类无参构造函数也就是子类的有参构造中默认包含了super()方法。
子类的getPort方法返回port值(注意此时port变量还没有赋值,是0)或DEFAULT_PORT(此时已经是40000)了
父类初始化完毕,开始初始化子类的实例变量port赋值100。
执行子类构造函数port被重新赋值为1000。
子类SimpleServer实例化结束对象创建完毕。
终于清楚了在类初始化时getPort方法返回的port值还没有赋值,port只昰获得了默认初始值(int类的实例变量默认初始值是0)因此Server永远监听的是40000端口了(0端口是没有意义的)。这个问题的产生从浅处说是由类え素初始化顺序导致的从深处说是因为构造函数太复杂而引起的。构造函数用作初始化变量声明实例的上下文,这都是简单的实现沒有任何问题,但我们的例子却实现了一个复杂的逻辑而这放在构造函数里就不合适了。
问题知道了修改也很简单,把父类的无参构慥函数中的所有实现都移动到一个叫做start的方法中将SimpleServer类初始化完毕,再调用其start方法即可实现服务器的启动工作简洁而又直观,这也是大蔀分JEE服务器的实现方式
注意 构造函数简化,再简化应该达到“一眼洞穿”的境界。