• 获取Class对象引用的两种方法


    今天重新翻阅Thanking in java。发现通过类字面常量获得Class对象的引用和Class.forName()方式有些区别。特记录下。

    1.Class.forName(String className):

        这种方式要注意className必须使用全限定名(即包含完整的包名)

    2.类字面常量

       比如:FancyToy.class

       这样做的优点是:1.编译器会对其进行检查,不需要置于try语句块中。所以更简单,更安全。

                              2.根除了对forName()方法的调用,故更高效。

       类字面常量不仅可以应用于普通的类,也可以应用于接口,数组,以及基本数据类型。

       另外对于基本数据类型的包装器,有一个标准的TYPE字段,该字段是一个引用,分别指向对应的基本数据类型的Class对象,即boolean.class等价于Boolean.TYPE,void.class等价于Void.TYPE等等。但是要注意Boolean.TYPE和Boolean.class的区别,是不同的。

    3.一个很重要的区别。

    为了使用类,需要经过三个步骤:

      1. 加载: 这是由类的加载器执行的。该步骤将查找字节码,并从这些字节码中创建一个Class对象。

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

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

    forName()这种方式会完全经过这三步。但是".class"方式,第三步会延迟,延迟到对静态方法或者非常数静态域进行首次引用时才执行,请看下面的代码:

    package bells;
    
    import java.util.Random;
    
    /**
     * @author bells
     * 
     */
    public class TestClassInitialization {
    
    	public static Random rand = new Random(47);
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) throws Exception {
    
    		Class initable = Initable.class;
    		System.out.println("After creating Initable ref");
    		System.out.println(Initable.staticFinal);  //这里Initable的static块不会被初始化,因为staticFinal是编译器常量
    		System.out.println(Initable.staticFinal2);
    
    		System.out.println(Initable2.staticNonFinal);
    
    		Class initable3 = Class.forName("typeinfo.Initable3");
    		System.out.println("After creating Initable3 ref");
    		System.out.println(Initable3.staticNonFinal);
    
    	}
    
    }
    
    class Initable {
    	static final int staticFinal = 47;
    	static final int staticFinal2 = TestClassInitialization.rand.nextInt(1000);
    	static {
    		System.out.println("Initializing Initable");
    	}
    }
    
    class Initable2 {
    	static int staticNonFinal = 147;
    	static {
    		System.out.println("Initaialzing Initable2");
    	}
    }
    
    class Initable3 {
    	static int staticNonFinal = 74;
    	static {
    		System.out.println("Initializing Initable3");
    	}
    }
    

      运行结果如下:

    从结果中可以看到,仅仅使用.class语法来获得对类的引用不会引起初始化。但是Class.forName()会立即进行初始化。

    还有一点:如果一个static final值是“编译期常量”,就像Initable.staticFinal那样,则这个值不需要对Initable类进行初始化就可以被读取。记住一定要是编译期常量才行。

  • 相关阅读:
    H
    并查集
    H
    Supermarket (贪心 并查集)
    H
    M
    N-Find a way
    HDU 4035 Maze
    #386. 【UNR #3】鸽子固定器
    P4688 [Ynoi2016]掉进兔子洞
  • 原文地址:https://www.cnblogs.com/pigzhu/p/3113354.html
Copyright © 2020-2023  润新知