[改善Java代码]建议40:匿名类的构造函数很特殊
建议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:匿名类的构造函数很特殊的更多相关文章
- [改善Java代码]建议采用的顺序是 List<T>、List<?>、List<Object>
建议98:建议采用的顺序是 List<T>.List<?>.List<Object> List<T>.List<?>.List<Obj ...
- [改善Java代码]使用匿名类的构造函数
建议39: 使用匿名类的构造函数 阅读如下代码,看看是否可以编译: public class Client { public static void main(String[] args) { Lis ...
- 从 Java 代码逆向工程生成 UML 类图和序列图
from:http://blog.itpub.net/14780914/viewspace-588975/ 本文面向于那些软件架构师,设计师和开发人员,他们想使用 IBM® Rational® Sof ...
- Myeclipse中把java代码导成UML类图
Myeclipse中把java代码导成UML类图 1.右键点击项目名称,选择New-------àUML2 Model 2.给类图命名 3.导成类图 1)如果要把整个项目导成类图,则把整个项目拖到类图 ...
- [改善Java代码]使用package-info类为包服务
建议50: 使用package-info类为包服务 Java中有一个特殊的类:package-info类,它是专门为本包服务的,为什么说它特殊呢?主要体现在3个方面: (1)它不能随便被创建 在一般的 ...
- [改善Java代码]避免在构造函数中初始化其他类
建议35: 避免在构造函数中初始化其他类 构造函数是一个类初始化必须执行的代码,它决定着类的初始化效率,如果构造函数比较复杂,而且还关联了其他类,则可能产生意想不到的问题,我们来看如下代码: publ ...
- [改善Java代码]在接口中不要存在实现代码
第3章 类.对象及方法 书读得多而不思考,你会觉得自己知道的很多. 书读得多而思考,你会觉得自己不懂的越来越多. —伏尔泰 在面向对象编程(Object-Oriented Programming,O ...
- [改善Java代码]asList方法产生的List对象不可更改
上一个建议之处了asList方法在转换基本类型数组时候存在的问题,在看下asList方法返回的列表有何特殊的地方.看代码: import java.util.Arrays; import java.u ...
- [改善Java代码]覆写equals方法必须覆写hashCode方法
覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先 ...
随机推荐
- 【转】linux代码段,数据段,BSS段, 堆,栈
转载自 http://blog.csdn.net/wudebao5220150/article/details/12947445 linux代码段,数据段,BSS段, 堆,栈 网上摘抄了一些,自己组 ...
- Spring Autowiring by Name
In Spring, "Autowiring by Name" means, if the name of a bean is same as the name of other ...
- STC-ISP下载过程
- codeforces 652B z-sort(思维)
B. z-sort time limit per test 1 second memory limit per test 256 megabytes input standard input outp ...
- javascript中数组的迭代等操作
- 【转】C#传委托给C的函数指针调用问题
C#传委托给C的函数指针调用问题C代码如下: #include "stdio.h" __declspec(dllexport) int Call(int (*qq)(int num ...
- linq to sql 三层架构中使用CRUD操作
/// <summary> /// 数据层 /// </summary> public partial class GasBottles : IGasBottles { #re ...
- 当LinkButton无效时,光标不显示为手型
在Flex组件LinkButton里,我们可以用useHandCursor属性来控制是否使用手型光标.现在我们要实现在LinkButton的enable=false时,useHandCursor=fa ...
- HDU 4123 Bob’s Race 树的直径 RMQ
Bob’s Race Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=41 ...
- Bump mapping的GLSL实现 [转]
原文 http://www.cnblogs.com/CGDeveloper/archive/2008/07/03/1234206.html 如果物体表面细节很多,我们可以不断的精细化物体的几何数据,但 ...