在Java的世界里,万事万物皆对象 **(除了静态成员和普通的数据类型(但有包装类)) **;那么我们平常所写的类其实也是对象,它们是java.lang.Class类的对象。
package Test;
public class ClassDemo1 {
public static void main(String []args){
//Foo类的实例对象
Foo foo1 = new Foo();
/*
Foo这个类也是一个实例对象,理论上是Class类的实例对象,但我们
接下来创建的Class类的实例对象实际上是Foo类的类类型,顾名思义,
类类型就是类的类型,也就是描述一个类是什么,都有哪些东西,所
以我们可以通过类类型知道一个类的属性和方法,并且可以调用一个
类的属性和方法,这就是反射的基础。
*/
/*
我们可以通过Fool类创建Class类的对象,也就是Fool类的类类型,
具体有以下三种方式。
*/
//第一种表示方式,这说明任何一个类都有一个隐含的静态成员变量class,
//这种方式是通过获取类的静态成员变量class得到的
Class c1 = Foo.class;
//第二种表示方式,通过该类的对象获得,比如通过Foo类的对象foo1来获得
Class c2 = foo1.getClass();
//第三种表达方式,forName里面的格式是forName("包名.类名")
//这里需要加上异常处理,否则会报错
try {
Class c3 = Class.forName("Test.Foo");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Foo foo = (Foo)c1.newInstance();//需要有无参数的构造方法
foo.print();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Foo{
void print()
{
System.out.println("foo!!!");
}
}
我的 ** 个人理解 ** 是Class类是一个万能的类,他可以制造出许多不同的实例对象,而我们通过上述方法创建的出来的Class类的实例对象(也就是Foo类的类类型),就是Class类可以制造出的不同的实例对象的其中一个。通过Foo类可以创建一个Foo类的类类型(也就是Class类许多实例对象的其中之一),也可以通过其他类,比如animal类,创建一个animal类的类类型(也是Class类许多实例对象之一)。我们可以通过Foo类的类类型来创建Foo类的实例对象,通过c1(c2,c3)创建Foo类的实例对象,* Foo foo= (Foo)c1.newInstance();//需要有无参数的构造方法 *,这里 的c1是Fool类的类类型,创建出来的就是Foo类的实例对象,如果c1是animal类的类类型,创建出来的就是animal类的实例对象。A类的类类型创建出的就是A类的实例对象。
最后,官网上的描述是这样的:c1,c2,c3表示了Foo类的类类型(class type)。
*** 2017/2/18重新修改添加 ***
*** 我们平常所写的类其实也是对象,它们是java.lang.Class类的对象 ***,其实这种说法也不是很准确,Class类是所有类(注意是对象)的共有信息的抽象,比如该类实现的接口、对应的加载器、类名等等。一句话,类类型保存了每个类所对应的类型信息。每一个类都有一个Class对象,这个对象在类被加载后由JVM自动构造。也是由JVM管理的,Class类是没有公共的构造方法的。
Class对象对于类来说就像是,DNA对于每个人,里面有你的一切生物信息。java中可以通过Class来取得类的实例,也许将来的将来通过你的DNA也能得到你的另一个实例。科幻电影里是已经实现了。
这里需要注意的是虚拟机只会产生一份字节码, 用这份字节码可以产生多个实例对象。也就是说Class对象只会有一个。看如下代码:
public class Test {
static {
System.out.println("静态初始化");
}
{
System.out.println("非静态初始化");
}
}
public class client {
public static void main(String[] arg) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
//方法1
Class c=Class.forName("com.zjj.ClassTest.Test");
//方法2
c=Test.class;
//方法3
Test t=new Test();
c=t.getClass();
Test t2=new Test();
}
}
输出结果:
静态初始化
非静态初始化
非静态初始化
静态初始化方法是在类加载的时候执行的,只执行一次,非静态初始化方法是在类被实例化的时候执行的,实例化一次执行一次。而输出结果只打印了一次“静态初始化”,说明只加载了一次,说明只有一个ClassLoader,说明只有一个Class对象,说明三次得到的Class对象都是同一个,有多个引用而已。
也就是说,在运行期间,如果我们要产生某个类的对象或者的得到某个类的Class对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。
** 至此,应该可以理解了Class也是一个类,只不过它是所有类的一个抽象,名字又和我们所知道的Class一样容易造成混淆。总的来说,每一个类都有对应的一个Class对象来保存这个类的信息,这个Class对象由JVM构造和管理。Class对象的存在是Java反射的基础。 **
** 反射机制是Java的一个重要的内容,为Java提供了运行时加载类的能力,也就是动态性。Class是信息提供者,Class Loader是加载工具,二者都是反射机制最基础的部分。那么所谓的反射就是解除耦合,方式就是通过Class取得未知类的信息,而后实例化。当然Class Loader的所做的工作是隐藏的,是Class对象去调用的。所以无需显式的自己调用。 **