zoukankan      html  css  js  c++  java
  • 类加载,类初始化及对象实例化

    类的加载分为三个阶段,加载--->链接--->初始化

    类加载的过程

    将class表示的二进制文件加载到内存,放在方法区中,并在堆中创建一个java.lang.Class对象(封装的是class的数据结构)

    类的主动使用,会加载类

     1 new Test()

     2 对类中的静态变量进行读写,对接口中的静态变量进行读取

     3 反射某个类 , Class.forName()

     4 调用静态方法

     5 初始化子类时,父类将被初始化

     6 启动类  ,采用java命令执行某个类

     类的被动使用,不会加载类

    1 子类引用父类的静态变量 ,父类会被初始化,子类不会被初始化

    public class Parent {
        public static int a = 123;
    
        static {
            System.out.println("Parent init");
        }
    }
    
    public class Child extends Parent {
    
        static {
            System.out.println("Child init");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            // 这里是访问的父类的静态变量
            System.out.println(Child.a);
        }
    }

    只初始化了父类

    2 通过引用类型定义数组,不会触发此类的初始化

    3  final修饰的常量,不会触发此类的初始化,因为在编译期间就放入了常量池

    4  final修饰的复杂类型,会触发此类的初始化,因为在编译期间不能计算得出其值

    4 JVM最先初始化的总是java.lang.Object类

    类初始化要注意的地方

    /**
     * 
        *   在static块里,不能对在它后面的静态变量进行读取的操作,但可以写入
         *   在对它前面定义的静态变量,可以读取和写入  
     */
    public class MyObject {
    
        private static  String  x = "abc"; 
        
        static {
            
            x= "edf";
            b =12;
            //这里会提示错误,can not reference a field before define it 
            //System.out.println(b);
        }
        
        private static int b = 10;
    }
    /**
     * 
        *  在初始化类Foo时候,会执行类的static块。这时候开启两个线程进行new对象,JVM保证了只能有一个线程执行类的初始化
     *
     */
    public class ClinitTest {
    
        
        public static void main(String[] args) {
            new Thread(()-> {new Foo();}).start();
            new Thread(()-> {new Foo();}).start();
        }
        
    }
    
    class Foo{
        
        private static AtomicBoolean init = new AtomicBoolean(true);
        static {
            System.out.println(Thread.currentThread().getName() + " will be inint");
            while (init.get()) {
    
            }
            System.out.println(Thread.currentThread().getName() + "  have done inint");
        }
    }

    对象实例化

    类的初始化和对象实例化有时是同时进行的

    class Price {
    
        static Price P = new Price(2.7);
        static double apple = 20;
        double price;
    
        public Price(double orange) {
            price = apple - orange;
        }
    }
    
    public class PriceTest {
        public static void main(String[] args) {
            //Price.P访问了类的静态变量,会触发类的初始化,即(加载,连接,初始化),当执行构造函数时
            //apple还没有初始化完成,处于连接阶段的准备阶段,其值为默认值0,这时构造函数计算的price为-2.7
            System.out.println(Price.P.price);// 结果为-2.7
        }
    }
    class Price {
        
        
        static Price P = new Price(2.7);
        final static double apple = 20;
        double price;
        
        public Price(double orange) {
            price = apple - orange;
        }
    }
    
    public class PriceTest {
        public static void main(String[] args) {
            //apple在编译阶段就完成赋值了,其值为20,这时构造函数计算的price为17.3
            System.out.println(Price.P.price);// 结果为17.3
        }
    }
    class Price {
        
        static double apple = 20;
        static Price P = new Price(2.7);
        double price;
        
        public Price(double orange) {
            price = apple - orange;
        }
    }
    
    public class PriceTest {
        public static void main(String[] args) {
            //Price.P访问了类的静态变量,会触发类的初始化,即(加载,连接,初始化),当执行构造函数时
            //apple已经完成了初始化,其值为20了,这时构造函数计算的price为17.3
            System.out.println(Price.P.price);// 结果为17.3
        }
    }
  • 相关阅读:
    websocket协议解决消息发送问题 Could not decode a text frame as UTF-8.
    成功解决internal/modules/cjs/loader.js:596 throw err; ^ Error: Cannot find module 'minimatch'
    FastDFS客户端与自定义文件存储系统
    fastdfs 中client.conf 文件
    centos 中 redis 的安装
    redis安装成功后get: command not found
    Shell基础知识(二)
    Shell基础知识(一)
    binary search模板总结
    配置远程jupyter notebook
  • 原文地址:https://www.cnblogs.com/moris5013/p/10557842.html
Copyright © 2011-2022 走看看