获取Class对象引用的两种方法
2013-06-02 12:16
323 查看
今天重新翻阅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"方式,第三步会延迟,延迟到对静态方法或者非常数静态域进行首次引用时才执行,请看下面的代码:
运行结果如下:
从结果中可以看到,仅仅使用.class语法来获得对类的引用不会引起初始化。但是Class.forName()会立即进行初始化。
还有一点:如果一个static final值是“编译期常量”,就像Initable.staticFinal那样,则这个值不需要对Initable类进行初始化就可以被读取。记住一定要是编译期常量才行。
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类进行初始化就可以被读取。记住一定要是编译期常量才行。
相关文章推荐
- 获取Class对象引用的两种方法
- Javascript下获取对象引用的两种方法之getElementsByTagName
- 关于Java的泛型在所声明的对象中如何获取class或者实例的方法的总结
- Jvm 标记对象是否被引用的两种方法
- Java反射机制(获取Class对象的三种方式+获取Class中的构造函数进行对象的初始化+获取反射类的字段+获取反射类的一般方法)
- Java中获取Class对象的三种方法
- Java 获取Class对象的三种方法
- (104)反射:获取Class的对象、构造函数、字段、方法。反射实例练习
- Java反射机制——获取Class对象,属性和方法(三)
- 2018/01/07JAVA 基础 / 接口与继承:用引用调用对象方法的两种情况讨论
- 四种获取Class对象的方法 Java反射机制
- 【Class】(1)一共有两种对象,Class对象,实体类对象。(2)Class对象可以得到实体类的所有方法属性
- Class对象获取方法
- Java反射02 : Class对象获取的三种方式和通过反射实例化对象的两种方式
- JavaScript,类与对象,获取html元素的两种方法
- 关于Java的泛型在所声明的对象中如何获取class或者实例的方法的总结
- Servlet中获取application对象的两种方法
- 【ThinkingInJava】27、关于class对象引用的各种关于class的方法
- 反射机制_介绍_Class对象获取_动态操作_构造器_方法_属性JAVA211-212
- 用原生dom的方法获取class对象(很简单实用)