[改善Java代码]构造代码块会想你所想
建议37: 构造代码块会想你所想
镜像博文:http://www.cnblogs.com/DreamDrive/p/5413408.html
http://www.cnblogs.com/DreamDrive/p/5422698.html
上一个建议中我们提议使用构造代码块来简化代码,并且也了解到编译器会自动把构造代码块插入到各个构造函数中,那我们接下来看看编译器是不是足够聪明,能够为我们解决真实的开发问题。有这样一个案例:统计一个类的实例数量。可能你要说了,这很简单,在每个构造函数中加入一个对象计数器不就解决问题了吗?或者使用我们上一个建议介绍的,使用构造代码块也可以。确实如此,我们来看如下代码是否可行:
public class Client {
public static void main(String[] args) {
new Base();
new Base("");
new Base(0);
System.out.println("实例对象数量:" + Base.getNumOfObjects());
}
}
class Base {
// 对象计数器
private static int numOfObjects = 0;
{
// 构造代码块,计算产生对象数量
numOfObjects++;
}
public Base() {
}
// 有参构造调用无参构造
public Base(String _str) {
this();
}
// 有参构造不调用其他构造
public Base(int _i) {
}
// 返回在一个JVM中,创建了多少个实例对象
public static int getNumOfObjects() {
return numOfObjects;
}
}
这段代码是可行的吗?能计算出实例对象的数量吗?哎,好像不对呀,如果编译器把构造代码块插入到各个构造函数中,那带有String形参的构造函数可就有问题,它会调用无参构造,那通过它生成Base对象时就会执行两次构造代码块:一次是由无参构造函数调用构造代码块,一次是执行自身的构造代码块,这样的话计算可就不准确了,main函数实际在内存中产生了3个对象,但结果却会是4。不过真是这样的吗?Are you sure?我们运行一下看看结果:
实例对象数量:3
非常遗憾,你错了,实例对象的数量还是3,程序没有任何问题。奇怪吗?不奇怪,上一个建议是说编译器会把构造代码块插入到每一个构造函数中,但是有一个例外的情况没有说明:如果遇到this关键字(也就是构造函数调用自身其他的构造函数时)则不插入构造代码块,对于我们的例子来说,编译器在编译时发现String形参的构造函数调用了无参构造,于是放弃插入构造代码块,所以只执行了一次构造代码块—结果就是如此。
那Java编译器为什么会这么聪明呢?这还要从构造代码块的诞生说起,构造代码块是为了提取构造函数的共同量,减少各个构造函数的代码而产生的,因此,Java就很聪明地认为把代码块插入到没有this方法的构造函数中即可,而调用其他构造函数的则不插入,确保每个构造函数只执行一次构造代码块。
还有一点需要说明,读者千万不要以为this是特殊情况,那super也会类似处理了。其实不会,在构造代码块的处理上,super方法没有任何特殊的地方,编译器只是把构造代码块插入到super方法之后执行而已,仅此不同。
注意 放心地使用构造代码块吧,Java已经想你所想了。
[改善Java代码]构造代码块会想你所想的更多相关文章
- java中构造代码块、方法调用顺序问题
1. 继承的概念 继承在本职上是特殊——一般的关系,即常说的is-a关系.子类继承父类,表明子类是一种特殊的父类,并且具有父类所不具有的一些属性或方法. 2. 继承中的初始化顺序 从类的结构上而言,其 ...
- Java: constructor 构造代码块
构造器与类同名 每个类可以有1一个以上的构造器 构造器可以有0个,1个或者多个参数 构造器没有返回值,不可以写return 构造器总是伴随着new操作一起调用 构造函数的作用:可以用于给对象进行初始化 ...
- Java中构造代码块的使用
例子1 public class Client { { System.out.println("执行构造代码块1"); } { System.out.println("执 ...
- Java 代码块:静态代码块、构造代码块、构造函数块
Class : StaticFa package edu.bai.du.lime.staticCode; public class StaticFa { // 随着类的声明而执行 static { S ...
- Github即将破百万的PDF:编写高质量代码改善JAVA程序的151个建议
在通往"Java技术殿堂"的路上,本书将为你指点迷津!内容全部由Java编码的最佳 实践组成,从语法.程序设计和架构.工具和框架.编码风格和编程思想等五大方面,对 Java程序员遇 ...
- [改善Java代码]使用构造块精炼程序
建议36: 使用构造代码块精炼程序 什么叫代码块(Code Block)?用大括号把多行代码封装在一起,形成一个独立的数据体,实现特定算法的代码集合即为代码块,一般来说代码块是不能单独运行的,必须要有 ...
- JAVA之旅(四)——面向对象思想,成员/局部变量,匿名对象,封装 , private,构造方法,构造代码块
JAVA之旅(四)--面向对象思想,成员/局部变量,匿名对象,封装 , private,构造方法,构造代码块 加油吧,节奏得快点了 1.概述 上篇幅也是讲了这点,这篇幅就着重的讲一下思想和案例 就拿买 ...
- java基础之静态代码块,局部代码块,构造代码块区别。
java中有几种常见的代码块,那怎样区别他们呢? 这里就这些问题,浅谈下我个人的理解. 1.局部代码块 局部代码块,又叫普通代码块.它是作用在方法中的代码块.例如: public void show( ...
- Java中普通代码块,构造代码块,静态代码块区别及代码示例
//执行顺序:(优先级从高到低.)静态代码块>mian方法>构造代码块>构造方法. 其中静态代码块只执行一次.构造代码块在每次创建对象是都会执行. 1 普通代码块 1 //普通代码块 ...
随机推荐
- LightOJ 1074 Extended Traffic (最短路spfa+标记负环点)
Extended Traffic 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/O Description Dhaka city ...
- HDU 5762 Teacher Bo (暴力)
Teacher Bo 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5762 Description Teacher BoBo is a geogra ...
- C++库研究笔记——操作符重载实现类型转换&这样做的意义
目标: 已知这个接口: std::vector<double> add_vec(double *d1, double *d2) { ..... return result; } 我们自定义 ...
- 校园网通过路由器开WiFi
闲话少说,为了在一个宿舍内达到一个网口N人上网目的,特地写一篇关于校园网通过路由器开wifi的文章,希望能帮助同学把wifi开起来,请看正文(操作以下步骤前建议先重置路由,也就是初始化复位): 一.一 ...
- 【Java】多线程冲突解决——同步锁
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827547.html 解决并行冲突最有效的方法就是加同步锁,主要有以下几种方法: 1:动态方法 ...
- 在Windows7上搭建Cocos2d-x 3.2alpha0开发环境
在windows7上搭建COCOS2D-X开发环境并不难, 但是由于框架更新过快,很多用户都有困难.我希望你们认为这个教程有用. 建议:为了避免安全相关的问题,请以管理员权限执行所有的操作,当运行命令 ...
- MATLAB代码
clear;clc%%%%%%%%%%%%方程里的参量%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%alpha=0.5;beta=0.5;%%% ...
- 我所理解的设计模式(C++实现)——备忘录模式(Memento Pattern)
概述: 我们玩单机游戏的时候总会遇到老婆大人的各位事情,一会去买瓶醋了,一会去打个酱油了,会耽误我们玩游戏的进程,但是此时我们能有“保存游戏”这个宝贝,我们的主基地不会在我们打酱油的时候被对手拆掉. ...
- mac下批量删除.svn文件
mac下.svn是隐藏文件,而且即使我们调成可见的,一个一个删也很麻烦.今天正好同事问起来这个命令,于是想可能有些人也需要,于是还是放到博客里吧 命令比较简单,其实就是一条linux命令,打开终端,首 ...
- cmp排序hdoj 1106排序
上班之余抽点时间出来写写博文,希望对新接触的朋友有帮助.今天在这里和大家一起学习一下cmp排序 /*标题还是比拟的水吧,但是花的时间还是比拟的多,心不够静*/ #include <iostrea ...