浅析类加载

前言:总结一下类加载的过程,于静态代码块、静态变量、事例变量等一些构建方式。因为这部分挺绕的,容易出错。

1、在java中可以将对象分为两大体系:字节码对象和实例对象

1.1、字节码对象:

每个类在加载(将类读到内存)时都会创建一个字节码对象,且这个对象在一个JVM内存中是唯一的.此对象中存储的是类的结构信息.所以可以说字节码对象是获取类结构信息的入口.

每个类对应的类字节码文件在jvm中都是唯一的【验证】

 

1     /**
2      * 测试类的字节码文件是否是唯一的
3      */
4     private static void testClassLoader_01(){
5         Class<?> class_1 = Object.class;
6         Class<?> class_2 = Object.class;
7         System.out.println(class_1 == class_2);
8         // 输出结果:true
9     }

 

 

 

 

 

字节码对象的获取方式?(常用方式有三种)

  • 类名.class:可以使用Class<?> 、Class<类名>来接收
  • Class.forName(“包名.类名”):编译阶段无法确定字符串对应的类名是否准确,只能用Class<?>泛型通配符来接收
  • 类的实例对象.getClass()
 1     /**
 2      * 三种类加载方式
 3      */
 4     private static void testClassLoader_02() throws ClassNotFoundException {
 5         Class<?> class_1 = Object.class;
 6         Class<?> class_2 = Class.forName("java.lang.Object");
 7         Class<?> class_3 = new Object().getClass();
 8         System.out.println((class_1 == class_2)&&(class_2 == class_3));
 9         // 注意:三种类加载方式,加载的是同一个类字节码文件
10     }

 

类加载时:

  静态代码块:可以执行,但不一定会执行。

  静类变量:可以初始化,但不一定会初始化。

 

1 class C_Object{
2     static{
3         System.out.println("进入了静态代码块");
4     }
5 }

 

 

 

  

1     private static void testClassLoader_03() throws ClassNotFoundException {
2         // 这个不会输出 进入了静态代码块
3         Class<?> class_1 = Object.class;
4         // 这个会输出  进入了静态代码块
5         Class<?> class_2 = Class.forName("com.turtle.oop.C_Object");
6     }

 

 

 

  

 对Class.forName()进行剖析:

  

1      // arg1:这个是我们要加载的字节码类   
2         // arg2:这个是确定我们在类加载的时候是否执行静态代码块,默认是true,执行,如果为false就不会执行静态代码块
3         // arg3:使用类加载器来完成类的加载
4         Class<?> c3 = Class.forName("com.turtle.oop.ClassObject",true,Thread.currentThread().getContextClassLoader());

 

 

 

 

总结案例:

 

 1 package com.turtle.oop;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 public class Test_ClassLoader_02 {
 7     public static void main(String [] args) throws ClassNotFoundException {
 8         Class<?> class_01 = Class.forName("com.turtle.oop.C_Object_2",true,Thread.currentThread().getContextClassLoader());
 9         // 出错
10     }
11 }
12 class C_Object_2{
13 /*    为类中的静态变量赋值是按顺序下来的
14     1-加载ClassObject_03类到内存中
15     2-为ClassObject_03类型的变量instance赋值,会调用构造方法
16     3-构造方法中使用了静态变量map,但是此时的静态变量map还没有赋值*/
17     static C_Object_2 instance=new C_Object_2();
18     // 如果和上面的交换位置也就不会出错了、如果改为非静态的就不会出错了
19     static Map<String,String> map = new HashMap<>();
20     public C_Object_2(){
21         map.put("Key_01","Value_01");
22     }
23 }

 

 

 报错:空指针错误

 

D:\Programs\JDK8\bin\java.exe "-javaagent:D:\Programs\JetBrains\IntelliJ IDEA 2018.3.5\lib\idea_rt.jar=55074:D:\Programs\JetBrains\IntelliJ IDEA 2018.3.5\bin" -Dfile.encoding=UTF-8 -classpath D:\Programs\JDK8\jre\lib\charsets.jar;D:\Programs\JDK8\jre\lib\deploy.jar;D:\Programs\JDK8\jre\lib\ext\access-bridge-64.jar;D:\Programs\JDK8\jre\lib\ext\cldrdata.jar;D:\Programs\JDK8\jre\lib\ext\dnsns.jar;D:\Programs\JDK8\jre\lib\ext\jaccess.jar;D:\Programs\JDK8\jre\lib\ext\jfxrt.jar;D:\Programs\JDK8\jre\lib\ext\localedata.jar;D:\Programs\JDK8\jre\lib\ext\nashorn.jar;D:\Programs\JDK8\jre\lib\ext\sunec.jar;D:\Programs\JDK8\jre\lib\ext\sunjce_provider.jar;D:\Programs\JDK8\jre\lib\ext\sunmscapi.jar;D:\Programs\JDK8\jre\lib\ext\sunpkcs11.jar;D:\Programs\JDK8\jre\lib\ext\zipfs.jar;D:\Programs\JDK8\jre\lib\javaws.jar;D:\Programs\JDK8\jre\lib\jce.jar;D:\Programs\JDK8\jre\lib\jfr.jar;D:\Programs\JDK8\jre\lib\jfxswt.jar;D:\Programs\JDK8\jre\lib\jsse.jar;D:\Programs\JDK8\jre\lib\management-agent.jar;D:\Programs\JDK8\jre\lib\plugin.jar;D:\Programs\JDK8\jre\lib\resources.jar;D:\Programs\JDK8\jre\lib\rt.jar;D:\Project\HomeWorks_FrameWork\01-JavaEE-Heighten\javaee\target\classes com.turtle.oop.Test_ClassLoader_02
Exception in thread "main" java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at com.turtle.oop.Test_ClassLoader_02.main(Test_ClassLoader_02.java:8)
Caused by: java.lang.NullPointerException
    at com.turtle.oop.C_Object_2.<init>(Test_ClassLoader_02.java:15)
    at com.turtle.oop.C_Object_2.<clinit>(Test_ClassLoader_02.java:12)
    ... 3 more

Process finished with exit code 1

 

 

 

上一篇:Win10怎么添加开机启动项?Win10添加开机自动运行软件三种方法


下一篇:BTC的交易