静态代码块 static{}

简介: 静态代码块 static{}

所谓的代码块就是一段独立的代码空间,那什么是静态代码块呢?说白了,静态代码块就是用static修饰的代码块,关于静态代码块的概念不多说,不过你需要知道它的一个特点,那就是


随着类的加载而执行,而且只执行一次


用代码验证静态代码块随着类的加载而执行,且执行一次


class StaticDemo{
//静态代码块
static {
System.out.println("静态代码块被执行");
}
void show(){
System.out.println("方法被执行");
}
}
public class StaticTest {
/**
* 静态代码块的特点:
* 随着类的加载而执行,而且只执行一次
*/
public static void main(String[] args){
new StaticDemo().show();
new StaticDemo().show();
}


执行结果如下


image.png


由输出结果我们可以看见,最先被打印的是静态代码块的输出内容,这就说明在加载类的时候是先执行了静态代码块的内容,随后调用了类中的方法,当再次创建实例调用方法的时候只有方法被调用了,而静态代码块不再执行,因此,静态代码块的特点是随着类的加载而执行,而且只执行一次!


与main函数的执行顺序

其实猜也猜得到静态代码块是先于main函数执行的,不过始终是眼见为实,让我们来用代码验证一下吧!


public class StaticTest {
/**
* 静态代码块的特点:
* 随着类的加载而执行,而且只执行一次
* 静态代码块的执行顺序优先于main函数
*/
static {
System.out.println("a");
}
public static void main(String[] hq){
System.out.println("b");
}
}


我们看执行结果,输出如下


image.png


代码验证结果依然是静态代码块优先于main函数执行,其实这是必然的,因为静态代码块是随着类的加载而执行。


为了让你我都更明白静态代码块的执行情况,接下来我们来一个稍微复杂点的,我们看看在继承当中的情况,代码如下


class StaticDemo{
//静态代码块
static {
System.out.println("父类静态代码块被执行");
}
void show(){
System.out.println("父类方法被执行");
}
}
public class StaticTest extends StaticDemo {
/**
* 静态代码块的特点:
* 随着类的加载而执行,而且只执行一次
* 静态代码块额执行顺序优先于main函数
*/
static {
System.out.println("子类静态代码块被执行");
}
void show(){
System.out.println("子类方法被执行");
}
public static void main(String[] hq){
System.out.println("main函数");
StaticTest staticTest = new StaticTest();
}
}


我们先来看以上代码,你能猜出以上代码的运行结果是什么吗?还是先看下结果吧


image.png


和你想的一样吗?我们知道静态代码块的加载是随着类的加载而执行,当执行main函数之前,StaticTest这个类被加载,而这个类又是继承自StaticDemo,因此会最先执行StaticDemo中的静态代码块,然后再执行StaticTest中的静态代码块,最后再执行main函数中的输出语句。


接下来我们再加上构造方法和非静态代码块,接下来的代码希望你能经常看看,那么静态代码块这块就足够了。


class StaticDemo{
//静态代码块
static {
System.out.println("父类静态代码块被执行");
}
//非静态代码块
{
System.out.println("父类非静态代码块被执行");
}
//构造方法
StaticDemo(){
System.out.println("父类构造方法被执行");
}
}
public class StaticTest extends StaticDemo {
/**
* 静态代码块的特点:
* 随着类的加载而执行,而且只执行一次
* 静态代码块额执行顺序优先于main函数
*/
static {
System.out.println("子类静态代码块被执行");
}
//非静态代码块
{
System.out.println("子类非静态代码块被执行");
}
StaticTest(){
System.out.println("子类构造方法被执行");
}
public static void main(String[] hq){
System.out.println("main函数");
new StaticTest();
}
}


你猜猜以上代码执行之后的输出结果是什么?我们来看最终的运行结果


image.png


总结

通过以上输出我们能总结出什么呢?


总结:静态代码块会随着类的加载而执行,而且只执行一次。当new StaticTest()开始执行的时候会先去执行父类中的静态代码块,然后再执行子类中的静态代码块,当所有的静态代码块都执行结束后会执行main函数中的输出语句(前提是输出语句在new StaticTest()之前),然后会去执行父类中的非静态代码块,接着是父类中的构造方法,紧接着执行子类中的非静态代码块,最后是子类中的构造方法,完事!


目录
相关文章
|
存储 缓存 数据管理
HarmonyOS学习路之开发篇—数据管理(轻量级数据存储)
轻量级数据存储适用于对Key-Value结构的数据进行存取和持久化操作。应用获取某个轻量级存储对象后,该存储对象中的数据将会被缓存在内存中,以便应用获得更快的数据存取速度。应用也可以将缓存的数据再次写回文本文件中进行持久化存储,由于文件读写将产生不可避免的系统资源开销,建议应用减少对持久化文件的读写频率。
|
Linux 开发者 Docker
Docker 引擎启动、停止、重启操作|学习笔记
快速学习 Docker 引擎启动、停止、重启操作
|
IDE 算法 中间件
初识REDHAWK
初识REDHAWK
516 2
|
关系型数据库 MySQL 编译器
【Qt 数据库 】qt使用mysql的准备工作
【Qt 数据库 】qt使用mysql的准备工作
369 1
|
存储 安全 C++
C++ 原子变量atomic variable
原子变量是 C++11 引入的一种同步机制,用于多线程环境中的无锁、线程安全操作。其操作不可分割,避免了数据竞争和不一致问题。原子变量位于 `<atomic>` 头文件中,支持多种类型如 `std::atomic<T>` 和特化类型。基本用法包括定义原子变量、加载、存储、交换及比较交换操作。内存顺序(如 `std::memory_order_seq_cst`)用于控制内存访问顺序和可见性,适用于不同场景。原子变量常用于线程安全的计数器和标志位等。
默认移动构造、默认移动赋值自动生成的条件
默认移动构造、默认移动赋值自动生成的条件
330 0
使用IntelliJ IDEA查看类图,内容极度舒适
使用IntelliJ IDEA查看类图,内容极度舒适
336 1
|
Linux API C++
C++ 11 使用detach()和join()函数使用的注意点
最近做项目的时候,使用了c++11的多线程,以前做项目都是使用微软提供的一些api,比如临界区、Mutex等来实现多线程,但是比如临界区这玩意只在windows下才有,linux是没有这个概念的,所以为了跨平台,c++11之后,就提供了多线程的支持。
293 0
|
Linux API
pthread_mutex_init & 互斥锁pthread_mutex_t的使用
pthread_mutex_init l         头文件: #include l         函数原型: int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr); pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; l         函数作用: 该函数用于C函数的多线程编程中,互斥锁的初始化。
2101 0
|
Java C语言
【C语言】【static用法】C语言实现静态代码块
【C语言】【static用法】C语言实现静态代码块
394 0