当一个类中有声明为static final的变量,这样的变量对类的加载器有一定的影响,首先看看下面的例子。
- package com.bird.classLoad;
- class FinalTest{
- public static final int a = 6/3;
- static{
- System.out.println("FinalTest static block");
- }
- }
- public class Test3 {
- public static void main(String[] args) {
- System.out.println(FinalTest.a);
- }
- }
因为a是static final变量,且它等于6/3,在编译的时候就可以知道它的值,所以直接访问a的值不会引起FinalTest类的初始化。作为表现,也就是static静态代码快不会被加载。
运行结果为
- 2
在看一个例子
- package com.bird.classLoad;
- import java.util.Random;
- class FinalTest4{
- public static final int a = new Random().nextInt(100);
- static{
- System.out.println("FinalTest4 static block");
- }
- }
- public class Test4 {
- public static void main(String[] args) {
- System.out.println(FinalTest4.a);
- }
- }
这个static final变量a因为i在编译的时候无法知道它的确切的值,所以只有等到运行的时候才能知道,所以自己访问FinalTest4.a会引起FinalTest4类的初始化。也就是static静态代码快的加载。
运行结果为
- FinalTest4 static block
- 82
下面的例子是讲,当子类被主动访问的时候,会引起其直接父类的初始化
- package com.bird.classLoad;
- class Parent{
- static int a = 3;
- static{
- System.out.println("Parent static block");
- }
- }
- class Child extends Parent{
- static int b = 4;
- static{
- System.out.println("Chind static block");
- }
- }
- public class Test5 {
- public static void main(String[] args) {
- System.out.println(Child.b);
- }
- }
因为直接访问Child,b,会先初始化Parent类,然后初始化Child类。
运行结果为
- Parent static block
- Chind static block
- 4
如果通过子类直接访问父类的变量,只会初始化父类而不会初始化子类
- package com.bird.classLoad;
- class Parent{
- static int a = 3;
- static{
- System.out.println("Parent static block");
- }
- }
- class Child extends Parent{
- static{
- System.out.println("Chind static block");
- }
- }
- public class Test5 {
- public static void main(String[] args) {
- System.out.println(Child.a);
- }
- }
直接访问Parent类的a变量,则只会直接初始化parent类,不会初始化Child类
运行结果如下
- Parent static block
- 3
相关推荐
- 静态`final`变量:对于静态`final`变量,如果在声明时没有初始化,那么可以在静态初始化块中初始化,确保在类加载时完成赋值。例如: ```java class Test1 { static final double PI; static { PI = 3.14; ...
类加载器分为引导类加载器、扩展类加载器和应用程序类加载器,以及用户自定义的类加载器。 2. **运行时数据区(Runtime Data Area)** JVM内存分为多个区域,包括方法区、堆、虚拟机栈、本地方法栈和程序计数器。 ...
类加载器负责加载类到JVM中。主要有Bootstrap ClassLoader、Extension ClassLoader和App ClassLoader,以及用户自定义的类加载器。类加载器遵循双亲委托模型,确保类的唯一性。 以上是JVM的一些核心概念和工作机制...
Java 类加载机制是Java虚拟机(JVM)的核心组成部分,负责将类的定义从Class文件加载到内存,并对其进行校验、解析和初始化。这个过程确保了程序运行时能够正确使用类的静态和动态特性。本文将深入探讨Java类加载的...
双亲委派模型是JVM默认的类加载方式,通过自定义类加载器可以实现特定的加载逻辑。 三、运行时数据区 JVM内存分为堆、方法区、虚拟机栈、本地方法栈和程序计数器五个区域。其中,堆是所有线程共享的内存区域,用于...
这通常涉及到类路径的设置和类加载器的作用。 接下来,关于Spring框架: 1. Spring框架刷新:"134-框架篇-01-spring_refresh_概述"、"135-框架篇-02-spring_refresh_01_Environment"以及"136-框架篇-03-spring_...
6. **类加载与双亲委派模型**:为了保证类加载的唯一性,JVM采用双亲委派模型,即新类加载请求首先交给父加载器,只有父加载器无法加载时才会尝试当前加载器。 7. **字节码执行**:JVM通过解释器和即时编译器(如...
Java虚拟机(JVM)的类加载过程是Java程序运行的基础,它涉及到类加载器、类的生命周期和一系列复杂的步骤。在这个过程中,类加载器主要任务是根据类的全限定名加载二进制字节流并转化为`java.lang.Class`对象。整个...
主要概念包括主内存、工作内存、 volatile、synchronized和final关键字。volatile能确保变量对所有线程可见,而synchronized则提供了互斥访问,确保同一时刻只有一个线程可以执行特定代码块。 虚拟机原理部分,我们...
1. **JVM架构**:JVM主要由类加载器、运行数据区、执行引擎、本地方法接口和本地库组成。每个部分都有其特定功能,如类加载器负责加载字节码,执行引擎负责解释或编译执行这些字节码。 2. **类加载机制**:JVM遵循...
类加载器按照双亲委托模型工作,确保类加载的一致性和安全性。 3. **运行时数据区**:JVM内存分为堆、栈、方法区、程序计数器、本地方法栈等几个区域。堆存储对象实例,栈保存方法调用,方法区存储类信息,程序...
- JVM的结构包括哪些部分,如类加载器、运行时数据区、执行引擎等。 - 解释JVM的生命周期,以及如何启动和关闭JVM。 2. **类加载机制** - 介绍双亲委派模型,理解类加载器之间的关系。 - 如何自定义类加载器,...
类加载器负责加载类到JVM中。主要有引导类加载器、扩展类加载器和应用程序类加载器,以及用户自定义的类加载器。它们遵循双亲委派模型,即从顶层加载器开始尝试加载类,如果找不到则向下传递。 1.1.5 垃圾回收(GC...
类加载器(ClassLoader)负责查找和加载类,双亲委托模型确保了类加载的安全性。理解这个机制对于理解和解决类冲突问题至关重要。 3. **运行时数据区**:JVM内存模型中,除了堆和栈,还包括方法区、本地方法栈和...
当遇到新的类引用时,JVM会通过类加载器动态地将类加载到内存中。类加载器有系统类加载器、扩展类加载器和应用程序类加载器等,它们遵循双亲委派模型,确保类加载的一致性和安全性。 三、内存管理 JVM内存主要分为...
- **可见性和一致性**:通过volatile、synchronized、final关键字来保证。 通过深入学习和实践这些JVM相关知识,可以更好地理解和解决Java程序中的性能问题,提升系统的稳定性和效率。对于初学者来说,这是一个很...
1. **JVM结构**:JVM主要由类加载器、运行时数据区、执行引擎、本地方法接口和本地库组成。类加载器负责加载类文件,运行时数据区包括堆、栈、方法区、程序计数器和本地方法栈,执行引擎执行字节码,本地方法接口...
12. **Java内存模型**:讲解Java内存模型(JMM)对并发编程的影响,以及volatile、synchronized和final关键字在保证内存可见性方面的作用。 13. **JNI与本地方法**:理解Java Native Interface(JNI)如何允许Java...
类加载器负责将类文件从文件系统或网络中读取并转化为Class对象。加载、验证、准备、解析和初始化是类加载的五个阶段。字节码是Java源代码编译后的中间表示,JVM通过字节码解释器执行。JIT(Just-In-Time)编译器...