zoukankan      html  css  js  c++  java
  • Class对象

    static静态代码块,一般用于初始化。或者加载比较大的,耗时的,比方说静态资源,节省运行时调用初始化时间。

    Class对象仅在需要的时候才被加载,static初始化是在类加载时进行的

    一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象,Class.forName("")同new Object(),只会在运行需要时被加载,加载在内存,除非被回收,否则不会重复加载。

    下面的例子说明,使用new对象的方式和Class.forName()加载类的方式,都只会加载一次,一旦存在,不会重复加载。

    package org.mj.typeinfo;
    /** 
     * @author: jing.ming 
     * @version 创建时间:2015年10月31日 下午8:29:40 
     * 类说明 
     */
    class Candy{
        static{
            System.out.println("Loading Candy!");
        }
    }
    
    public class LoadClass {
    
        public static void main(String[] args) {
            new Candy();    
            new Candy();
            try {
                Class.forName("org.mj.typeinfo.Candy");
            } catch (ClassNotFoundException e) {
                System.out.println("Could't find Candy!");
            }
    
        }
    
    }

    运行console结果输出:

    Loading Candy!

    可见重复生成实例,只会加载一次类,就是在第一次加载。

    =============萌萌哒分隔线=================================

    但是,有趣的一点是,当使用类字面常量方式生成对Class对象的引用时,即使用“.class”来创建对Class对象的引用时,不会自动地初始化该Class对象。

    我们都知道,java中为了使用类而做的准备工作实际上包括三个步骤:

    1.加载,这是由类加载器执行的。该步骤将查找字节码(通常在classpath所指定的路径中查找,但这并不是必须的。),并从这些字节码中创建一个Class对象。

    2.链接。该阶段验证类中的字节码,为静态域分配存储空间,并且如果必须的话,将解析这个类创建的对其他类的所有引用。

    3.初始化。如果该类具有超类,则对其初始化,执行静态初始化器和静态初始化块。

    初始化被延迟到了对静态方法(构造器隐式地是静态的)或者非常数静态域进行首次引用时才执行;

    package org.mj.typeinfo;
    
    import java.util.Random;
    
    /** 
     * @author: jing.ming 
     * @version 创建时间:2015年10月31日 下午9:17:44 
     * 类说明 
     */
    class Initable{
        static final int staticFinal = 47 ;
        static final int staticFinal2 = 
                ClassInitialization.rand.nextInt(1000);
        static {
            System.out.println("Initializing Initable") ;
        }
    }
    class Initable2{
        static int staticNonFinal = 147;
        static{
            System.out.println("Initializing Initable2") ;
        }
    }
    class Initable3{
        static int staticNonFinal = 74;
        static{
            System.out.println("Initializing Initable3") ;
        }
    }
    public class ClassInitialization {
        public static Random rand = new Random(47) ;
        public static void main(String[] args) throws ClassNotFoundException {
            Class initable  = Initable.class ;
            System.out.println("After creating Initable ref");
            //Does not trigger initialization
            System.out.println(Initable.staticFinal);
            //Does trigger initialization
            System.out.println(Initable.staticFinal2);
            //Does trigger initialization
            System.out.println(Initable2.staticNonFinal);
            Class initable3 = Class.forName("org.mj.typeinfo.Initable3");
            System.out.println("After creating Initable3 ref") ;
            System.out.println(Initable3.staticNonFinal) ;
        }
    
    }

    console输出:

    After creating Initable ref
    47
    Initializing Initable
    258
    Initializing Initable2
    147
    Initializing Initable3
    After creating Initable3 ref
    74

    从上面的输出可以看到:

    java初始化有效的实现了惰性,从对initable引用的创建中可以看到,仅使用.class语法来获得对类的引用不会引发初始化。但是,为了产生Class引用,Class.forname()立即就进行了初始化,就像在initable3引用的创建中所看到的。

    如果一个static final值是“编译期常量”,就像Initable.staticFinal那样,那么这个值不需要对Initable类进行初始化就可以被读取。但是,如果只是将一个域设置成static和final的,还不足以确保这种行为,例如,对Initable.staticFinal2的访问将强制进行类的初始化,因为它不是一个编译期常量。

    如果一个static域不是final的,那么在对它访问时,总是要求在它被读取之前,要先进行链接(为这个域分配存储空间)和初始化(初始化该存储空间),就像在Initable2.staticNonFinal的访问中看到的那样。

  • 相关阅读:
    【C/C++】【类和对象】计算类所占的字节数
    【算法】【单调栈】单调栈
    【算法】【字符串】C语言常用库函数实现
    【算法】【字符串】Leetcode哈希表相关高频面试题
    ubuntu20.04安装测试uhttpd
    华为Mate14上安装Ubuntu20.04纪要
    shell判断参数值是否在数组内的方法
    降低PDF质量
    Ubuntu 16.04上安装Global阅读源代码工具
    Linux下好用的屏幕录像软件kazam及截图软件shutter
  • 原文地址:https://www.cnblogs.com/jsStudyjj/p/4923962.html
Copyright © 2011-2022 走看看