在java中,有两种RTTI的方式,一种是传统的,即假设在编译时已经知道了所有的类型;还有一种,是利用反射机制,在运行时再尝试确定类型信息。
一、RTTI
Java中的每一个类都对应着一个Class对象(java.lang.Class)。通过这个Class对象你可以在运行时得到很多类中的有用的信息。用Class.forName来得到一个Class对象。
传统的RTTI有3种实现方式:
1、向上转型或向下转型(upcasting and downcasting),在java中,向下转型(父类转成子类)需要强制类型转换
2、Class对象(用了Class对象,不代表就是反射,如果只是用Class对象cast成指定的类,那就还是传统的RTTI)
3、instanceof或isInstance()
- try {
- Class c = Class.forName("MyClass");
- String name = c.getName(); // "MyPackge.MyClass"
- name = c.getSimpleName(); // "MyClass"
- name = c.getCanonicalName(); // "MyPackge.MyClass"
- Class superClass = c.getSuper();
- if (superClass != null) // Object's super class is null
- superClass.newInstance();
- boolean b = c.isInterface();
- for(java.lang.Class face: c.getInterfaces())
- name = face.getName();
- } catch (ClassNotFoundException) {}
- 二、反射机制
- Java还有一套反射机制。RTTI能够维护的类型都是编译时已知的类型,而反射可以使用一些在编译时完全不可知的类型。比如在进行一个远程调用时,类信息是通过网络传输过来的,编译器在编译时并不知道这个类的存在。Java的反射与RTTI的区别就在于编译时不需要知道任何事情,匿名对象的信息在运行时确定下来就可以。
- 举例:
-
- class SomeClass {
- public SomeClass() {}
- public int SomeMethod(double d, char c) { return 2; }
- public int a;
- }
-
- public class ReflectTest {
- public static void main(String[] args) {
- Class c = Class.forName("SomeClass");
- for (Constructor<?> constructor: c.getConstructors())
- System.out.println(constructor);
- for (Method method: c.getMethods())
- System.out.println(method);
- for (Field field: c.getFields())
- System.out.println(field);
-
- SomeClass sc = new SomeClass();
- Method method = c.getMethod("SomeMethod", double.class, char.class);
- Integer returnedValue = (Integer)method.invoke(sc, 3, '4');
- Field field = c.getField("a");
- int value = field.getInt(sc);
- System.out.println(value);
- }
- }
- class SomeClass {