Class对象
来源:互联网 发布:中国网络被攻击2017 编辑:程序博客网 时间:2024/04/29 19:58
Java程序运行时类型信息RTTI可以使我们在程序运行时发现和使用使用类型信息。
Class对象
Class对象是一个特殊的对象,每个类都有一个且仅有一个Class对象。Class对象就是用来创建类的所有“常规”实例对象的,Java通过Class对象来执行其RTTI。
对于每个新类,首先JVM编译生成.class文件,当我们使用一个类的实例时,JVM首先检查这个类是否已经加载到内存中。如果没有加载到内存中,首先就是类加载器动态的加载到JVM内存中。一旦某个类的Class对象被加载到了内存中,它就被用来创建这个类的所有对象。
从上面可知,某一个类的实例对象和Class对象不是一个东西。我们是首先必须生成Class对象才能生成实例对象。那么生成Class对象的方式有哪些呢?有如下三种:
1、Class.forName(“类的全限定名”);(这里必须是包名+类名)
2、类名.class
3、实例对象.getClass();
关于类的加载机制可以参考JVM部分的博客:http://blog.csdn.net/u010853261/article/details/53981375
从上面的blog可知,类的加载过程可以分为:预加载、连接、初始化。经过这三部之后该类就可以创建实例并使用了。而在初始化阶段才真正的类中定义的Java程序代码(或则说字节码),比如给static变量赋予用户指定的值以及执行静态代码块也是在这一步执行。
下面有个测试代码,分析这三种获取Class对象的区别:
package test;/** * Created by louyuting on 17/1/14. */class First{ private static int staticA = 1; private int B=20; public First() { System.out.println("First类的构造函数"); } static { System.out.println("staticA="+staticA); staticA=2; System.out.println("静态域的Loading First"); System.out.println("静态域的Loading First"+B); } { System.out.println("staticA="+staticA); System.out.println("B=" + B); System.out.println("非静态域参数初始化"); }}class Second{ static { System.out.println("Loading Second"); }}class Third{ static { System.out.println("Loading Third"); }}public class ClassTest { @org.junit.Test public void test1() throws ClassNotFoundException { Class first1 = First.class;//没有加载类 System.out.println("first1:" + first1); } @org.junit.Test public void test2() throws ClassNotFoundException { Class first2 = Class.forName("test.First");//加载类到JVM System.out.println("first2:" + first2); } @org.junit.Test public void test3() throws ClassNotFoundException { Class first3 = new First().getClass();//加载类到JVM内存并把非静态域参数初始化. System.out.println("first3:" + first3); }}
上面有三个测试函数test1()、test2()和test3()。这三个测试函数实际就是三种获取Class对象的方式。下面看看三种运行结果:
1)test1的运行结果:
first1:class test.First
从test1()的运行结果可知,First.class这种方式获取class对象的时候,在JVM中加载类的时候并没有执行初始化动作,所以静态域和静态代码块都没有被执行。
2)test2()的运行结果如下:
//output:staticA=1静态域的Loading Firstfirst2:class test.First
运行结果可知,Class.forName(“”);这种方式获取class对象的时候,在JVM中加载类的时候执行了初始化动作,所以静态域和静态代码块都被执行了,从输出的结果就可知。但是类的非静态域就没有被执行,我在写测试代码时,准备在static静态块中输出B值,发现直接报错,“说没有B这个静态域变量可以引用”,说明非静态域参数这时没有被初始化。
3)test3()的运行结果如下:
//output:staticA=1静态域的Loading FirststaticA=2B=20非静态域参数初始化First类的构造函数first3:class test.First
test3()这种方式是获取Class对象方式是直接先new一个First实例对象,从上文的理论可知,首先肯定实现加载First类的Class对象到JVM中并成功初始化了才能够使用该类的实例对象。所以首先就是在加载Class对象那个时就执行了静态域,之后在new实例对象时执行了非静态域的参数实例化。之后执行构造器。
上面测试代码的github地址
对上面的内容做一个总结:
上面主要是介绍了三种获取某一个类的Class对象的方法。但是一般情况下推荐使用“.class”这种方式,因为这样做不仅简单而且更加安全,因为它在编译时就会收到检查。但是以这种方式需要注意的一点是:使用“.class”来创建对Class对象的引用时不会自动的初始化该Class对象,初始化操作被延迟到了对静态方法(构造器是隐式的静态方法)或则静态域首次进行引用时才执行。而其余的方式都是马上就进行了初始化。
- Class对象
- Class对象
- Class 对象
- class对象
- Class对象
- Class对象
- Class对象
- Class对象
- Class对象
- Class对象
- Class对象
- Class对象
- Class对象
- Class对象
- [Java] Class对象
- 产生inner class对象
- Class对象测试
- class 对象对齐
- xgboost 在windows的环境的安装
- 微信分享网页失败的原因
- Hadoop源码解析之RPC协议
- keil4 stm32 开发环境搭建
- python核心编程(十一&十二)— 函数和函数式编程、模块
- Class对象
- HDUoj 5363 Key Set (快速幂,数学,规律
- 剑指offer——数值的整数次方
- Webkit模块介绍
- JSONObject To JavaBean
- 算法提高 计算器
- java虚拟机--垃圾收集算法与垃圾收集器
- 送快递
- c++ 构造函数 继承