为什么语言里要提供「反射」功能

Yang 298

反射可以让开发人员可以通过外部类的全路径名创建对象,并使用这些类,实现一些扩展的功能。反射还可以枚举出类的全部成员,包括构造函数、属性、方法。以帮助开发者写出正确的代码。

一、为什么需要反射

反射(reflection)允许静态语言在运行时(runtime)检查、修改程序的结构与行为。

在静态语言中,使用一个变量时,必须知道它的类型。在Java中,变量的类型信息在编译时都保存到了class文件中,这样在运行时才能保证准确无误;换句话说,程序在运行时的行为都是固定的。如果想在运行时改变,就需要反射这东西了。举个例子:

在Spring中,有这样的java bean配置:

<bean id=”someID” class=”net.liujiacai.Foobar”>

    <property name=”someField” value=”someValue” />

</bean>

spring在处理这个bean标签时,发现class属性指定的是net.liujiacai.Foobar这个类,就会调用Class.forName(String)来实例化这个类,再通过反射,可以取到someField属性的值了。

如果我们想改变这个程序运行时的信息,我们这里直接修改bean,property的属性即可,无需重新编译。

在动态语言中,使用变量不需要声明类型,因而不需要这反射这种机制。 比如在javascript中,我们知道有个变量foobar,不管foobar有没有sayHello()属性,我们都可以这么写:

foobar.sayHello()

因为没有类型检查,这里这么写是允许的。至于在运行时报不报错,就要看运行时foobar的真正值了。

二、反射的作用

反射机制提供了以下几个功能:

在运行时判断任意一个对象所属的类;

在运行时构造任意一个类的对象;

在运行时判断任意一个类所具有的成员变量和方法;

在运行时调用任意一个对象的方法。

反射可以让开发人员可以通过外部类的全路径名创建对象,并使用这些类,实现一些扩展的功能。 反射还可以枚举出类的全部成员,包括构造函数、属性、方法。以帮助开发者写出正确的代码。

延伸阅读

反射是不是破坏了封装性

答案可以说是,也可以说不是。

说是,是因为,通过运用反射机制API,确实可以访问到一个对象的私有成员。

说不是,是因为,并不是所有的反射API,都破坏了封装性。即使因某种必要原因,访问了私有成员,封装的目的还是不变的。比如,在Java种,你想让hello与hi等价。也就是说让”hello”.equals(“hi”) == true,你可以这么做:

Field value = String.class.getDeclaredField(“value”);

value.setAccessible(true);

value.set(“hello”, “hi”.toCharArray());

System.out.println(“hello”.equals(“hi”));

//输出true

其实真正的封装是种理想的状态,不见得是面向对象中的银弹。现实中,有些场合也许破坏封装性是种更明智的选择。

回复

我来回复
  • 暂无回复内容

注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部