zoukankan      html  css  js  c++  java
  • [改善Java代码]建议40:匿名类的构造函数很特殊

    建议40: 匿名类的构造函数很特殊

    在上一个建议中我们讲到匿名类虽然没有名字,但可以有一个初始化块来充当构造函数,那这个构造函数是否就和普通的构造函数完全一样呢?我们来看一个例子,设计一个计算器,进行加减乘除运算,代码如下:

     1 // 定义一个枚举,限定操作符
     2 enum Ops {
     3     ADD, SUB
     4 }
     5 
     6 class Calculator {
     7     private int i, j, result;
     8 
     9     // 无参构造
    10     public Calculator() {
    11     }
    12 
    13     // 有参构造
    14     public Calculator(int _i, int _j) {
    15         i = _i;
    16         j = _j;
    17     }
    18 
    19     // 设置符号,是加法运算还是减法运算
    20     protected void setOperator(Ops _op) {
    21         result = _op.equals(Ops.ADD) ? i + j : i - j;
    22     }
    23 
    24     // 取得运算结果
    25     public int getResult() {
    26         return result;
    27     }
    28 }

    代码的意图是,通过构造函数输入两个int类型的数字,然后根据设置的操作符(加法还是减法)进行计算,编写一个客户端调用:

    1 public static void main(String[] args) {  
    2     Calculator c1 = new Calculator(1,2) {  
    3          {  
    4              setOperator(Ops.ADD);  
    5          }  
    6     };  
    7     System.out.println(c1.getResult());  
    8 } 

    这段匿名类的代码非常清晰:接收两个参数1和2,然后设置一个操作符号,计算其值,结果是3,这毫无疑问,但是这中间隐藏着一个问题:带有参数的匿名类声明时到底是调用的哪一个构造函数呢?我们把这段程序模拟一下:

    1 //加法计算  
    2 class Add extends Calculator {  
    3      {  
    4           setOperator(Ops.ADD);  
    5      }  
    6      //覆写父类的构造方法  
    7      public Add(int _i, int _j) {  
    8      }  
    9 } 

    匿名类和这个Add类是等价的吗?可能有人会说:上面只是把匿名类增加了一个名字,其他的都没有改动,那肯定是等价的啦!毫无疑问!那好,你再写个客户端调用Add类的方法看看。是不是输出结果为0(为什么是0?这很容易,有参构造没有赋值)。这说明两者不等价,不过,原因何在呢?

    原来是因为匿名类的构造函数特殊处理机制,一般类(也就是具有显式名字的类)的所有构造函数默认都是调用父类的无参构造的,而匿名类因为没有名字,只能由构造代码块代替,也就无所谓的有参和无参构造函数了,它在初始化时直接调用了父类的同参数构造,然后再调用了自己的构造代码块,也就是说上面的匿名类与下面的代码是等价的:

     1 //加法计算  
     2 class Add extends Calculator {  
     3      {  
     4           setOperator(Ops.ADD);  
     5      }  
     6      //覆写父类的构造方法  
     7      public Add(int _i, int _j) {  
     8           super(_i,_j);  
     9      }  
    10 } 

    它首先会调用父类有两个参数的构造函数,而不是无参构造,这是匿名类的构造函数与普通类的差别,但是这一点也确实鲜有人细细琢磨,因为它的处理机制符合习惯呀,我传递两个参数,就是希望先调用父类有两个参数的构造,然后再执行我自己的构造函数,而Java的处理机制也正是如此处理的!

  • 相关阅读:
    计算JensenShannon Divergence距离的方法
    perl 取出正则表达式的匹配位置
    QQ客服左右提示
    JS获取DropDownList的value值与text值
    一个大文件上传组件RadUpLoad(带进度条时间显示)
    asp.net不同后辍名的文件
    RowDataBound事件 .
    当sql2000和sql2005同时装时,因为都用了1433的端口号,可能会导致连接失败,这里讲asp.net 的连接方法 .
    CSS圆角
    ASP.NET把图片存入数据库和使用文件流读取显示(转)
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5430256.html
Copyright © 2011-2022 走看看