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
        }
    }
  • 相关阅读:
    比官方文档更易懂的Vue.js教程!包你学会!
    张腾:腾讯云融合通信应用场景及案例分享
    你大概走了假敏捷:《手绘敏捷宝典》在此,还不来收!
    这个PHP无解深坑,你能解出来吗?(听说能解出来的都很秀)
    从小数学就不及格的我,竟然用极坐标系表白了我的女神!(附代码)
    epoll
    hash_map
    BloomFilter
    Wrapper模式(Decorator模式)
    setvbuf
  • 原文地址:https://www.cnblogs.com/moris5013/p/10557842.html
Copyright © 2011-2022 走看看