zoukankan      html  css  js  c++  java
  • [改善Java代码]构造代码块会想你所想

    建议37: 构造代码块会想你所想

    镜像博文:http://www.cnblogs.com/DreamDrive/p/5413408.html

    http://www.cnblogs.com/DreamDrive/p/5422698.html

    上一个建议中我们提议使用构造代码块来简化代码,并且也了解到编译器会自动把构造代码块插入到各个构造函数中,那我们接下来看看编译器是不是足够聪明,能够为我们解决真实的开发问题。有这样一个案例:统计一个类的实例数量。可能你要说了,这很简单,在每个构造函数中加入一个对象计数器不就解决问题了吗?或者使用我们上一个建议介绍的,使用构造代码块也可以。确实如此,我们来看如下代码是否可行:

     1 public class Client {
     2     public static void main(String[] args) {
     3         new Base();
     4         new Base("");
     5         new Base(0);
     6         System.out.println("实例对象数量:" + Base.getNumOfObjects());
     7     }
     8 }
     9 
    10 class Base {
    11     // 对象计数器
    12     private static int numOfObjects = 0;
    13 
    14     {
    15         // 构造代码块,计算产生对象数量
    16         numOfObjects++;
    17     }
    18 
    19     public Base() {
    20     }
    21 
    22     // 有参构造调用无参构造
    23     public Base(String _str) {
    24         this();
    25     }
    26 
    27     // 有参构造不调用其他构造
    28     public Base(int _i) {
    29     }
    30 
    31     // 返回在一个JVM中,创建了多少个实例对象
    32     public static int getNumOfObjects() {
    33         return numOfObjects;
    34     }
    35 }

    这段代码是可行的吗?能计算出实例对象的数量吗?哎,好像不对呀,如果编译器把构造代码块插入到各个构造函数中,那带有String形参的构造函数可就有问题,它会调用无参构造,那通过它生成Base对象时就会执行两次构造代码块:一次是由无参构造函数调用构造代码块,一次是执行自身的构造代码块,这样的话计算可就不准确了,main函数实际在内存中产生了3个对象,但结果却会是4。不过真是这样的吗?Are you sure?我们运行一下看看结果:

    实例对象数量:3

    非常遗憾,你错了,实例对象的数量还是3,程序没有任何问题。奇怪吗?不奇怪,上一个建议是说编译器会把构造代码块插入到每一个构造函数中,但是有一个例外的情况没有说明:如果遇到this关键字(也就是构造函数调用自身其他的构造函数时)则不插入构造代码块,对于我们的例子来说,编译器在编译时发现String形参的构造函数调用了无参构造,于是放弃插入构造代码块,所以只执行了一次构造代码块—结果就是如此。

    那Java编译器为什么会这么聪明呢?这还要从构造代码块的诞生说起,构造代码块是为了提取构造函数的共同量,减少各个构造函数的代码而产生的,因此,Java就很聪明地认为把代码块插入到没有this方法的构造函数中即可,而调用其他构造函数的则不插入,确保每个构造函数只执行一次构造代码块。

    还有一点需要说明,读者千万不要以为this是特殊情况,那super也会类似处理了。其实不会,在构造代码块的处理上,super方法没有任何特殊的地方,编译器只是把构造代码块插入到super方法之后执行而已,仅此不同。

    注意 放心地使用构造代码块吧,Java已经想你所想了。

  • 相关阅读:
    CMD 常用命令
    CMD 删除脚本
    HAproxy 介绍
    HAproxy 配置参数详解
    HAproxy 源码包安装
    lvs keepalived 安装配置详解【转】
    linux下负载均衡(LVS安装与配置)【转】
    CentOS 6.3下部署LVS(NAT)+keepalived实现高性能高可用负载均衡【转】
    Linux负载均衡软件LVS之二(安装篇)[转]
    Mysql + keepalived 实现双主热备读写分离【转】
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5422705.html
Copyright © 2011-2022 走看看