java类加载
先来看一段小程序:
package com;
public class Main1 {
static {
System.out.println("1111") ;
}
public static void main(String[] args) {
System.out.println("2222") ;
}
}
输出结果为:
1111
2222
其中static的执行时机就是class被 classloader加载的时候执行。
这有什么用?看下面代码
package com;
import java.util.ArrayList;
import java.util.List;
public class Main1 {
public static List<String> keyNames = new ArrayList<String>();
static {
keyNames.add("语文");
keyNames.add("数学");
keyNames.add("英语");
keyNames.add("物理");
keyNames.add("化学");
keyNames.add("历史");
keyNames.add("政治");
}
public static void main(String[] args) {
for(String key : keyNames)
System.out.printf("key = %s\n", key);
}
}
程序输出结果:
key = 语文
key = 数学
key = 英语
key = 物理
key = 化学
key = 历史
key = 政治
讨论:
任何语言任何平台开发的时候我们都需要有静态的全局资源,有些是单独的字段,比如应用系统名称,版本,服务器下载地址等等。这些静态资源可以直接赋值加载。但是不是所有资源都能够赋值初始化,比如某些静态资源是集合类型的,比如一个城市下面有多少个行政区,一个学校有多少个教室,比如上面例子程序中有多少个学科。这些数据最后可能会影响显示多少个page,会将应用程序分成多个tab。
一般的方法是singleton(单例模式),在初始化的时候赋值添加这些集合成员。
但是使用java这个static 代码区特性,可以定义一段代码,在.class文件被加载到虚拟机的过程中自动执行这段代码初始化,它甚至比main函数还要先执行。
static块代码,可以有多个,比如下面代码:
package com;
import java.util.ArrayList;
import java.util.List;
public class Main1 {
public static List<String> keyNames = new ArrayList<String>();
static {
keyNames.add("语文");
keyNames.add("数学");
keyNames.add("英语");
keyNames.add("物理");
keyNames.add("化学");
keyNames.add("历史");
keyNames.add("政治");
}
static {
keyNames.add("1");
keyNames.add("2");
keyNames.add("3");
keyNames.add("4");
keyNames.add("5");
keyNames.add("6");
keyNames.add("7");
}
public static void main(String[] args) {
for(String key : keyNames)
System.out.printf("key = %s\n", key);
}
}
也就是可以分模块加载不同业务模块的静态数据。
static 模块的代码,只有在这个class被使用的时候加载,看下面例子代码:
package com;
class Test {
static {
System.out.println("Test.class 被加载到虚拟机。");
}
public static void test(){}
}
public class Main1 {
static {
System.out.println("Main1.class 被加载到虚拟机。");
}
public static void main(String[] args) {
System.out.println("Test.test() 方法被执行之前。");
Test.test();
System.out.println("Main1.main 方法被执行之后。");
}
}
上面代码输出内容为:
Main1.class 被加载到虚拟机。
Test.test() 方法被执行之前。
Test.class 被加载到虚拟机。
Main1.main 方法被执行之后。
可以看到,Test的static代码块,并不是程序一开始执行就执行了,而是要等待Test类被使用的时候,才会被执行。
这样也不用担心程序一开始加载资源过多什么的。
多掌握这些技巧,可以在特定的需求下,不用写一些别扭的代码,任何需求都可以实现,但是要找到最合适的方式实现,就需要多积累一些技巧。