RTT、Class 对象与反射

2016-03-07 15:22:38   最后更新: 2016-03-07 15:46:11   访问数量:742




RTTI 即 Run-Time Type Identification,运行时类型检查,这个机制让你的程序中某个数据的类型信息直到运行时才被发现和使用

java 提供了两大类 RTTI 机制,一种是“传统的”RTTI,他要求我们在编译时已知所有类型,另一种是反射机制,他允许我们在运行时才发现和使用类型信息

 

最基本的 RTTI 机制就是多态的实现,比如派生类与基类之间的转型和动态绑定

那么,RTTI 是如何工作的呢?

RTTI 是利用 Class 对象实现的,Class 对象就是用来创建所有常规对象的,他拥有对应类的大量相关信息,每当编译器加载一个类,就会产生一个 Class 对象,类加载器首先检查这个类的 Class 是否已经被加载,如果没有被加载,类加载器就会根据类名找到对应的 .class 文件,从而创建对应的 Class 对象

 

Class 对象也提供了很多方法供外部使用,如:

static Class<?> forName(String className) throws ClassNotFoundException

 

这个静态方法通过传入的类名字符串加载了对应的类,可以让你在某个类还没有被加载的时候提前加载这个类,类对应的 static 块就会被执行,static 成员会被创建和初始化,如果参数中指定的类名不存在,那么就会抛出 ClassNotFoundException 异常

 

下面的例子展示了 Class 对象的几个常用的用法:

package cn.techlog.tesh; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * Created by techlog on 2016/2/28. */ interface HasBatteries { } interface Waterproof { } interface Shoots { } class Toy { Toy() { } Toy(int i) { } } class FancyToy extends Toy implements HasBatteries, Waterproof, Shoots { FancyToy() { super(1); } } public class Test { static void printInfo(Class cc) { System.out.println("Class name: " + cc.getName() + "is interface? [" + cc.isInterface() + "]"); System.out.println("Simple name: " + cc.getSimpleName()); System.out.println("Canonical name: " + cc.getCanonicalName()); } public static void main(String[] argv) { Class c = null; try { c = Class.forName("cn.techlog.test.FancyToy"); } catch (ClassNotFoundException e) { System.out.println("cannot find FancyToy"); System.exit(-1); } printInfo(c); for (Class face : c.getInterfaces()) { printInfo(face); } Class up = c.getSuperclass(); Object obj = null; try { obj = up.newInstance(); } catch (InstantiationException e) { System.out.println("Cannot instance"); } catch (IllegalAccessException e) { System.out.println("Cannot access"); } printInfo(obj != null ? obj.getClass() : null); } }

 

 

这段代码展示了 Class 对象的几个用法,其中需要注意的是,forName 的参数必须是完整的类路径,需要包含包名,否则将无法找到对应的类

getName 方法获取了完整的类名(包含包名),getSimpleName 方法获取了类名,getInterfaces 方法获取了类实现的所有接口的 Class 对象,getSuperclass 则获取了父类的 Class 对象,newInstance 方法则通过 Class 对象创建了一个类对象,但是他只能通过无参构造器创建对象,否则就会抛出异常

 

除了使用并不安全的 forName 方法外,类名.class 也可以生成 Class 对象,如使用 Test.class,基本类型也支持这样方式的调用,如 int.class

 

简单地说,java 的反射机制就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法

上面所说的 Class 类可以实现这个功能,java.lang.reflect 类库也提供了一些功能

reflect 类库包含了 Field、Method 和 Constructor 类,这些类都是由 jvm 在运行时创建的,用以表示某各类里对应的成员

使用这个类库可以通过 Constructor 创建新的对象,用 get、set 方法读取和修改与 Field 对象关联的字段,用 invoke 方法调用与 Method 对象关联的方法

还可以通过 getFields、getMethods、getConstructors 等方法获取字段、方法、构造器的对象的数组

 






读书笔记      技术帖      龙潭书斋      java      object      thinking in java      java编程思想      class对象      rtti      类型     


京ICP备15018585号