static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法,下面我们详细的讨论一下该语句块的特性及应用。
一、在程序的一次执行过程中,static{}语句块中的内容只被执行一次,看下面的示例:
示例一
class Test{ public static int X=100; public final static int Y;=200 public Test(){ System.out.println("Test构造函数执行"); } static{ System.out.println("static语句块执行"); } public static void display(){ System.out.println("静态方法被执行"); } public void display_1(){ System.out.println("实例方法被执行"); } } public class StaticBlockTest{ public static void main(String args[]){ try{ Class.forName("Test"); Class.forName("Test"); }catch(ClassNotFoundException e){ e.printStackTrace(); } } }
结果:你会发现虽然执行了两条Class.forName("Test")语句,但是,只输出了一条"静态方法被执行"语句;其实第二条Class.forName()语句已经无效了,因为在虚拟机的生命周期中一个类只被加载一次;又因为static{}是伴随类加载执行的,所以,不管你new多少次对象实例,static{}都只执行一次。 --关于类加载请看本文的附录。
二、static{}语句块执行的时机(其实就是附录中类加载的时机)
上面说到static{}会在类被加载的时候执行,我们必须准确理解类加载的准确含义,含义如下:
1、用Class.forName()显示加载的时候,如上面的示例一;
2、实例化一个类的时候,如将main()函数的内容改为:Test t=new Test();//这种形式其实和1相比,原理是相同的,都是显示的加载这个类,读者可以验证Test t=new Test();和Test t=(Test)Class.forName().newInstance();这两条语句效果相同。
3、调用类的静态方法的时候,如将main()函数的内容改为:Test.display();
4、调用类的静态变量的时候,如将main()函数的内容改为:System.out.println(Test.X);
总体来说就这四种情况,但是我们特别需要注意一下两点:
1、调用类的静态常量的时候,是不会加载类的,即不会执行static{}语句块,读者可以自己验证一下(将main()函数的内容改为System.out.println(Test.Y);),你会发现程序只输出了一个200;(这是Java虚拟机的规定,当访问类的静态常量时,如果编译器可以计算出常量的值,则不会加载类,否则会加载类)
2、用Class.forName()形式的时候,我们也可以自己设定要不要加载类,如将Class.forName("Test")改为 Class.forName("Test",false,StaticBlockTest.class.getClassLoader()),你会发现程序什么都没有输出,即Test没有被加载,static{}没有被执行。
三、static{}语句块的执行次序
1、当一个类中有多个static{}的时候,按照static{}的定义顺序,从前往后执行;
2、先执行完static{}语句块的内容,才会执行调用语句;
示例二
public class TestStatic{ static{ System.out.println(1); } static { System.out.println(2); } static { System.out.println(3); } public static void main(String args[]){ System.out.println(5); } static { System.out.println(4); } }
结果:程序会输出1,2,3,4,5
3、如果静态变量在定义的时候就赋给了初值(如 static int X=100),那么赋值操作也是在类加载的时候完成的,并且当一个类中既有static{}又有static变量的时候,同样遵循“先定义先执行”的原则;
示例三
class Test{ public static int X=300; static{ System.out.println(X); X=200; System.out.println(X); } } public class StaticBlockTest{ public static void main(String args[]){ System.out.println(Test.X); } }
结果:程序会依次输出300,200,200,先执行完X=300,再执行static{}语句块。
四、static{}语句块应用
1、JDBC中的应用
熟悉JDBC的读者应该知道,java中有一个DriverManager类,用于管理各种数据库驱动程序、建立新的数据库连接。DriverManager类包含一些列Drivers类,这些Drivers类必须通过调用DriverManager的registerDriver()方法来对自己进行注册,那么注册是什么时候发生的呢?下面会给出答案:
所有Drivers类都必须包含有一个静态方法,利用这个静态方法可以创建该类的实例,然后在加载该实例时向DriverManage类进行注册。我们经常用Class.forName()对驱动程序进行加载,那么注册就发生在这条语句的执行过程中,前面说的Drivers的静态方法是放在static{}中的,当对驱动程序进行加载的时候,会执行该static{},便完成了注册。
2、hibernate中的应用
hibernate中的SessionFactory是一个重量级的类,创建该类的对象实例会耗费比较多的系统资源,如果每次需要时都创建一个该类的实例,显然会降低程序的执行效率,所以经常将对该类的实例化放在一个static{}中,只需第一次调用时执行,提高程序的执行效率,如下:
static { try { configuration.configure(configFile); sessionFactory = configuration.buildSessionFactory(); } catch (Exception e) { System.err.println("%%%% Error Creating SessionFactory %%%%"); e.printStackTrace(); } }
五、附录
类加载:Java命令的作用是启动虚拟机,虚拟机通过输入流,从磁盘上将字节码文件(.class文件)中的内容读入虚拟机,并保存起来的过程就是类加载。
类加载特性 :
*在虚拟机的生命周期中一个类只被加载一次。
*类加载的原则:延迟加载,能少加载就少加载,因为虚拟机的空间是有限的。
*类加载的时机:
1)第一次创建对象要加载类.
2)调用静态方法时要加载类,访问静态属性时会加载类。
3)加载子类时必定会先加载父类。
4)创建对象引用不加载类.
5) 子类调用父类的静态方法时
(1)当子类没有覆盖父类的静态方法时,只加载父类,不加载子类
(2)当子类有覆盖父类的静态方法时,既加载父类,又加载子类
6)访问静态常量,如果编译器可以计算出常量的值,则不会加载类,例如:public static final int a =123;否则会加载类,例如:public static final int a = math.PI。
相关推荐
### Java中的Static属性详解 #### 一、引言 在Java编程语言中,`static`关键字扮演着重要的角色。它允许我们创建与类关联而非特定实例关联的数据成员和方法。本文将详细介绍`static`属性的基本概念、静态成员变量...
Java中的`static`关键字在编程中扮演着至关重要的角色,主要用在以下几个方面: 1. **静态变量(Static Variables)**: - 静态变量由类共享,而不是由类的实例(对象)单独拥有。这意味着所有实例共享同一份静态...
在Java编程语言中,`static`关键字扮演着至关重要的角色,它允许我们定义静态成员变量、静态方法和静态初始化块。这些静态元素具有以下几个关键特点: 1. **静态变量(Static Variables)**: - 静态变量是属于类...
Java 中 Switch 选择语句代码详解 Java 中的 Switch 选择语句是一种多路分支语句,用于根据不同的条件来执行不同的语句块。下面是 Switch 语句的基本结构: switch(表达式){ case 常量1: 语句块1; break; case...
Java中的`static`关键字是用来声明类级别的成员,包括变量、方法和代码块。它与对象无关,而是直接关联到类本身。以下是对`static`关键字的详细解释: 1. **静态变量(Static Variables)** - 静态变量是属于类的...
详解 Java 语言中的跳转语句 本文详细介绍了 Java 语言中的跳转语句,包括 break 语句和 continue 语句的使用方法和区别。跳转语句是 Java 语言中的重要组成部分,对程序的控制流程和可读性产生了重要的影响。本文...
在Java编程语言中,`static`关键字用于定义类级别的成员,包括变量和方法。静态成员不依赖于类的实例,而是直接与类相关联。这意味着它们在类加载时被初始化,并且所有类的实例都可以共享这些静态成员。下面将详细...
总结来说,Java中的`static`块主要用于类的初始化,它在类加载时执行一次,常用于设置类级别变量的初始值。`static`块内的局部变量只在该块内部有效,不会影响到类级别的同名变量。了解并正确使用`static`块对于理解...
Java中的`static`关键字是用来修饰成员变量、成员方法和代码块的,它的主要作用在于创建全局或静态的实体,使得这些实体独立于类的任何实例存在。下面将详细阐述`static`的各个方面: 1. **静态变量(Static ...
语句块 2. 成员变量(但是不能修饰局部变量) 3. 方法 4. 接口(内部接口) 5. 类(只能修饰在类中的类, 即静态内部类) 6. jdk 1.5 中新增的静态导入 那么static 修饰的表示什么呢? 当创建一个类时,...
Java循环语句详解 Java中的循环语句是指在一个程序中,重复执行某些语句的语句。循环语句有三种基本形式:for循环、while循环和do-while循环。每种循环语句都有其特点和使用场景。在本实验中,我们将详细介绍这三种...
Java复合语句的使用方法详解 Java复合语句是一种重要的语句结构,在 Java 编程中占据着核心地位。本文将详细介绍 Java 复合语句的使用方法及其实例。 什么是 Java 复合语句 Java 复合语句是一种语句结构,它由开...
Java中的`static`关键字在编程中扮演着至关重要的角色,它是Java类定义的一部分,用于修饰类的成员变量、成员方法以及代码块。下面我们将详细探讨`static`变量、`static`方法以及`static`代码块的作用和用法。 1. *...
Java基础入门编程详解,这本书籍是为初学者精心编写的,旨在帮助他们系统地学习Java编程语言的基础知识。Java作为一种广泛应用于互联网、企业级应用、移动开发等领域的编程语言,其扎实的基础对于开发者来说至关重要...
### Java流程控制语句详解 #### 一、概述 Java是一种广泛使用的面向对象编程语言,其强大的功能之一在于能够通过不同的流程控制语句来决定程序的执行路径。这些流程控制语句包括顺序语句、选择语句(如if...else...
本文详细介绍了 Java 中使用 continue 语句的实例详解,包括基本概念、使用 continue 语句的实例详解、注意事项等。通过本文,读者可以了解如何使用 continue 语句来控制循环的执行,可以更好地掌握 Java 编程语言。
5. Character 流和 Byte 流是 Java 语言中的两种流,前者是块读写,后者是字节读写。 6. 监听事件和处理事件是 Java 语言中的事件处理机制,Listener 需要登记事件处理构件。 7. Applet 是 Java 语言中的小程序,...
### Java synchronized 关键字详解 #### 一、synchronized关键字简介 `synchronized`是Java语言提供的关键字之一,用于实现线程间的同步控制。通过在方法或代码块上使用`synchronized`,可以确保同一时间只有一个...
### Java控制语句详解 #### 一、概述 在Java编程语言中,控制语句扮演着极其重要的角色,它们能够使程序逻辑更加灵活多样。控制语句主要包括顺序语句、选择语句(如if...else)、循环语句等。本文将重点介绍选择...
Java 输入输出语句详解 Java 语言中,输入输出语句是编程的基本组成部分。本文将详细介绍 Java 中的输入输出语句,包括标准输入输出流、控制台输入、BufferedReader 和 Scanner 的使用。 一、标准输入输出流 Java...