【JAVA笔记——道】Class初始化理解
来源:互联网 发布:labp网络管理协议 编辑:程序博客网 时间:2024/04/29 11:02
静态域、非静态域、Final、父类以及抽象类正常实例化
设置Initalized用于初始化时对于结果进行输出
//被实例化类,设置初始方法用于显示初始化标记public class Initalized { public Initalized(String s) { System.out.println(s); }}
设置接口类用于测试类继承,设置内容如下
interface InitalizeaedInterface { //接口中变量默认都是static final Initalized s1 = new Initalized("Initalizeaed Interface"); //usual method public void test1(); //static method //public void test2(); //final method public void test3(); //static final method //public void test4();}
设置抽象类作为实现类父类
package com.cunchen.practice.init;//设置被实例化类的父类public abstract class InitalizedAbstract { //父类中域中对于被实例化类进行实习化 Initalized a = new Initalized("Initalizeaed Abstract"); Initalized b; static Initalized c; //被实例化类的父类的构造方法 public InitalizedAbstract() { b = new Initalized("Abstract Constractor"); } //父类的非静态方法 public void test5() { b = new Initalized("Abstract method"); } //父类的非静态方法,此方法在子类中被覆盖 public void test6() { b = new Initalized("Abstract covered method"); } //父类静态方法 public static void test7() { c = new Initalized("Abstract static method"); }}
最终实现类如下
//实例化类public class InitalizationTest extends InitalizedAbstract implements InitalizeaedInterface{ //变量域中实例化 Initalized s1 = new Initalized("Usual declared"); //变量域中静态变量实例化 static Initalized s2 = new Initalized("Static declared"); //变量域中常量实例化 final Initalized s5 = new Initalized("Final declared"); //变量域中静态常量实例化 static final Initalized s6 = new Initalized("Static final declared"); Initalized s3; static Initalized s4; //静态方法域中执行静态方法 static { getReply(); } //构造方法 public InitalizationTest() { super(); s3 = new Initalized("Constructor"); } //普通方法 public void test1() { s3 = new Initalized("Method"); } //静态方法 public static void test2() { s4 = new Initalized("Static Method"); } //Final方法 public final void test3() { s4 = new Initalized("Final Method"); } //静态Final方法 public static final void test4() { s4 = new Initalized("Static final Method"); } //重写父类方法 public void test6() { s3 = new Initalized("Test covered method"); } //静态域执行方法 public static void getReply() { s4 = new Initalized("Static block"); } public static void main(String[] args) { //初始化过程 InitalizationTest test = new InitalizationTest(); System.out.println("-------------------------------"); //方法执行过程 test.test1(); //普通方法 test.test2(); //静态方法 test.test3(); //Final方法 test.test4(); //Static Final 方法 test.test5(); //父类方法 test.test6(); //重写方法 System.out.println("-------------------------------"); //空对象访问 test = null; test.test2(); //普通方法 test.test1(); //静态方法 }}
实际运行结果如下
Static declaredStatic final declaredStatic blockInitalizeaed AbstractAbstract ConstractorUsual declaredFinal declaredConstructor-------------------------------MethodStatic MethodFinal MethodStatic final MethodAbstract methodTest covered method-------------------------------Static MethodException in thread "main" java.lang.NullPointerException at com.cunchen.practice.init.InitalizationTest.main(InitalizationTest.java:74)
得出结论如下:
1.类内部初始化顺序为 静态域->非静态域->构造方法
2.类实例化过程中不会对于实现的接口的域进行初始化
3.类实例化过程中会在其构造方法之前对父类初始化
4.无论是静态方法还是非静态方法,在实例化过程中不直接执行
5.子类重写父类方法之后调用重写方法将不会对父类方法调用
6.静态域静态方法会在类加载时就直接进行初始化
7.空对象可以访问静态化区域,但不可以访问非静态化区域,,这个问题还引出对象在JVM存储结构的问题,不同对象在虚拟机中不同的存储策略决定了其不同的实现方式
反射方式
新建RunTest类
public class RunTest { public static void main(String[] args) throws ClassNotFoundException { //反射看class初始化情况 Class.forName("com.cunchen.practice.init.InitalizationTest"); System.out.println("-------------------------------"); InitalizationTest test = new InitalizationTest(); System.out.println("-------------------------------"); test.test1(); test.test6(); System.out.println("-------------------------------"); }}
执行之后得到结果如下
Static declaredStatic final declaredStatic block-------------------------------Initalizeaed AbstractAbstract ConstractorUsual declaredFinal declaredConstructor-------------------------------MethodTest covered method-------------------------------
得出结论:
- 反射仅会目标类静态域进行初始化,而对非静态域不初始化
- 静态域只会在类初次加载初始化,再次加载不进行初始化
- 反射之后,类并未真正实例化,并未调用其构造方法
ClassLoader加载类
修改main方法如下:
public static void main(String[] args) throws ClassNotFoundException { ClassLoader.getSystemClassLoader().loadClass("com.cunchen.practice.init.InitalizationTest"); System.out.println("-------------------------------"); //反射看class初始化情况 Class.forName("com.cunchen.practice.init.InitalizationTest"); System.out.println("-------------------------------"); InitalizationTest test = new InitalizationTest(); System.out.println("-------------------------------"); test.test1(); test.test6(); System.out.println("-------------------------------"); }
结果如下
-------------------------------Static declaredStatic final declaredStatic block-------------------------------Initalizeaed AbstractAbstract ConstractorUsual declaredFinal declaredConstructor-------------------------------MethodTest covered method-------------------------------
得到结论:ClassLoader在进行类加载之后并不对类进行任何初始化操作
深入理解
Class的装载包括3个步骤:加载(loading),连接(link),初始化(initialize)
Class.forName重载了两种实现方法,
public static Class<?> forName(String className) throws ClassNotFoundException public static Class<?> forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException
第二个方法中的initialize方法其实就是指定Class被loading后是不是必须被初始化
实际上第一个方法执行结果等同于Class.forName(className, true, currentLoader)
ClassLoader.loadClass(String name)源码如下
public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
实际执行情况为loadClass(name, false),装载的class将不会被link。
这两个方法都用于装载Class。但如果程序依赖于Class是否被初始化,就必须用Class.forName(name)了。相信到此大家也能明白在JDBC中经常用到的加载JDBC驱动程序是什么原理了把。
深入了解推荐
对象生命周期详解
Java ClassLoader详解
- 【JAVA笔记——道】Class初始化理解
- Java笔记—初始化
- 《深入理解java虚拟机》学习笔记5——Java Class类文件结构
- 《深入理解java虚拟机》学习笔记5——Java Class类文件结构
- 《深入理解java虚拟机》学习笔记5——Java Class类文件结构
- 《深入理解java虚拟机》学习笔记5——Java Class类文件结构
- 《深入理解java虚拟机》学习笔记5——Java Class类文件结构
- 《深入理解java虚拟机》学习笔记5——Java Class类文件结构
- 《深入理解java虚拟机》学习笔记5——Java Class类文件结构
- Java基础笔记——对象初始化
- effective java笔记——延迟初始化
- java学习笔记.09——初始化
- Java笔记——初始化和清除
- JAVA Class中初始化顺序
- java Class与静态初始化
- 深入理解Java虚拟机笔记---class类文件结构概述
- 深入理解Java虚拟机笔记---class类文件结构概述
- 学习《深入理解java虚拟机》笔记-class文件检验器
- Hibernate3一级缓存和二级缓存的理解!
- 日经春秋 20151220
- DragonBoard 410c低速扩展口详解
- MySql常用函数
- Linux命令之rm
- 【JAVA笔记——道】Class初始化理解
- BOOL in Objectice-C
- start kernel 之后没有任何输出与uboot无法将bootargs传入内核的调查方法与解决之道
- 最小生成树Prim算法
- 删除表的外键约束
- DLVA prj
- block的使用
- 字符串中的智慧(一)
- MVC5学习系列——添加视图