为什么需要RTTI
public class Test {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Father f = new Son();
System.out.println(f.getClass().getName()); //son
f.getClass().getMethod("anotherHello").invoke(f);
}
}
class Father{
public void sayHello() {
System.out.println("hello world,this is father");
}
}
class Son extends Father {
public void sayhello(){
System.out.println("hello world,this is son");
}
public void anotherHello() {
System.out.println("this is another hello");
}
}
- RTTI名称的含义:在运行时,识别一个对象的类型
- 面向对象编程中基本的目的是,让代码只操纵对基类的引用,多态
- 有时需要操作特定类的独有方法,而这是无法从基类获取的,这就是使用RTTI的意义
Class对象
- 类型信息在运行时由Class对象表示,每个类都有一个Class对象,包含与类相关的信息
- 每当编译一个新类,就会由jvm中的类加载器子系统生成一个同名的Class对象(.class)
- 类加载器子系统是一条类加载器链,原生的类加载器加载可信类,包括java api类,也可以额外增加类加载器
- 所有类都是在第一次使用的时候(创建第一个对类的静态成员的引用时),动态加载到jvm中。这说明,构造器也是静态的。
- 一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象
- 想在运行时使用类型信息,就必须先获得对Class对象的引用
package rtti;
interface HasBatteries{};
interface Waterproot{};
interface Shoots{};
class Toy{
public Toy() { }
public Toy(int i) { }
}
class FancyToy extends Toy implements HasBatteries,Waterproot,Shoots {
FancyToy(){ super(1);}
}
public class ToyTest {
static void printInfo(Class cc) {
System.out.println("Class name:"+cc.getName()+"n" //获取全限定类名
+"isInterface:"+cc.isInterface()+"n"
+ "Simple name:"+cc.getSimpleName()+"n" //获取不含包名的类名
+ "Canonocal name:"+cc.getCanonicalName()+"n"////获取全限定类名
);
}
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("rtti.FancyToy");
} catch (ClassNotFoundException e) {
System.out.println("can't find FancyToy");
System.exit(1);
}
System.out.println(c);
for (Class face :
c.getInterfaces()) {//获取接口数组
printInfo(face);
}
Class up = c.getSuperclass();//获取父类Class对象的引用
Object obj = null;
try {
obj = up.newInstance();//通过class对象,创建类的实例
} catch (InstantiationException e) {
System.out.println("can not instantiate");
System.exit(1);
} catch (IllegalAccessException e) {
System.out.println("can not access");
System.exit(1);
}
printInfo(obj.getClass());
}
}
- Class.forName()是获取Class对象引用的一种方法,必须传入全限定类名
- 它有一个副作用,如果类没有加载就加载它
- 另一种方式是getClass()方法,这个方法属于根object的一部分
- newInstance()是实现虚拟构造器的一种途径,虚拟构造器允许声明“我不知道你的确切类型,但无论如何要正确的创建自己”
- 使用newInstance()来创建的类必须要带有默认构造器
类字面常量
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。