[改善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 //普通代码块 ...
随机推荐
- homework-08 C++课程课后思考与练习
经过上次晚交作业导致没分以后 我再也不敢晚交作业了 今天就把这次作业先写了 homework Part 1 1. 理解C++变量的作用域和生命周期 a) 用少于10行代码演示你对局部变量的生命周期的理 ...
- Gym 100507L Donald is a postman (水题)
Donald is a postman 题目链接: http://acm.hust.edu.cn/vjudge/contest/126546#problem/L Description Donald ...
- My97DatePicker源码的K方法
<head></head> <script> var X = window,M = "document", C = "getEleme ...
- HDU 4489 The King’s Ups and Downs (DP+数学计数)
题意:给你n个身高高低不同的士兵.问你把他们按照波浪状排列(高低高或低高低)有多少方法数. 析:这是一个DP题是很明显的,因为你暴力的话,一定会超时,应该在第15个时,就过不去了,所以这是一个DP计数 ...
- C++中void型指针
问题由来: PX_FORCE_INLINE void* operator new(size_t size, const char* handle, const char * filename, int ...
- ags模版与vs
esri为每个版本的sdk指定了特定的vs开发版本,比如ags10.0,ags10.1指定的是vs2008和vs2010,大概是因为发布时间的关系. 无论如何,我们可以将模版移植到新的vs下.(注意红 ...
- Cocos2d-x——支持多触点
1:在AppController的didFinishLaunchingWithOptions中,加入 [__glView setMultipleTouchEnabled:YES]; 2:在CCLaye ...
- 添加zlib压缩步骤 OpenSSL
1.Link Binary With Libraries 中添加 libz.dyllb 2.复制OpenSSL(libssl.a & libcryto.a & NSData+Cocoa ...
- RT-Thread学习笔记(1)
前几天我在看uCOS-II的东西,看来看去一直没什么头绪.还有一点是,我很介意它现在是个商业软件,在官网下载东西,半天下完结果只有个lib,没有源代码.只能去其他地方下载老版本. 我还很介意不是在官方 ...
- Ectouch修改虚拟销售数量的方法
1.参考:http://zhidao.baidu.com/link?url=5OEkRlKqtRcmnO6iyW2pq-gw1aj-1S6QdImmBkQZHHt6tcvT50aIf_1nibP3T6 ...