在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 {