static语句块的执行时间
package utfTest;
public class Test01 {
public static void main(String[] args) {
//Person.show();
System.out.println("p还没有初始化");
Class cls=Person.class;
System.out.println("执行了语句:Class cls=Person.class;不知道static语句在这条语句之前是否有输出");
Person p = new Person();
System.out.println("p刚刚被初始化,这里输出是用来验证static语句块是在哪里被输出的");
p.setName("小明");
p.setAge(18);
Person p1 = p;
p1.setAge(10);
p.setName("小邹");
System.out.println("p1创建了");
System.out.println(p.getName()+" "+p.getAge());
System.out.println(p1.getName()+" "+p1.getAge());
}
}
class Person{
int age;
String name;
static int id=0;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
static{
System.out.println("这里输出的是静态代码块");//这条语句在编译阶段执行,只会被执行一次
System.out.println("id="+id);
}
static public void show(){
System.out.println("这是static方法,我是在什么时候被输出的呢?");
}
}
运行结果是:
static语句块是在初始化阶段被执行的,而不是类加载阶段。
如果在main方法的开头添加了代码块:Person.show();那么运行结果是:
以下转载自:https://blog.csdn.net/berber78/article/details/46472789
一、误区:简单认为JAVA静态代码块在类被加载时就会自动执行。证错如下:
- class MyClass1 {
- static {//静态块
- System.out.println("static block ");
- }
- }
- public class Main {
- Class[] classArray = {
- MyClass1.class//这样引用该类,必然需要将该类加载到虚拟机中
- };
- public static void main(String[] args){
- System.out.println("hello word");
- }
- }
执行结果:并没有输出" static bolck"
二、正解:static块真正的执行时机。如果了解JVM原理,我们知道,一个类的运行分为以下步骤:
- 装载
- 连接
- 初始化
其中装载阶段又三个基本动作组成:
- 通过类型的完全限定名,产生一个代表该类型的二进制数据流
- 解析这个二进制数据流为方法区内的内部数据结
- 构创建一个表示该类型的java.lang.Class类的实例
另外如果一个类装载器在预先装载的时遇到缺失或错误的class文件,它需要等到程序首次主动使用该类时才报告错误。
连接阶段又分为三部分:
- 验证,确认类型符合Java语言的语义,检查各个类之间的二进制兼容性(比如final的类不用拥有子类等),另外还需要进行符号引用的验证。
- 准备,Java虚拟机为类变量分配内存,设置默认初始值。
- 解析(可选的) ,在类型的常量池中寻找类,接口,字段和方法的符号引用,把这些符号引用替换成直接引用的过程。
当一个类被主动使用时,Java虚拟就会对其初始化,如下六种情况为主动使用:
- 当创建某个类的新实例时(如通过new或者反射,克隆,反序列化等)
- 当调用某个类的静态方法时
- 当使用某个类或接口的静态字段时
- 当调用Java API中的某些反射方法时,比如类Class中的方法,或者java.lang.reflect中的类的方法时
- 当初始化某个子类时
- 当虚拟机启动某个被标明为启动类的类(即包含main方法的那个类)
Java编译器会收集所有的类变量初始化语句和类型的静态初始化器,将这些放到一个特殊的方法中:clinit。
实际上,static块的执行发生在“初始化”的阶段。初始化阶段,jvm主要完成对静态变量的初始化,静态块执行等工作。
下面我们看看执行static块的几种情况:
1、第一次new A()的过程会打印"";因为这个过程包括了初始化
2、第一次Class.forName("A")的过程会打印"";因为这个过程相当于Class.forName("A",true,this.getClass().getClassLoader());
3、第一次Class.forName("A",false,this.getClass().getClassLoader())的过程则不会打印""。因为false指明了装载类的过程中,不进行初始化。不初始化则不会执行static块。
参考资料:《深入Java虚拟机》
---------------------
本文来自 berber78 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/berber78/article/details/46472789?utm_source=copy
static语句块的执行时间的更多相关文章
- static{ }语句块详解
static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法.举ge例子: public class Test { public static i ...
- 转 java中static{}语句块详解
原文地址:http://blog.csdn.net/lubiaopan/article/details/4802430 感谢原作者! static{}(即static块),会在类被加载的时候执 ...
- java中static{}语句块详解
static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法,下面我们详细的讨论一下该语句块的特性及应用. 一.在程序的一次执行过程中,stati ...
- 关于java的static语句块
声明:转载请注明出处 static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法,下面我们详细的讨论一下该语句块的特性及应用. 一.在程序的一次 ...
- Static语句块和初始语句块的使用---2015年10月恒生电子笔试试卷
package lhm.test; /** * @author lenovo * */public class Person { private int id; private static int ...
- Java static{}语句块详解
[转自] http://blog.csdn.net/lubiaopan/article/details/4802430 static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一 ...
- static 语句块
static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法,下面我们详细的讨论一下该语句块的特性及应用. 一.在程序的一次执行过程中,stati ...
- Java中关于static语句块的理解
Java中关于static语句块的理解 一.static块会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法. 实例一 public class A{ String name ...
- Java static 语句块
总结前一天学习,参考原文http://www.cnblogs.com/dolphin0520/p/3799052.html1: 对Static有了进一步的认识 这个地方重点是初始化各个变量顺序, ...
随机推荐
- shell程序
例一:helloworld #!/bin/sh -x message="hello" read name echo "$message ,$name" 例二:选 ...
- highcharts 绘制图标的JAVASCRIPT 类库 收藏
官方站点 : http://www.highcharts.com 演示样例网址 : http://www.highcharts.com
- dom控制
(1)创建新节点 createDocumentFragment() //创建一个DOM片段 createElement_x_x() //创建一个具体的元素 createTextNode() ...
- request获取数据的几种方法
1.request.getparameter(); String value=request.getparameter("key"); 2.request.getParameter ...
- AndroidX86模拟器Genymotion的一些使用和另一款Andy模拟器
命令行启动虚拟机 当我们下载安装好,可以通过命令行运行指定名字模拟器 D:\ProgramFiles\Genymobile\Genymotion\player --vm-name "Sam ...
- jquery垂直滚动插件一个参数用于设置速度,兼容ie6
利用外层的块级元素负外边距来滚动 1.使用 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://ww ...
- Ubuntu下安装和编译ffmpeg
参考:http://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu 1.安装依赖包 sudo apt-get update sudo apt-get -y ...
- 迁移EXT4
http://fanli7.net/a/JAVAbiancheng/ANT/20101003/43604.html 級別: 中級 Roderick W. Smith ,顧問和作家 2008 年6 月0 ...
- linux下proc里关于磁盘性能的参数(转)
我们在磁盘写操作持续繁忙的服务器上曾经碰到一个特殊的性能问题.每隔 30 秒,服务器就会遇到磁盘写活动高峰,导致请求处理延迟非常大(超过3秒).后来上网查了一下资料,通过调整内核参数,将写活动的高峰分 ...
- XP,32/64位Win7,32/64位Win10系统【电脑城版】
本系统是10月最新完整版本的Windows10 安装版镜像,Win10正式版,更新了重要补丁,提升应用加载速度,微软和百度今天宣布达成合作,百度成为Win10 Edge浏览器中国默认主页和搜索引擎,系 ...