解析Java类和对象的初始化过程
类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和 JVM 层次来分析的文章更是鲜有所见。
本文主要对类和对象初始化全过程进行分析,通过一个实际问题引入,将源代码转换成 JVM 字节码后,对 JVM 执行过程的关键点进行全面解析,并在文中穿插入了相关 JVM 规范和 JVM 的部分内部理论知识,以理论与实际结合的方式介绍对象初始化和类初始化之间的协作以及可能存在的冲突问题。
问题引入
近日我在调试一个枚举类型的解析器程序,该解析器是将数据库内一万多条枚举代码装载到缓存中,为了实现快速定位枚举代码和具体枚举类别的所有枚举元素,该类在装载枚举代码的同时对其采取两种策略建立内存索引。由于该类是一个公共服务类,在程序各个层面都会使用到它,因此我将它实现为一个单例类。这个类在我调整类实例化语句位置之前运行正常,但当我把该类实例化语句调整到静态初始化语句之前时,我的程序不再为我工作了。 下面是经过我简化后的示例代码:
[清单一]
package com.ccb.framework.enums;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class CachingEnumResolver {
//单态实例 一切问题皆由此行引起
private static final CachingEnumResolver SINGLE_ENUM_RESOLVER = new CachingEnumResolver();
/*MSGCODE->Category内存索引*/
private static Map CODE_MAP_CACHE;
static {
CODE_MAP_CACHE = new HashMap();
//为了说明问题,我在这里初始化一条数据
CODE_MAP_CACHE.put("0","北京市");
}
//private, for single instance
private CachingEnumResolver() {
//初始化加载数据 引起问题,该方法也要负点责任
initEnums();
}
/** * 初始化所有的枚举类型 */
public static void initEnums() {
// ~~~~~~~~~问题从这里开始暴露 ~~~~~~~~~~~//
if (null == CODE_MAP_CACHE) {
System.out.println("CODE_MAP_CACHE为空,问题在这里开始暴露.");
CODE_MAP_CACHE = new HashMap();
}
CODE_MAP_CACHE.put("1", "北京市");
CODE_MAP_CACHE.put("2", "云南省");
//..... other code...
}
public Map getCache() {
return Collections.unmodifiableMap(CODE_MAP_CACHE);
}
/** * 获取单态实例 * * @re
相关文档:
在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法,一个是关键字外,最主要有什么区别?它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新类。那么为什么会有两种创建对象方式?这主要考虑到软件的可伸缩、可扩展和可重用等软件设计思想。
......
通过Java反射调用方法
这是个测试用的例子,通过反射调用对象的方法。
TestRef.java
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
/**
* Created by IntelliJ IDEA.
* File: TestRef.java
* User: leizhimin
* Date: 2008-1-28 14:48:44 ......
package Demo;
// Java泛型无法向上转型
class Info23<T> {
private T var; // 定义泛型变量
public void setVar(T var) {
this.var = var;
}
public T getVar() {
return this.var;
}
public String toString() { // 直接打印
return this.var.toString();
}
}
public class GenericsDem ......
下面是20个非常有用的Java程序片段,希望能对你有用。
1. 字符串有整型的相互转换
1
2
String a = String.valueOf(2); //integer to numeric string
3
int i = Integer.parseInt(a); //numeric string to an int
2. 向文件末尾添加内容
01
......