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类被使用的时候,才会被执行。
这样也不用担心程序一开始加载资源过多什么的。
多掌握这些技巧,可以在特定的需求下,不用写一些别扭的代码,任何需求都可以实现,但是要找到最合适的方式实现,就需要多积累一些技巧。