1.为什么需要RTTI:RTTI:在运行时识别一个对象的类型,其对应的类就是Class对象。RTTI维护类型的信息,为多态的实现提供基础。
public static void main(String[] args) { Person person = new Person(); System.out.println(person.getClass().getName()); Person man = new Man(); System.out.println(man.getClass().getName()); } } class Person { public void say() { System.out.println("person"); } } class Man extends Person { @Override public void say() { System.out.println("man"); } }
通过getClass的getName方法,得到这个变量具体指向哪个类new出来的对象。
2.Class对象:java有两种对象:实例对象和Class对象。每个类的运行时的类型信息就是用Class对象表示的,它包含了与类有关的信息。每个类都有对应的Class类的对象引用,可以用过getClass()获取。Class类只有私有构造函数,对应的Class对象只能有JVM创建和加载。
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { //三种方式 //1、对象.getClass() Iphone iphone = new Iphone(); Class clz = iphone.getClass(); //2、类.class() clz = Iphone.class; //3、Class.forName(包名.类名) clz = Class.forName("SixtyThree.Iphone"); //创建对象 Iphone iphone2 = (Iphone) clz.getConstructor().newInstance(); System.out.println(iphone2); } } class Iphone { public Iphone() { } }
3.类字面常量:Java还提供了另一种方法来生成对Class对象的引用,即使用类字面常量。简单有安全,在编译是就会受到检查,不需要放在try语句块中。
加载:由类加载器执行,查找字节码,创建一个Class对象。链接:验证字节码,为静态域分配空间。初始化:如果该类有超类,则对其初始化,执行静态初始化器和静态初始化块。
class Number { static final int i = 123; static int i1 = 12; static { System.out.println("number"); } } class Number2 { static int i = 1; static { System.out.println("number2"); } } public class Test1 { public static void main(String[] args) throws ClassNotFoundException { Class num = Number.class; System.out.println(Number.i); System.out.println(Number.i1); Class num2 = Class.forName("SixtyFour.Number2"); System.out.println(Number2.i); } }
使用.class语法来获得对类的引用不会引发初始化,为了产生Class引用,Class.forName()立即就进行了初始化。