昆明java培训
达内昆明广州春城路

18487146383

热门课程

构造函数尽量简化

  • 时间:2016-09-30
  • 发布:昆明Java培训
  • 来源:达内新闻

昆明Java培训的老师知道通过new关键字生成的对象必然会调用构造函数,构造函数的简繁情况会直接影响实例对象的创建是否繁琐,在项目开发中,我们一般都会制定构造函数尽量简单,尽可能不抛异常,尽量不做复杂运算等规范,那如果一个构造函数确实复杂了会怎么样?我们开看一段代码:

1 public class Client34 {

2    public static void main(String[] args) {

3        Server s= new SimpleServer(1000);

4    }

5 }

6

7 abstract class Server {

8    public final static int DEFAULT_PORT = 40000;

9

10    public Server() {

11        //获得子类提供的端口号

12        int port = getPort();

13        System.out.println("端口号:" + port);

14        /*进行监听动作*/

15    }

16

17    //由子类提供端口号,并作可用性检查

18    protected abstract int getPort();

19 }

20

21 class SimpleServer extends Server {

22    private int port = 100;

23

24    //初始化传递一个端口号

25    public SimpleServer(int _port) {

26        port = _port;

27    }

28

29    //检查端口是否有效,无效则使用默认端口,这里使用随机数模拟

30    @Override

31    protected int getPort() {

32        return Math.random() > 0.5 ? port : DEFAULT_PORT;

33    }

34

35 }

该代码是一个服务类的简单模拟程序,Server类实现了服务器的创建逻辑,子类要在生成实例对象时传递一个端口号即可创建一个监听端口的服务,该代码的意图如下:

通过SimpleServer的构造函数接收端口参数;

子类的构造函数默认调用父类的构造函数;

父类构造函数调用子类的getPort方法获得端口号;

父类的构造函数建立端口监听机制;

对象创建完毕,服务监听启动,正常运行。

貌似很合理,再仔细看看代码,确实与我们的意图相吻合,那我们尝试多次运行看看,输出结果要么是"端口号:40000",要么是"端口号:0",永远不会出现"端口号:100"或是"端口号:1000",这就奇怪了,40000还好说,那个0是怎么冒出来的呢?怠慢什么地方出现了问题呢?

要解释这个问题,我们首先要说说子类是如何实例化的。子类实例化时,会首先初始化父类(注意这里是初始化,不是生成父类对象),也就是初始化父类的变量,调用父类的构造函数,然后才会初始化子类的变量,调用子类的构造函数,最后生成一个实例对象。了解了相关知识,我们再来看看上面的程序,其执行过程如下:

子类SimpleServer的构造函数接收int类型的参数1000;

父类初始化常量,也就是DEFAULT_PORT初始化,并设置值为40000;

执行父类无参构造函数,也就是子类有参构造函数默认包含了super()方法;

父类无参构造函数执行到“int port = getPort()”方法,调用子类的getPort方法实现;

子类的getPort方法返回port值(注意,此时port变量还没有赋值,是0)或DEFAULT_PORT(此时已经是40000)了;

父类初始化完毕,开始初始化子类的实例变量,port值赋值100;

执行子类构造函数,port值被重新赋值为1000;

子类SimpleServer实例化结束,对象创建完毕。

终于清楚了,在类初始化时getPort方法返回值还没有赋值,port只是获得了默认初始值(int类型的实例变量默认初始值是0),因此Server永远监听的是40000端口(0端口是没有意义的)。这个问题的产生从浅处说是类元素初始顺序导致的,从深处说是因为构造函数太复杂引起的。构造函数用作初始化变量,声明实例的上下文,这都是简单实现的,没有任何问题,但我们的例子却实现了一个复杂的逻辑,而这放在构造函数里就不合适了。

问题知道了,修改也很简单,把父类的无参构造函数中的所有实现都移动到一个叫做start的方法中,将SimpleServer类初始化完毕,再调用其start方法即可实现服务器的启动工作,简洁而又直观,这也是大部分JEE服务器的实现方式。

昆明Java培训的老师提醒大家注意:构造函数简化,再简化,应该达到"一眼洞穿"的境界。

上一篇:不要覆写静态方法
下一篇:避免在构造函数中初始化其它类

昆明java培训教你实现JSP页面跳转简易方法,120天后月薪过万

昆明Java培训告诉你java和大数据和互联网发展中起什么作用

昆明java培训:初学者学Java Script 5个小技巧

昆明java培训多久可以学会?120天教你成为java开发大神!

选择城市和中心
贵州省

广西省

海南省

扫一扫

了解更多干货