java提高篇(十一)-----代码块
在编程过程中我们可能会遇到如下这种形式的程序:
public class Test {
{
////
}
}
这种形式的程序段我们将其称之为代码块,所谓代码块就是用大括号({})将多行代码封装在一起,形成一个独立的数据体,用于实现特定的算法。一般来说代码块是不能单独运行的,它必须要有运行主体。在Java中代码块主要分为四种:
一、 普通代码块
普通代码块是我们用得最多的也是最普遍的,它就是在方法名后面用{}括起来的代码段。普通代码块是不能够单独存在的,它必须要紧跟在方法名后面。同时也必须要使用方法名调用它。
public class Test {
public void test(){
System.out.println("普通代码块");
}
}
二 、 静态代码块
想到静态我们就会想到static,静态代码块就是用static修饰的用{}括起来的代码段,它的主要目的就是对静态属性进行初始化。
public class Test {
static{
System.out.println("静态代码块");
}
}
三、 同步代码块
使用 synchronized 关键字修饰,并使用“{}”括起来的代码片段,它表示同一时间只能有一个线程进入到该方法块中,是一种多线程保护机制。
四、 构造代码块
在类中直接定义没有任何修饰符、前缀、后缀的代码块即为构造代码块。我们明白一个类必须至少有一个构造函数,构造函数在生成对象时被调用。构造代码块和构造函数一样同样是在生成一个对象时被调用,那么构造代码在什么时候被调用?如何调用的呢?看如下代码:
public class Test {
/**
* 构造代码
*/
{
System.out.println("执行构造代码块...");
}
/**
* 无参构造函数
*/
public Test(){
System.out.println("执行无参构造函数...");
}
/**
* 有参构造函数
* @param id id
*/
public Test(String id){
System.out.println("执行有参构造函数...");
}
}
上面定义了一个非常简单的类,该类包含无参构造函数、有参构造函数以及构造代码块,同时在上面也提过代码块是没有独立运行的能力,他必须要有一个可以承载的载体,那么编译器会如何来处理构造代码块呢?编译器会将代码块按照他们的顺序(假如有多个代码块)插入到所有的构造函数的最前端,这样就能保证不管调用哪个构造函数都会执行所有的构造代码块。上面代码等同于如下形式:
public class Test {
/**
* 无参构造函数
*/
public Test(){
System.out.println("执行构造代码块...");
System.out.println("执行无参构造函数...");
}
/**
* 有参构造函数
* @param id id
*/
public Test(String id){
System.out.println("执行构造代码块...");
System.out.println("执行有参构造函数...");
}
}
运行结果
public static void main(String[] args) {
new Test();
System.out.println("----------------");
new Test("1");
}
------------
Output:
执行构造代码块...
执行无参构造函数...
----------------
执行构造代码块...
执行有参构造函数...
从上面的运行结果可以看出在new一个对象的时候总是先执行构造代码,再执行构造函数,但是有一点需要注意构造代码不是在构造函数之前运行的,它是依托构造函数执行的。正是由于构造代码块有这几个特性,所以它常用于如下场景:
1、 初始化实例变量
如果一个类中存在若干个构造函数,这些构造函数都需要对实例变量进行初始化,如果我们直接在构造函数中实例化,必定会产生很多重复代码,繁琐和可读性差。这里我们可以充分利用构造代码块来实现。这是利用编译器会将构造代码块添加到每个构造函数中的特性。
2、 初始化实例环境
一个对象必须在适当的场景下才能存在,如果没有适当的场景,则就需要在创建对象时创建此场景。我们可以利用构造代码块来创建此场景,尤其是该场景的创建过程较为复杂。构造代码会在构造函数之前执行。
上面两个常用场景都充分利用构造代码块的特性,能够很好的解决在实例化对象时构造函数比较难解决的问题,利用构造代码不仅可以减少代码量,同时也是程序的可读性增强了。特别是当一个对象的创建过程比较复杂,需要实现一些复杂逻辑,这个时候如果在构造函数中实现逻辑,这是不推荐的,因为我们提倡构造函数要尽可能的简单易懂,所以我们可以使用构造代码封装这些逻辑实现部分。
五、 静态代码块、构造代码块、构造函数执行顺序
从词面上我们就可以看出他们的区别。静态代码块,静态,其作用级别为类,构造代码块、构造函数,构造,其作用级别为对象。
1、 静态代码块,它是随着类的加载而被执行,只要类被加载了就会执行,而且只会加载一次,主要用于给类进行初始化。
2、 构造代码块,每创建一个对象时就会执行一次,且优先于构造函数,主要用于初始化不同对象共性的初始化内容和初始化实例环境。
3、 构造函数,每创建一个对象时就会执行一次。同时构造函数是给特定对象进行初始化,而构造代码是给所有对象进行初始化,作用区域不同。
通过上面的分析,他们三者的执行顺序应该为:静态代码块 > 构造代码块 > 构造函数。
public class Test {
/**
* 静态代码块
*/
static{
System.out.println("执行静态代码块...");
}
/**
* 构造代码块
*/
{
System.out.println("执行构造代码块...");
}
/**
* 无参构造函数
*/
public Test(){
System.out.println("执行无参构造函数...");
}
/**
* 有参构造函数
* @param id
*/
public Test(String id){
System.out.println("执行有参构造函数...");
}
public static void main(String[] args) {
System.out.println("----------------------");
new Test();
System.out.println("----------------------");
new Test("1");
}
}
-----------
Output:
执行静态代码块...
----------------------
执行构造代码块...
执行无参构造函数...
----------------------
执行构造代码块...
执行有参构造函数...
参看文献:《编写高质量代码 改善java程序的151个建议》
java提高篇(十一)-----代码块的更多相关文章
- Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序
静态代码块:用staitc声明,jvm加载类时执行,仅执行一次构造代码块:类中直接用{}定义,每一次创建对象时执行.执行顺序优先级:静态块,main(),构造块,构造方法. 构造函数 public H ...
- java提高篇(十一)-----强制类型转换
在java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换. 在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需 ...
- Java提高篇(二七)-----TreeMap
TreeMap的实现是红黑树算法的实现,所以要了解TreeMap就必须对红黑树有一定的了解,其实这篇博文的名字叫做:根据红黑树的算法来分析TreeMap的实现,但是为了与Java提高篇系列博文保持一致 ...
- java提高篇(十七)-----异常(二)
承接上篇博文:java提高篇-----异常(一) 五.自定义异常 Java确实给我们提供了非常多的异常,但是异常体系是不可能预见所有的希望加以报告的错误,所以Java允许我们自定义异常来表 ...
- java提高篇(十)-----详解匿名内部类
在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始 ...
- java提高篇(八)----详解内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...
- java提高篇(九)-----详解匿名内部类
在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始 ...
- Java提高篇---TreeMap
TreeMap的实现是红黑树算法的实现,所以要了解TreeMap就必须对红黑树有一定的了解,其实这篇博文的名字叫做:根据红黑树的算法来分析TreeMap的实现,但是为了与Java提高篇系列博文保持一致 ...
- 【转】java提高篇(十)-----详解匿名内部类
原文网址:http://www.cnblogs.com/chenssy/p/3390871.html 在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节 ...
- java提高篇(十)-----详解匿名内部类 ,形参为什么要用final
在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始 ...
随机推荐
- 初始化openwrt的rootpassword
更改openwrt源代码 shadow 文件 package/base-files/files/etc/shadow shadow 文件參考http://blog.csdn.net/u01164188 ...
- iOS_UIButton 简单操作
UIButton 风格 typedef NS_ENUM(NSInteger, UIButtonType) { UIButtonTypeCustom = 0, // no button type UIB ...
- 《数字图像处理原理与实践(MATLAB版)》一书之代码Part2
本文系<数字图像处理原理与实践(MATLAB版)>一书之代码系列的Part2(P43~80),代码运行结果请參见原书配图,建议下载代码前阅读下文: 关于<数字图像处理原理与实践(MA ...
- Android数据库hibernate框架
说明 /** * YDL_Hibernate总结 <br/> * (一)支持功能: 1.自己主动建表,支持属性来自继承类:可依据注解自己主动完毕建表,而且对于继承类中的注解字段也支持自己主 ...
- c#控制台应用程序-“进入指定日期检查出星期几”
这涉及一个算法: 基姆拉尔森计算公式 W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1) mod 7 在公式中d表示日期中的日数.m表示月份数.y表示年数. 注意:在公式 ...
- hdu4126(最小生成树+dfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4126 题意:给出一幅3000个点的图,有10000次操作: 求将某条边的权值变大后的最小生成树,最后输 ...
- [Android]解决3gwap联网失败:联网请求在设置代理与直连两种方式的切换
[Android]解决3gwap联网失败:联网请求在设置代理与直连两种方式的切换 问题现象: 碰到一个问题,UI交互表现为:联通号码在3gwap网络环境下资源一直无法下载成功. 查看Log日志,打印出 ...
- jQuery cxSelect 多级联动下拉菜单
随着电商热门,这种多层次的互动更充分地体现在下拉菜单,最明显的是多级联动地址下拉选择,因此,这里是一个简单的分享 jQuery cxSelect 多级联动下拉菜单 cxSelect 它是基于 jQue ...
- pygame系列_font游戏字体
在pygame游戏开发中,一个友好的UI中,漂亮的字体是少不了的 今天就给大伙带来有关pygame中字体的一些介绍说明 首先我们得判断一下我们的pygame中有没有font这个模块 1 if not ...
- jps查看java进程中哪个线程在消耗系统资源
jps或ps -ef|grep java可以看到有哪些java进程,这个不用说了.但值得一提的是jps命令是依赖于/tmp下的某些文件 的. 而某些操作系统,定期会清理掉/tmp下的文件,导致jps无 ...