JAVA中 静态块的作用

JAVA中 静态块的作用,第1张

我先说一下静态块吧,下面就是一个静态块,

static

{

}

静态块的特点是在类加载的时候就执行,先说一下类加载,一个程序要想运行,首先要把代码加载到内存中对吧?然后才能去和CPU交流,这是冯诺依曼计算机规定的。Java也是一样,Java的.class字节码文件要想执行,首先也要加载到内存,由类加载器把字节码文件的代码加载到内存中,这一步就叫类加载,这是首先要进行的。

public

class

Test

{

static

{

System.out.println("我是静态块")

}

}

当创建Test类的一个对象的时候,比如new

Test()

,是这样,首先是类加载,然后才能new对象,静态块在类加载的时候就执行了,这就说明静态块在new对象之前就会执行,而且一个类在第一次被使用的时候会被加载,然后在整个应用程序的生命周期当中不会再次被加载了,就加载这一次,所以这就说明,静态块就执行一次,不会执行第二遍!

public

class

Test

{

public

Test()

{//

构造方法

System.out.println("我是构造方法,创建对象的时候我会执行,我执行完,对象就造出来了")

}

static

{

System.out.println("我是静态块,类加载的时候我就执行了,而且只执行这一次")

}

}

然后这样:

new

Test()

new

Test()

你会发现首先打印出静态块的信息,然后才打印出构造方法信息,然后再次new

Test()的时候,只打印出了构造方法的信息,这个例子证明了我上面说的是对的!

这就是静态块,我说完了,至于你说的

静态块中初始化Map。

初始化这几个字很难讲他的意思,意思包括

把一些内容设为默认状态、把没准备的准备好、在什么什么之前就怎么怎么样、将变量赋为默认值,等等,这个不能精确的说,只能就事说事,下面就可以说是在静态块中初始化Map,

public

class

Test

{

private

static

Map

m

static

{

m

=

new

HashMap()

}

}

就说道这儿,楼主

看了一个帖子

写的是初始化Map的,

如果还有疑问

不如把地址贴出来,大家也好帮你,就光说初始化Map,这个问的太叫人没法回答了。

想了很久,终于弄明白为什么了。

静态块确实是在main之前运行,但这不是关键。 关键在于类的初始化过程。

类的初始化,包括静态赋值如 static boolean initialized = false和静态初始化块, static { ... }, 按照声明的顺序依次执行。某个线程在对某个类进行初始化的时候,会先给这个类加锁,直到初始化全部完成之后才释放锁。 你的代码存在死锁问题。

把代码改成这样,看看输出是什么:

public class HelloWorld {

private static boolean initialized = false

static Thread t = new Thread(new Runnable() {

public void run() {

System.out.println("aaaa")

System.out.println(initialized)// label

System.out.println("Hello ")

initialized = true

}

})

static {

t.start()

}

static {

try {

Thread.sleep(500)

}

catch(Exception e) {

}

System.out.println("bbbb")

}

public static void main(String[] args) {

System.out.println(" world!")

}

}

你会发现输出是这样的:

aaaa

bbbb

false ....

注意,bbbb总是在false之前打印,不管sleep多长时间。

而在run方法里,打印aaaa之后应该紧接着打印false才对,为什么还要等待睡觉中的bbbb呢?

虚拟机在执行 main之前,先要加载HelloWorld类,那么mian线程会对HelloWorld的Class加锁,然后依次执行

static boolean initialized = false

static Thread t = ...

static { t.start()}

static { sleep(500)print "bbbb"}

执行完这些语句,才会把锁释放。

在这之间,启动了t线程,t先打印aaaa,然后试图打印initialized,但是这时候HelloWorld的Class被锁定了,所以t线程必须等待main线程把锁释放掉,也就是上面所有的static语句执行完毕。等main线程执行完了bbbb,就会把锁释放掉,然后t线程就可以继续执行了。

如果加入了join语句,那么main线程就会等待t线程,但是t线程试图访问initialized的时候必须等待main线程,这就导致了死锁。你把label语句去掉之后,就不需要等到main线程了,所以会把hello打印出来。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11949869.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-19
下一篇 2023-05-19

发表评论

登录后才能评论

评论列表(0条)

保存