Java静态块(静态初始化,实例初始化和构造方法)总结

来源:互联网 发布:逐点比较圆弧插补vb 编辑:程序博客网 时间:2024/05/16 14:30

这篇文章总结来自于两篇博文:

http://blog.csdn.net/clam_clam/article/details/6689998

http://hbiao68.iteye.com/blog/1676081

首先有三个概念需要了解:

一.静态初始化:是指执行静态初始化块里面的内容。
二.实例初始化:是指执行实例初始化块里面的内容。
三.构造方法:一个名称跟类的名称一样的方法,特殊在于不带返回值。
我们先来看一段程序结果:

[java] view plaincopy
  1. package com;  
  2.   
  3. class Book{       
  4.     public static int booksum=0;//静态变量       
  5.        
  6.     static{//这是静态初始化块  
  7.         print();       
  8.         System.out.println("this is static block");       
  9.     }       
  10.        
  11.     {//实例初始化块       
  12.         System.out.println("初始化块:"+booksum);       
  13.     }       
  14.        
  15.     public Book(){//构造方法       
  16.         System.out.println("this is Book's constructor~");       
  17.         booksum+=1;       
  18.     }       
  19.        
  20.     public static void print(){//静态方法       
  21.         System.out.println("this is static method~");       
  22.     }   
  23.       
  24.     public static void main(String []args){  
  25.         //Book book=new Book();  
  26.     }  
  27. }  

执行结果:
this is static method~
this is static block
如果把 
[java] view plaincopy
  1. public static void main(String []args){  
  2.     //Book book=new Book();  
  3.   }  
的注释去掉的话,运行结果为:
this is static method~
this is static block
初始化块:0
this is Book's constructor~
总结:

仅从代码执行的角度来探讨Java加载类、创建对象的过程,并没有深入到JVM的机制中去。

1.一个对象第一次被创建时,先要加载该对象所属的类,即对应的.class文件,当然如果类已经加载,再次创建该类的对象时,就不再需要重新加载类了。而一个类加载的时候,有三个部分需要加载,一个是静态变量,再然后是静态方法,然后是静态初始化块。 (见到第一次执行结果就知道了,由于没有创建实例所以初始化块不执行)

2.然后开始创建该类的实例了,当然如果静态方法跟静态初始化对象中有对象的创建时,就继续加载该对象的类,当然已经加载了该对象的类的话就不需要再次加 载了。那么对象实例的创建过程是什么呢?首先是成员变量的引入,然后是实例初始化块,之后才是构造方法,构造方法执行完成之后才算把这个对象给创建出来了。

在这个过程中,真正可以编写执行代码的地方有三个,静态初始化、实例初始化以及构造方法。从以上的分析中我们可以看到,这三个代码块的执行顺序是先类的静态初始化,再实例初始化,最后执行构造方法。也就是说,静态初始化是属于类加载的过程,所以它只执行一次,而实例初始化是每个对象创建时都会执行一次,而构造方法跟实例初始化其实也差不多,不过它在实例初始化之后执行,而且构造方法可以重载多个,执行哪个构造方法是根据你的选择来的。
可以把main () 函数加一条语句看看:

[java] view plaincopy
  1. public static void main(String []args){  
  2.     Book book=new Book();  
  3.     Book book1=new Book();  
  4.  }  
此时执行结果为:

this is static method~
this is static block
初始化块:0
this is Book's constructor~
初始化块:1
this is Book's constructor~

这说明实例初始化是每个对象创建时都会执行的。


Java编译器会收集所有的类变量初始化语句和类型的静态初始化器,将这些放到一个特殊的方法中:clinit
实际上,static块的执行发生在“初始化”的阶段。初始化阶段,jvm主要完成对静态变量的初始化,静态块执行等工作

Java代码  收藏代码
  1. public class A {  
  2.   
  3.     static {  
  4.         System.out.println("static is a");  
  5.     }  
  6.     {  
  7.         System.out.println("class A block");  
  8.     }  
  9.       
  10.     public A(){  
  11.         System.out.println("this is a");  
  12.     }  
  13. }  

  

Java代码  收藏代码
  1. public class B extends A{  
  2.   
  3.     static{  
  4.         System.out.println("static is b");  
  5.     }  
  6.     {  
  7.         System.out.println("class B block");  
  8.     }  
  9.       
  10.     public B(){  
  11.         System.out.println("this is b");  
  12.     }  
  13. }  

 

Java代码  收藏代码
  1. package hb.mm;  
  2.   
  3. public class Test {  
  4.   
  5.     /** 
  6.      * 考察点 
  7.      * 当一个类被主动使用时,Java虚拟就会对其初始化,如下六种情况为主动使用: 
  8.  
  9. 1.当创建某个类的新实例时(如通过new或者反射,克隆,反序列化等) 
  10. 2.当调用某个类的静态方法时 
  11. 3.当使用某个类或接口的静态字段时 
  12. 4.当调用Java API中的某些反射方法时,比如类Class中的方法,或者java.lang.reflect中的类的 
  13. 方法时 
  14. 5.当初始化某个子类时 
  15. 6.当虚拟机启动某个被标明为启动类的类(即包含main方法的那个类) 
  16.  
  17.     Java编译器会收集所有的类变量初始化语句和类型的静态初始化器,将这些放到一个特殊的方法中: 
  18. clinit实际上,static块的执行发生在“初始化”的阶段。初始化阶段,jvm主要完成对静态变量的初 
  19. 始化,静态块执行等工作 
  20.      */  
  21.     public static void main(String[] args) {  
  22.         // 当子类被初始化的时候父类也要跟着初始化  
  23.         A ab = new B();  
  24.         System.out.println("---------------------");  
  25.         new B();  
  26.     }  
  27.   
  28. }  

 

static is a

static is b

class A block

this is a

class B block

this is b

---------------------

class A block

this is a

class B block

this is b



--------------------------------------------------------------------------------------------------------------------------------------------------

java静态变量存放区静态的意思:只有一份!不存在拷贝!

虚拟机内存分为四个区:stack segment,heap segment,data segment,code segment;
stack 区存放函数参数和局部变量;
heap  区存放对象;
data  区存放static 的变量或者字符串常量; 
code  区存放类中的方法;
所以,静态变量是存放在data区的

静态变量属于类的属性。至于他放在那里?有人说的是静态区。我不知道到底有没有这个翻译。但是 深入jvm里是是翻译为方法区的。虚拟机的体系结构:堆,方法区,本地方法栈,pc寄存器。而方法区保存的就是一个类的模板,堆是放类的实例的。栈是一般来用来函数计算的。随便找本计算机底层的书都知道了。栈里的数据,函数执行完就不会存储了。这就是为什么局部变量每一次都是一样的。就算给他加一后,下次执行函数的时候还是原来的样子。


static函数与普通函数有什么区别:
static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝


全局变量和静态变量的区别: 
全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。全局变量(外部变量)的说明之前再冠以static就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。



0 0
原创粉丝点击