Java程序在运行时,Java运行时系统一直对全部的对象进行所谓的运行时类型标识,即所谓的RTTI。这项信息纪录了每一个对象所属的类。虚拟机一般使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动建立。java
Class类的做用是运行时提供或得到某个对象的类型信息,和C++中的typeid()函数相似。这些信息也可用于反射。函数
咱们都知道全部的java类都是继承了object这个类,在object这个类中有一个方法:getclass().这个方法是用来取得该类已经被实例化了的对象的该类的引用,这个引用指向的是Class类的对象。咱们本身没法生成一个Class对象(构造函数为private),而 这个Class类的对象是在当各种被调入时,由 Java 虚拟机自动建立 Class 对象,或经过类装载器中的 defineClass 方法生成。咱们生成的对象都会有个字段记录该对象所属类在CLass类的对象的所在位置。以下图所示:
code
第一种办法,Class类的forName函数对象
public class shapes{} Class obj= Class.forName("shapes");
第二种办法,使用对象的getClass()函数继承
public class shapes{} shapes s1=new shapes(); Class obj=s1.getClass(); Class obj1=s1.getSuperclass();//这个函数做用是获取shapes类的父类的类型
第三种办法,使用类字面常量接口
Class obj=String.class; Class obj1=int.class;
注意,使用这种办法生成Class类对象时,不会使JVM自动加载该类(如String类)。而其余办法会使得JVM初始化该类。get
获取一个Class类的对象后,能够用 newInstance() 函数来生成目标类的一个实例。然而,该函数并不能直接生成目标类的实例,只能生成object类的实例虚拟机
Class obj=Class.forName("shapes"); Object ShapesInstance=obj.newInstance();
Class<shapes> obj=shapes.class; shapes newShape=obj.newInstance();
由于有了类型限制,因此使用泛化Class语法的对象引用不能指向别的类。class
Class obj1=int.class; Class<Integer> obj2=int.class; obj1=double.class; //obj2=double.class; 这一行代码是非法的,obj2不能改指向别的类了
然而,有个灵活的用法,使得你能够用Class的对象指向基类的任何子类。泛型
Class<? extends Number> obj=int.class; obj=Number.class; obj=double.class;
所以,如下语法生成的Class对象能够指向任何类。
Class<?> obj=int.class; obj=double.class; obj=shapes.class;
最后一个奇怪的用法是,当你使用这种泛型语法来构建你手头有的一个Class类的对象的基类对象时,必须采用如下的特殊语法
public class shapes{} class round extends shapes{} Class<round> rclass=round.class; Class<? super round> sclass= rclass.getSuperClass(); //Class<shapes> sclass=rclass.getSuperClass();
咱们明知道,round的基类就是shapes,可是却不能直接声明 Class < shapes >,必须使用特殊语法
Class < ? super round >
这个记住就能够啦。