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

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

 // 定义一个枚举,限定操作符
enum Ops {
ADD, SUB
} class Calculator {
private int i, j, result; // 无参构造
public Calculator() {
} // 有参构造
public Calculator(int _i, int _j) {
i = _i;
j = _j;
} // 设置符号,是加法运算还是减法运算
protected void setOperator(Ops _op) {
result = _op.equals(Ops.ADD) ? i + j : i - j;
} // 取得运算结果
public int getResult() {
return result;
}
}

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

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

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

 //加法计算
class Add extends Calculator {
{
setOperator(Ops.ADD);
}
//覆写父类的构造方法
public Add(int _i, int _j) {
}
}

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

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

 //加法计算
class Add extends Calculator {
{
setOperator(Ops.ADD);
}
//覆写父类的构造方法
public Add(int _i, int _j) {
super(_i,_j);
}
}

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

[改善Java代码]建议40:匿名类的构造函数很特殊的更多相关文章

  1. [改善Java代码]建议采用的顺序是 List<T>、List<?>、List<Object>

    建议98:建议采用的顺序是 List<T>.List<?>.List<Object> List<T>.List<?>.List<Obj ...

  2. [改善Java代码]使用匿名类的构造函数

    建议39: 使用匿名类的构造函数 阅读如下代码,看看是否可以编译: public class Client { public static void main(String[] args) { Lis ...

  3. 从 Java 代码逆向工程生成 UML 类图和序列图

    from:http://blog.itpub.net/14780914/viewspace-588975/ 本文面向于那些软件架构师,设计师和开发人员,他们想使用 IBM® Rational® Sof ...

  4. Myeclipse中把java代码导成UML类图

    Myeclipse中把java代码导成UML类图 1.右键点击项目名称,选择New-------àUML2 Model 2.给类图命名 3.导成类图 1)如果要把整个项目导成类图,则把整个项目拖到类图 ...

  5. [改善Java代码]使用package-info类为包服务

    建议50: 使用package-info类为包服务 Java中有一个特殊的类:package-info类,它是专门为本包服务的,为什么说它特殊呢?主要体现在3个方面: (1)它不能随便被创建 在一般的 ...

  6. [改善Java代码]避免在构造函数中初始化其他类

    建议35: 避免在构造函数中初始化其他类 构造函数是一个类初始化必须执行的代码,它决定着类的初始化效率,如果构造函数比较复杂,而且还关联了其他类,则可能产生意想不到的问题,我们来看如下代码: publ ...

  7. [改善Java代码]在接口中不要存在实现代码

    第3章  类.对象及方法 书读得多而不思考,你会觉得自己知道的很多. 书读得多而思考,你会觉得自己不懂的越来越多. —伏尔泰 在面向对象编程(Object-Oriented Programming,O ...

  8. [改善Java代码]asList方法产生的List对象不可更改

    上一个建议之处了asList方法在转换基本类型数组时候存在的问题,在看下asList方法返回的列表有何特殊的地方.看代码: import java.util.Arrays; import java.u ...

  9. [改善Java代码]覆写equals方法必须覆写hashCode方法

    覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先 ...

随机推荐

  1. [cocos2d-x]File文件的IO读写处理

    转载:http://blog.csdn.net/chiuan/article/details/8618411 为了保存自定义数据文件,需要保存文件和读取文件,也就是File的IO处理: 针对cocos ...

  2. Android实例-全屏显示程序(XE10+小米2)(无图)

    方法一:选中窗体->BorderStyle改为“None” 方法二: 1.下载第三方控件QAndroid.Shell 2.执行FShell.Execute('su -c mount -o rem ...

  3. sping配置文件中引入properties文件方式

    <!-- 用于引入 jdbc有配置文件参数 可以使用PropertyPlaceholderConfigurer 或者PropertyOverrideConfigurer --> <b ...

  4. JEECMS-自定义标签[list]

    1.自定义标签类 import static cn.com.yhxl.common.web.freemarker.DirectiveUtils.OUT_LIST; import static free ...

  5. PicklingError: Can't pickle <type 'generator'>: it's not found as __builtin_

    多进程传递 参数时,需要是python系统已知的,不然不知道怎么序列化

  6. ASP.NET MVC4中用 BundleCollection

    来源:http://www.cnblogs.com/madyina/p/3702314.html ASP.NET MVC4中对JS和CSS的引用又做了一次变化,在MVC3中我们这样引用资源文件: &l ...

  7. C# winform 最小化到电脑右下角

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  8. 详解Oracle创建用户权限全过程

    本文将介绍的是通过创建一张表,进而实现Oracle创建用户权限的过程.以下这些代码主要也就是为实现Oracle创建用户权限而编写,希望能对大家有所帮助. 注意:每条语语分开执行,结尾必须用分号; // ...

  9. visual studio 2012进行C语言开发[图文]

    现在大家计算机大概都脱离XP了,so,之前蛮多可以用的编译器,可能放在我们现在的Win7,win8下面会出现一些比如不兼容了之类的问题.其实,用微软强大的IDE-visual studio系列,也是可 ...

  10. Android自己定义DataTimePicker(日期选择器)

    Android自己定义DataTimePicker(日期选择器)  笔者有一段时间没有发表关于Android的文章了,关于Android自己定义组件笔者有好几篇想跟大家分享的,后期会记录在博客中.本篇 ...