Java基础: 静态与动态代码块
来源:互联网 发布:快剪软件 编辑:程序博客网 时间:2024/05/22 13:39
定义:在定义属性的位置上,在任何方法之外,定义一个代码块
种类:分为两类即动态代码块、静态代码块
<1> 动态初始代码块:在初始化属性之前调用初始化代码块 {……}
<2> 静态初始代码块:在类加载时运行 static{……} 只被运行一次,往往用作一个类的准备工作
示例代码:
- package mark.zhang;
- public class Linux {
- /**
- * 动态代码块
- */
- {
- System.out.println("--动态初始化代码块--");
- }
- /**
- * 静态代码块
- */
- static {
- System.out.println("--静态初始化代码块--");
- }
- /**
- * 测试
- *
- * @param args
- */
- public static void main(String[] args) {
- Linux linux = new Linux();
- }
- }
执行结果:
- --静态初始化代码块--
- --动态初始化代码块--
从结果看出,创建Linux类的实例时加载这个类,从而代码块执行,只是静态代码块先于动态代码块之前执行。那么,我们思考两个问题,类何时被加载,代码块、构造方法以及成员变量之间的执行顺序是谁先谁后??汗,别急,往下看。
先说一说类加载时机吧!!
(1)new 一个对象的时候,加载
(2)没有创建对象,访问类中静态方法(final和非final的均可以)和静态属性(不可以被final修饰,final修饰的静态属性是在常量池里),加载
(3)声明一个类的引用,不加载
(4)创建子类,先加载父类,再加载子类
(5)父类中的公开静态方法,子类继承,使用子类的类名调用此方法,加载父类
注意,这里需要满足两个条件:
<a> 子类不可以重写该静态方法,其实父类的静态方法子类是不可以重写只可以继承的。即使重写也要加上static关键字。那么也就说明父类的静态方法是不可以被子类重写的,子类重写的这个静态方法称之为子类自己的静态方法(只不过和父类的该静态方法重名罢了!!)
<b> main方法不可以在子类中,看例子代码,如下:
- package mark.zhang;
- public class Linux {
- /**
- * 动态代码块
- */
- {
- System.out.println("--父类Linux--动态初始化代码块--");
- }
- /**
- * 静态代码块
- */
- static {
- System.out.println("--父类Linux--静态初始化代码块--");
- }
- static void get() {
- System.out.println("--父类Linux--get()");
- }
- }
- class Ubuntu extends Linux {
- /**
- * 动态代码块
- */
- {
- System.out.println("--子类Linux--动态初始化代码块--");
- }
- /**
- * 静态代码块
- */
- static {
- System.out.println("--子类ubuntu静态初始化代码块--");
- }
- }
- class Test {
- /**
- * 测试
- *
- * @param args
- */
- public static void main(String[] args) {
- Ubuntu.get();
- }
- }
在主函数中运行以下代码:
- //加载了父类之后,虚拟机已经知道m()方法的调用了,就不会再加载子类,延迟加载
- Ubuntu.get();
运行结果:
- --父类Linux--静态初始化代码块--
- --父类Linux--get()
(6)没有创建对象,访问类中静态常量(能计算出结果的常量,在编译的时候会用计算出来的结果替换表达式),不加载
(7)没有创建对象,访问类中静态常量(不确定的值),加载
关于(6)(7),举两个个小例子吧??!!!
- package my.test;
- public class FinalTest {
- // 编译时常量,编译器在编译时会将所有用到该变量的地方替换成相应的字面值
- public static final int a = 4+4;
- static {
- System.out.println("--static code--");
- }
- }
- class Test {
- public static void main(String[] args) {
- System.out.println("FinalTest.a= " + FinalTest.a);
- }
- }
该例子中没有执行静态代码块,正如(6)所说。
运行结果:
- FinalTest.a= 8
再看一个例子,来说明(7)的正确性!!!
- package my.test;
- public class FinalTest {
- // 运行时常量,在运行的时候才能确定
- public static final int a = 4 + Math.abs(1);
- static {
- System.out.println("--static code--");
- }
- }
- class Test {
- public static void main(String[] args) {
- System.out.println("FinalTest.a= " + FinalTest.a);
- }
- }
运行结果,执行静态代码块内容。
- --static code--
- FinalTest.a= 5
ok,上面说的都是关于类的加载时机问题,接着说说代码块、构造方法以及成员变量之间的执行顺序的问题。要想说明白这个问题,需要从两个方面说,一个是单纯的一个类,另一个就是一个类与另一个类的继承。
<1> 单纯的一个类
- package mark.zhang;
- public class Linux {
- // 静态成员变量
- public static String name = "Linux OS";
- // 一般变量
- public int size = 2;
- public Linux() {
- System.out.println("--父类Linux--构造方法--");
- }
- /**
- * 动态代码块
- */
- {
- System.out.println("--父类Linux--动态初始化代码块--");
- }
- /**
- * 静态代码块
- */
- static {
- System.out.println("--父类Linux--静态初始化代码块--");
- }
- }
测试一下,呵呵!!
- class Test {
- /**
- * 测试
- *
- * @param args
- */
- public static void main(String[] args) {
- new Linux();
- }
- }
测试结果,如下:
- --父类Linux--静态初始化代码块--
- --父类Linux--动态初始化代码块--
- --父类Linux--构造方法--
<2> 具有继承关系的两个类
- package mark.zhang;
- public class Linux {
- // 静态成员变量
- public static String name = "Linux OS";
- // 一般变量
- public int size = 2;
- public Linux() {
- System.out.println("--父类Linux--构造方法--");
- }
- /**
- * 动态代码块
- */
- {
- System.out.println("--父类Linux--动态初始化代码块--");
- }
- /**
- * 静态代码块
- */
- static {
- System.out.println("--父类Linux--静态初始化代码块--");
- }
- }
- class Ubuntu extends Linux {
- public Ubuntu() {
- System.out.println("--子类Ubuntu--构造方法--");
- }
- /**
- * 动态代码块
- */
- {
- System.out.println("--子类Ubuntu--动态初始化代码块--");
- }
- /**
- * 静态代码块
- */
- static {
- System.out.println("--子类ubuntu静态初始化代码块--");
- }
- }
- class Test {
- /**
- * 测试
- *
- * @param args
- */
- public static void main(String[] args) {
- new Ubuntu();
- }
- }
执行结果,如下:
- --父类Linux--静态初始化代码块--
- --子类ubuntu静态初始化代码块--
- --父类Linux--动态初始化代码块--
- --父类Linux--构造方法--
- --子类Ubuntu--动态初始化代码块--
- --子类Ubuntu--构造方法--
至于,代码块与成员变量之间谁先谁后,其实是与它们在类中声明顺序有关的。现在以一个小例子说明问题:
- package mark.zhang;
- public class Linux {//静态与非静态成员变量与静态代码块、非静态代码块的执行顺序与其声明顺序有关
- RedHat rh1 = new RedHat("非静态成员变量rh1");
- static RedHat rh11 = new RedHat("静态成员变量rh11");
- public Linux() {
- System.out.println("--父类Linux--构造方法--");
- }
- /**
- * 动态代码块
- */
- {
- System.out.println("--父类Linux--动态初始化代码块--");
- }
- /**
- * 静态代码块
- */
- static {
- System.out.println("--父类Linux--静态初始化代码块--");
- }
- RedHat rh2 = new RedHat("非静态成员变量rh2");
- static RedHat rh22 = new RedHat("静态成员变量rh22");
- }
- class RedHat {
- static int times = 1;
- public RedHat(String info) {
- System.out.println(info + ", the order " + (times++));
- }
- }
测试:
- class Test {
- /**
- * 测试
- *
- * @param args
- */
- public static void main(String[] args) {
- new Linux();
- }
- }
运行结果:
- 静态成员变量rh11, the order 1
- --父类Linux--静态初始化代码块--
- 静态成员变量rh22, the order 2
- 非静态成员变量rh1, the order 3
- --父类Linux--动态初始化代码块--
- 非静态成员变量rh2, the order 4
- --父类Linux--构造方法--
- Java基础: 静态与动态代码块
- Java基础: 静态与动态代码块
- java 代码块,构造代码块,与静态代码块
- java 静态代码块与静态方法
- Java静态与非静态代码块
- java 静态代码块与非静态代码块
- java 静态代码块 动态代码块 加载时间
- 【java基础】static静态代码块,构造器代码块以及局部代码块的区别与应用!
- Java基础复习:构造代码块和静态代码块
- Java基础--静态代码块:static{}
- java基础-静态代码块执行
- JAVA代码块非静态代码块与静态代码块构造函数比较
- java static 与 static静态代码块
- java中的静态变量、静态方法与静态代码块
- java中的静态变量、静态方法与静态代码块
- java中的静态变量、静态方法与静态代码块
- 静态代码块和动态代码块
- java基础之静态代码块,局部代码块,构造代码块区别。
- 查找整数:给出一个包含n个整数的数列,问整数a在数列中的第一次出现是第几个。
- 也谈BIO | NIO | AIO (Java版)
- 剑指offer系列源码-和为S的连续正数序列
- 确定和监控网络连接状态
- 运行jar包时读取jar里面的文件
- Java基础: 静态与动态代码块
- 解读设计模式----简单工厂模式(SimpleFactory Pattern),你要什么我就给你什么
- 微信的末路基因,即时通讯走到终点?
- log4j日志配置
- WindowManager.LayoutParams.type属性
- jQuery对象和DOM对象之间的区别与相互转化
- java类加载全过程
- Jquery扩展
- [编程思想]领域模型和缓存应用【一】