一、引言
很多时候我们的程序可能需要在运行时识别对象和类的信息,比如多态就是基于运行时环境进行动态判断实际引用的对象。在运行时识别对象和类的信息主要有两种方式:1.RTTI,具体是Class对象,它假定我们在编译时已经知道了所有类型。2.反射机制,运行我们在运行时发现和使用类的信息。
二、RTTI
RTTI(Run-Time Type Infomation),运行时类型信息。可以在运行时识别一个对象的类型。类型信息在运行时通过Class对象表示,Class对象包含与类有关的信息,可以使用Class对象来创建类的实例。
每个类对应一个Class对象,这个Class对象放在.class文件中,当我们的程序中首次主动使用某类型时,会把该类型所对应的Class对象加载进内存,在这篇文章JVM之类加载器中阐述了哪些情况符合首次主动使用。
既然RTTI和Class对象有莫大的关系,即有了Class对象,就可以进行很多操作,那么,我们如何获取到Class对象呢?有三种方法1. Class.forName("全限定名");(其中,全限定名为包名+类名)。2. 类字面常量,如String.class,对应String类的Class对象。3.通过getClass()方法获取Class对象,如String str = "abc";str.getClass();。
通过一个类对应的Class对象后,我们可以做什么?我们可以获取该类的父类、接口、创建该类的对象、该类的构造器、字段、方法等等。总之,威力相当大。
下面我们通过一个例子来熟悉Class对象的各种用法。
package com.hust.grid.leesf.algorithms; import java.lang.reflect.Constructor; import java.lang.reflect.Method; interface SuperInterfaceA { }; interface SuperInterfaceB { }; class SuperC { private String name; public SuperC() { } public SuperC(String name) { this.name = name; } @Override public String toString() { return name; } } class Sub extends SuperC implements SuperInterfaceA, SuperInterfaceB { private String name; public Sub() { super(); } public Sub(String name) { super(name); this.name = name; } public String getName() { return name; } } public class Main { public static Sub makeInstance(Class<?> clazz) { Sub sub = null; try { sub = (Sub) clazz.newInstance(); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } return sub; } public static void printBasicInfo(Class<?> clazz) { System.out.println("CanonicalName : " + clazz.getCanonicalName()); System.out.println("Name : " + clazz.getName()); System.out.println("Simple Name : " + clazz.getSimpleName()); System.out.println("SuperClass Name : " + clazz.getSuperclass().getName()); Class<?>[] interfaces = clazz.getInterfaces(); for (Class<?> inter : interfaces) { System.out.println("Interface SimpleName : " + inter.getSimpleName()); } Constructor<?>[] constructors = clazz.getConstructors(); for (Constructor<?> cons : constructors) { System.out.println("Constructor Name : " + cons.getName() + " And Parameter Count : " + cons.getParameterCount()); } Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { System.out.println("Method Name : " + method.getName()); } } public static void main(String[] args) { //Sub sub = new Sub(); //Class<?> clazz = sub.getClass(); Class<?> clazz = Sub.class; Sub instance = makeInstance(clazz); if (instance != null) { System.out.println("make instance successful"); } else { System.out.println("make instance unsuccessful"); } printBasicInfo(clazz); } }