Java中静态代码块、构造代码块、构造函数、普通代码块
在Java中,静态代码块、构造代码块、构造函数、普通代码块的执行顺序是一个笔试的考点,通过这篇文章希望大家能彻底了解它们之间的执行顺序。
1、静态代码块
①、格式
在java类中(方法中不能存在静态代码块)使用static关键字和{}声明的代码块:
public class CodeBlock {
static{
System.out.println("静态代码块");
}
}
②、执行时机
静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数。如果一个类中有多个静态代码块,会按照书写顺序依次执行。后面在比较的时候会通过具体实例来证明。
③、静态代码块的作用
一般情况下,如果有些代码需要在项目启动的时候就执行,这时候就需要静态代码块。比如一个项目启动需要加载的很多配置文件等资源,我们就可以都放入静态代码块中。
④、静态代码块不能存在任何方法体中
这个应该很好理解,首先我们要明确静态代码块是在类加载的时候就要运行了。我们分情况讨论:
对于普通方法,由于普通方法是通过加载类,然后new出实例化对象,通过对象才能运行这个方法,而静态代码块只需要加载类之后就能运行了。
对于静态方法,在类加载的时候,静态方法也已经加载了,但是我们必须要通过类名或者对象名才能访问,也就是说相比于静态代码块,静态代码块是主动运行的,而静态方法是被动运行的。
不管是哪种方法,我们需要明确静态代码块的存在在类加载的时候就自动运行了,而放在不管是普通方法还是静态方法中,都是不能自动运行的。
⑤、静态代码块不能访问普通变量
这个理解思维同上,普通变量只能通过对象来调用,是不能放在静态代码块中的。
2、构造代码块
①、格式
在java类中使用{}声明的代码块(和静态代码块的区别是少了static关键字):
public class CodeBlock {
static{
System.out.println("静态代码块");
}
{
System.out.println("构造代码块");
}
}
②、执行时机
构造代码块在创建对象时被调用,每次创建对象都会调用一次,但是优先于构造函数执行。需要注意的是,听名字我们就知道,构造代码块不是优先于构造函数执行,而是依托于构造函数,也就是说,如果你不实例化对象,构造代码块是不会执行的。怎么理解呢?我们看看下面这段代码:
public class CodeBlock {
{
System.out.println("构造代码块");
} public CodeBlock(){
System.out.println("无参构造函数");
}
public CodeBlock(String str){
System.out.println("有参构造函数");
}
}
我们反编译生成的class文件:
如果存在多个构造代码块,则执行顺序按照书写顺序依次执行。
③、构造代码块的作用
和构造函数的作用类似,都能对对象进行初始化,并且只要创建一个对象,构造代码块都会执行一次。但是反过来,构造函数则不一定每个对象建立时都执行(多个构造函数情况下,建立对象时传入的参数不同则初始化使用对应的构造函数)。
利用每次创建对象的时候都会提前调用一次构造代码块特性,我们可以做诸如统计创建对象的次数等功能。
3、构造函数
1.构造函数的命名必须和类名完全相同。在java中普通函数可以和构造函数同名,但是必须带有返回值;
2.构造函数的功能主要用于在类的对象创建时定义初始化的状态。它没有返回值,也不能用void来修饰。这就保证了它不仅什么也不用自动返回,而且根本不能有任何选择。而其他方法都有返回值,即使是void返回值。尽管方法体本身不会自动返回什么,但仍然可以让它返回一些东西,而这些东西可能是不安全的;
3.构造函数不能被直接调用,必须通过new运算符在创建对象时才会自动调用;而一般的方法是在程序执行到它的时候被调用的;
4.当定义一个类的时候,通常情况下都会显示该类的构造函数,并在函数中指定初始化的工作也可省略,不过Java编译器会提供一个默认的构造函数.此默认构造函数是不带参数的。而一般的方法不存在这一特点;
4、普通代码块
普通代码块和构造代码块的区别是,构造代码块是在类中定义的,而普通代码块是在方法体中定义的。且普通代码块的执行顺序和书写顺序一致。
public void sayHello(){
{
System.out.println("普通代码块");
}
}
5、执行顺序
- 静态代码块>构造代码块>构造函数>普通代码块
public class CodeBlock {
static{
System.out.println("静态代码块");
}
{
System.out.println("构造代码块");
}
public CodeBlock(){
System.out.println("无参构造函数");
} public void sayHello(){
{
System.out.println("普通代码块");
}
} public static void main(String[] args) {
System.out.println("执行了main方法"); new CodeBlock().sayHello();;
System.out.println("---------------");
new CodeBlock().sayHello();;
}
}
反编译生成的class文件:
执行结果:
我们创建了两个匿名对象,但是静态代码块只是调用了一次。
6、父类和子类执行顺序
对象的初始化顺序:
首先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,当子类的静态内容执行完毕之后,再去看父类有没有构造代码块,如果有就执行父类的构造代码块,父类的构造代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有构造代码块,如果有就执行子类的构造代码块。子类的构造代码块执行完毕再去执行子类的构造方法。
总之一句话,静态代码块内容先执行,接着执行父类构造代码块和构造方法,然后执行子类构造代码块和构造方法。
父类:SuperClass.java
package com.ys.extend; public class SuperClass {
static{
System.out.println("父类静态代码块");
}
{
System.out.println("父类构造代码块");
}
public SuperClass(){
System.out.println("父类构造函数");
}
}
子类:SubClass.java
package com.ys.extend; public class SubClass extends SuperClass{
static{
System.out.println("子类静态代码块");
} {
System.out.println("子类构造代码块");
} public SubClass(){
System.out.println("子类构造函数");
} }
测试:
public static void main(String[] args) {
SubClass sb = new SubClass();
System.out.println("------------");
SubClass sb1 = new SubClass();
}
打印结果:
Java中静态代码块、构造代码块、构造函数、普通代码块的更多相关文章
- Java 中静态代码块初始化问题测试
Java 中静态代码块初始化问题测试 原创 情况一:变量是 static final 修饰的"编译期常量",如 public static final String a = &qu ...
- java中静态代码执行顺序
1.Java中静态变量只能在类主体中定义,不能在方法中定义. 静态变量属于类所有而不属于方法. 2. 静态块:用static申明,JVM加载类时执行,仅执行一次 构造块:类中直接用{}定义,每一次创建 ...
- 浅谈Java中静态初始化块跟非初始化块
众所周知在JAVA编程语言中有两种初始化块: 静态初始化块 非静态初始化块 他们到底有什么区别呢?今天就浅谈一下JAVA中静态初始化块和非静态初始化块的区别 静态初始化块 定义: ...
- 关于JAVA中事件分发和监听机制实现的代码实例-绝对原创实用
http://blog.csdn.net/5iasp/article/details/37054171 文章标题:关于JAVA中事件分发和监听机制实现的代码实例 文章地址: http://blog.c ...
- java中如何把图片转换成二进制流的代码
在学习期间,把开发过程经常用到的一些代码段做个备份,下边代码内容是关于java中如何把图片转换成二进制流的代码,应该能对各朋友也有用处. public byte[] SetImageToByteArr ...
- java中静态属性和和静态方法的继承问题 以及多态的实质
首先结论是:java中静态属性和和静态方法可以被继承,但是没有被重写(overwrite)而是被隐藏. 静态方法和属性是属于类的,调用的时候直接通过类名.方法名完成的,不需继承机制就可以调用如果子类里 ...
- Java中静态变量的声明位置
Java中静态变量只能是成员变量,局部方法中的局部变量除final外不能有任何其他修饰符,例如: public class Test { static String x = "1" ...
- 谈谈java中静态变量与静态方法在有继承关系的两个类中调用
谈谈java中静态变量与静态方法在有继承关系的两个类中调用 学习的中如果遇到不明白或者不清楚的的时候,就是自己做些测试,自己去试试,这次我就做一个关于静态变量和静态方法在有继承关系的两个类中的问题测试 ...
- Java 中静态变量和实例变量区别
Java 中静态变量和实例变量区别 静态变量属于类,该类不生产对象,通过类名就可以调用静态变量. 实例变量属于该类的对象,必须产生该类对象,才能调用实例变量. 在程序运行时的区别: 实例变量属于某个对 ...
- java中继承,子类是否继承父类的构造函数
java中继承,子类是否继承父类的构造函数 java继承中子类是不会继承父类的构造函数的,只是必须调用(隐式或者显式) 下面来看例子: public class TestExtends { publi ...
随机推荐
- VS2015远程调试
原文链接 VS2015远程调试 在PayPal支付时,PayPal回调函数一直报错,本地没有外网IP,没有办法在本地调试,需要远程调试: 1.找到远程调试的文件夹: 找到对应的服务器的型号:64位 ...
- P1040 加分二叉树
转自:(http://www.cnblogs.com/geek-007/p/7197439.html) 经典例题:加分二叉树(Luogu 1040) 设一个 n 个节点的二叉树 tree 的中序遍历为 ...
- C#访问C++动态分配的数组指针
项目中遇到C#调用C++算法库的情况,C++内部运算结果返回矩形坐标数组(事先长度未知且不可预计),下面方法适用于访问C++内部分配的任何结构体类型数组.当时想当然的用ref array[]传递参数, ...
- Python学习之--socket
1.Socket概述 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket.socket通常也称作"套接字",用于描述IP地址和端口,是一个 ...
- 【NOIP2015提高组】运输计划
https://daniu.luogu.org/problem/show?pid=2680 使完成所有运输计划的时间最短,也就是使时间最长的运输计划耗时最短.最大值最小问题考虑用二分答案,每次chec ...
- 高效管理http连接
1.Http连接基础 Http协议承载了互联网上的主要流量,然而说到传输,还要回归到最基本的网络分层模型TCP/IP.TCP/IP是全球计算机及网络设备都在使用的一种常用的分组交互网络分层协议集.客户 ...
- SQL-Oracle游标
游标提供了一种从集合性质的结果集中提供出单条记录的手段.初始时指向首记录. 游标的种类 静态游标.REF游标 静态游标:能够理解为一个数据快照,打开游标后的结果集是数据库表中数据的备份,数据不会对表的 ...
- Oracle学习笔记(7)——高级查询(1)
在学习高级查询之前,我们先了解一下怎样查看Oracle数据库中的全部表.由于我们要使用到Oracle数据库中SCOTT用户下的几张表(这些表是Oracle数据库自带的表). 分组查询 分组函数的概念: ...
- Android进程间通信与数据共享(ppt)
- 快速上手virtualenv
五分钟轻松学会管理项目开发环境. 在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.x.所有第三方的包都会被pip安装到Python3的site-packages目录下. p ...