Run-time Type Identification(RTTI)运行时类型检察,可以简单的理解成:Lets you find the exact type of an object when you have only a reference to the base type.
To cast some type using the enforce cast, like this:
(AppleTree)aTree
This is the most basic form of RTTI。All casts are checked at run time for correctness. That’s exactly what RTTI means: at run time, the type of an object is identified. RTTI forms including:
1. The classic cast; e.g., “(Shape),” which uses RTTI to make sure the cast is correct. This will throw a ClassCastException if you’ve performed a bad cast.
2. The Class object representing the type of your object. The Class object can be queried for useful run time information.
3. We can use the keywords instanceof to check type correctness before a cast, Class.isinstance(“SomeObj”) also do this.
RTTI Syntax:
First, we must get a reference to the appropriate Class object. One way to do this, is to use a string and the Class.forName( ) method. This is convenient because we don’t need an object of that type in order to get the Class reference. However, if we do already have an object of the type we’re interested in, we can fetch the Class reference by calling a method that’s part of the Object root class: getClass( ). This returns the Class reference representing the actual type of the object. Class has many interesting methods, find out more by looking up the class Class in the JDK documentation.
When we’re using reflection to interact with an object of an unknown type, the JVM will simply look at the object and see that it belongs to a particular class (just like ordinary RTTI), but then, before it can do anything else, the Class object must be loaded. Thus, the .class file for that particular type must still be available to the JVM, either on the local machine or across the network. So the true difference between RTTI and reflection is that with RTTI, the compiler opens and examines the .class file at compile time. Put another way, we can call all the methods of an object in the “normal” way. With reflection, the .class file is unavailable at compile time; it is opened and examined by the run-time environment.
对于以下三类组件中的任何一类来说 -- 构造函数、字段和方法 -- java.lang.Class 提供四种独立的反射调用,以不同的方式来获得信息。调用都遵循一种标准格式。以下是用于查找构造函数的一组反射调用:
Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,
Constructor[] getConstructors() -- 获得类的所有公共构造函数
Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)
Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关)
获得字段信息的Class 反射调用不同于那些用于接入构造函数的调用,在参数类型数组中使用了字段名:
Field getField(String name) -- 获得命名的公共字段
Field[] getFields() -- 获得类的所有公共字段
Field getDeclaredField(String name) -- 获得类声明的命名的字段
Field[] getDeclaredFields() -- 获得类声明的所有字段
用于获得方法信息函数:
Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法
Method[] getMethods() -- 获得类的所有公共方法
Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法
Method[] getDeclaredMethods() -- 获得类声明的所有方法
Java允许我们从多种管道为一个class生成对应的Class object。下图是一份整理。
|
Class object 诞生管道
|
示例
|
|
运用getClass()
注:每个class 都有此函数
|
String str = "abc";
Class c1 = str.getClass();
|
|
运用
Class.getSuperclass()2
|
Button b = new Button();
Class c1 = b.getClass();
Class c2 = c1.getSuperclass();
|
|
运用static method
Class.forName()
(最常被使用)
|
Class c1 = Class.forName ("java.lang.String");
Class c2 = Class.forName ("java.awt.Button");
Class c3 = Class.forName ("java.util.LinkedList$Entry");
Class c4 = Class.forName ("I");
Class c5 = Class.forName ("[I");
|
|
运用
.class 语法
|
Class c1 = String.class;
Class c2 = java.awt.Button.class;
Class c3 = Main.InnerClass.class;
Class c4 = int.class;
Class c5 = int[].class;
|
|
运用
primitive wrapper classes
的TYPE 语法
|
Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Character.TYPE;
Class c4 = Short.TYPE;
Class c5 = Integer.TYPE;
Class c6 = Long.TYPE;
Class c7 = Float.TYPE;
Class c8 = Double.TYPE;
Class c9 = Void.TYPE;
|
图2:Java 允许多种管道生成Class object。
Java classes 各成份所对应的Reflection APIs
Java class成份,分别对应于下图的Reflection API,其中出现的Package、Method、Constructor、Field等等classes,都定义于java.lang.reflect。
|
Java class 内部模块(参见图3)
|
Java class 内部模块说明
|
相应之Reflection API,多半为Class methods。
|
返回值类型(return type)
|
|
(1) package
|
class隶属哪个package
|
getPackage()
|
Package
|
|
(2) import
|
class导入哪些classes
|
无直接对应之API。
解决办法见图5-2。
|
|
|
(3) modifier
|
class(或methods, fields)的属性
|
int getModifiers()
Modifier.toString(int)
Modifier.isInterface(int)
|
int
String
bool
|
|
(4) class name or interface name
|
class/interface
|
名称getName()
|
String
|
|
(5) type parameters
|
参数化类型的名称
|
getTypeParameters()
|
TypeVariable <Class>[]
|
|
(6) base class
|
base class(只可能一个)
|
getSuperClass()
|
Class
|
|
(7) implemented interfaces
|
实现有哪些interfaces
|
getInterfaces()
|
Class[]
|
|
(8) inner classes
|
内部classes
|
getDeclaredClasses()
|
Class[]
|
|
(8') outer class
|
如果我们观察的class 本身是inner classes,那么相对它就会有个outer class。
|
getDeclaringClass()
|
Class
|
|
(9) constructors
|
构造函数getDeclaredConstructors()
|
不论 public 或private 或其它access level,皆可获得。另有功能近似之取得函数。
|
Constructor[]
|
|
(10) methods
|
操作函数getDeclaredMethods()
|
不论 public 或private 或其它access level,皆可获得。另有功能近似之取得函数。
|
Method[]
|
|
(11) fields
|
字段(成员变量)
|
getDeclaredFields()不论 public 或private 或其它access level,皆可获得。另有功能近似之取得函数。
|
Field[]
|
发表于 @ 2007年09月21日 23:30:00|评论(loading...)|编辑