已同步更新至我的blog:http://dxjia.cn/2015/08/java-class-object/java
类是面向对象编程语言的一个重要概念,它是对一项事物的抽象归纳,能够包含该事物的一些属性定义,以及操做属性的方法。面向对象编程中,咱们都是以类来编码。编程
简单理解,就是new,就是对类的实例化,建立这个类对应的实际对象,类只是对事物的描述,而实例化就至关于为这个描述新开辟了一块内存,能够改变这块区域里的各类属性(成员变量),固然,也能够实例化多块区域,只是不一样的对象而已。app
注意这里C大写了,与类概念区分开,在java里,Class是一个实实在在的类,在包 java.lang 下,有这样一个Class.java文件,它跟咱们本身定义的类同样,是一个实实在在的类,Class对象就是这个Class类的实例了。在Java里,全部的类的根源都是Object类,而Class也不例外,它是继承自Object的一个特殊的类,它内部能够记录类的成员、接口等信息,也就是在Java里,Class是一个用来表示类的类。(o(∩_∩)o 有点绕啊,抓住关键一点,Class是一个实实在在的类,能够为它建立实例,也就是本文后面提到的Class对象,也看叫作Class实例)。编程语言
java提供了下面几种获取到类的Class对象的方法:测试
1) 利用对象实例调用getClass()方法获取该对象的Class实例;
2) 使用Class类的静态方法forName("包名+类名"),用类的名字获取一个Class实例编码
3)运用 类名.class 的方式来获取Class实例;spa
咱们知道java世界是运行在JVM之上的,咱们编写的类代码,在通过编译器编译以后,会为每一个类生成对应的.class文件,这个就是JVM能够加载执行的字节码。运行时期间,当咱们须要实例化任何一个类时,JVM会首先尝试看看在内存中是否有这个类,若是有,那么会直接建立类实例;若是没有,那么就会根据类名去加载这个类,当加载一个类,或者当加载器(class loader)的defineClass()被JVM调用,便会为这个类产生一个Class对象(一个Class类的实例),用来表达这个类,该类的全部实例都共同拥有着这个Class对象,并且是惟一的。code
在java里,类只是信息描述的,写明了有哪些内部属性及接口,你能够理解为是定义了一套规则;而Class对象在java里被用来对类的状况进行表述的一个实例,也就是是类的实际表征,能够理解为是对规则的图表化,这样JVM才能直观的看懂,能够看作是一个模版;而类的实例化对象,就是经过模版,开辟出的一块内存进行实际的使用。对象
例子:blog
咱们经过一个例子来理解Class实例,为了说明方便,咱们新建一个包名深点的类。
新建Name.java(固然,该文件要放在com\dxjia\sample的目录下)
1 package com.dxjia.sample; 2 3 public class Name { 4 static int count = 0; 5 static { 6 count++; 7 System.out.println("Name Class Loaded! count = [" + count + "]" ); 8 } 9 10 public Name() { 11 System.out.println("Name Constructor called!"); 12 } 13 14 }
再在根目录新建一个Test主类
1 import com.dxjia.sample.Name; 2 3 public class Test { 4 static { 5 Name mName; 6 System.out.println("Test Class loaded"); 7 } 8 9 public static void main(String[] args) { 10 System.out.println("entern Test main()"); 11 12 // Name.class 13 Class mClassPointClass; 14 // Class.forName("完整包名+类名") 15 Class mClassForName; 16 // new 对象后,对象.getClass() 17 Class mClassObjectPointClass1; 18 Class mClassObjectPointClass2; 19 20 try { 21 //测试 类名.class 22 mClassPointClass = Name.class; 23 System.out.println("mClassPointClass = " + mClassPointClass); 24 25 //测试Class.forName() 26 mClassForName = Class.forName("com.dxjia.sample.Name"); 27 System.out.println("mClassForName = " + mClassForName); 28 29 //测试Object.getClass() 30 Name name1 = new Name(); 31 mClassObjectPointClass1 = name1.getClass(); 32 System.out.println("mClassObjectPointClass1 = " + mClassObjectPointClass1); 33 } catch (ClassNotFoundException e) { 34 // TODO Auto-generated catch block 35 e.printStackTrace(); 36 return; 37 } 38 39 Name name2; 40 System.out.println("defined one Name object"); 41 name2 = new Name(); 42 System.out.println("Name object instance done!"); 43 44 mClassObjectPointClass2 = name2.getClass(); 45 46 if (mClassForName == mClassPointClass 47 && mClassPointClass == mClassObjectPointClass1 48 && mClassObjectPointClass1 == mClassObjectPointClass2) { 49 System.out.println("all the Class object equal..."); 50 } 51 } 52 }
分别对他们进行编译:
1 javac com\dxjia\sample\Name.java 2 javac Test.java
执行:
1 java Test
代码中使用了static静态代码块来进行实验,一个类的运行,JVM作会如下几件事情 一、类装载 二、连接 三、初始化 四、实例化;而初始化阶段作的事情是初始化静态变量和执行静态方法等的工做,并且永远只执行一次。
输出结果:
Test Class loaded
entern Test main()
mClassPointClass = class com.dxjia.sample.Name
Name Class Loaded! count = [1]
mClassForName = class com.dxjia.sample.Name
Name Constructor called!
mClassObjectPointClass1 = class com.dxjia.sample.Name
defined one Name object
Name Constructor called!
Name object instance done!
all the Class object equal...
经过结果能够看出在使用 类名.class得到Class实例时,并不会触发类的初始化,而 Class.forName方法就会触发,固然实例化对象确定也是会触发的,但由于static代码块只执行一次,因此不会再有打印,最后的打印,说明一个类的Class实例只有惟一的一个。
扩展:
对于Class.forName("")方法,能够看看下面这篇文章,结合起来理解,会更清晰:理解Class.forName()