博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[改善Java代码]建议40:匿名类的构造函数很特殊
阅读量:6207 次
发布时间:2019-06-21

本文共 1771 字,大约阅读时间需要 5 分钟。

建议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的处理机制也正是如此处理的!

 

转载地址:http://efzja.baihongyu.com/

你可能感兴趣的文章
Sql學習資源
查看>>
303. Range Sum Query - Immutable
查看>>
禁用SettingSyncHost.exe
查看>>
Spring MVC 之请求处理方法可接收参数(三)
查看>>
线程与进程的区别
查看>>
理解angular中的module和injector,即依赖注入
查看>>
C#+ AE 注意问题汇总(不断更新)
查看>>
2016第42周学习小结
查看>>
Sublime常用快捷键
查看>>
[Android&Java]浅谈设计模式-代码篇:观察者模式Observer
查看>>
idea springboot热部署无效问题
查看>>
Java基础之关键字
查看>>
arcgis series license
查看>>
每一刻向你前进一步
查看>>
linux服务之ntp与chrony
查看>>
ARouter原理剖析及手动实现
查看>>
利用adb shell和node.js实现抖音自动抢红包功能
查看>>
2019请对2018的我好一点 | 掘金年度征文
查看>>
对于多重共线性的简单理解
查看>>
LeetCode 406 Queue Reconstruction by Height
查看>>