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打印出来。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)