`
hyw520110
  • 浏览: 220950 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

反射的污染

    博客分类:
  • java
阅读更多

出自《java puzzle》


这个谜题举例说明了一个关于反射的简单应用。这个程序会打印出什么呢?

Java代码 复制代码
  1. import java.util.*;   
  2. import java.lang.reflect.*;   
  3. public class Reflector {   
  4.   public static void main(String[] args) throws Exception {   
  5.     Set<String> s = new HashSet<String>();   
  6.     s.add("foo");   
  7.     Iterator it = s.iterator();   
  8.     Method m = it.getClass().getMethod("hasNext");   
  9.     System.out.println(m.invoke(it));   
  10.   }   
  11. }  
import java.util.*;
import java.lang.reflect.*;
public class Reflector {
  public static void main(String[] args) throws Exception {
    Set<String> s = new HashSet<String>();
    s.add("foo");
    Iterator it = s.iterator();
    Method m = it.getClass().getMethod("hasNext");
    System.out.println(m.invoke(it));
  }
}



这个程序首先创建了一个只包含单个元素的集合(set),获得了该集合上的迭代器,然后利用反射调用了迭代器的hasNext方法,最后打印出此该方法调用的结果。由于该迭代器尚未返回该集合中那个唯一的元素,hasNext方法应该返回true。然而,运行这个程序却得到了截然不同的结果:
Exception in thread "main" java.lang.IllegalAccessException:
Class Reflector can not access a member of class HashMap$HashIterator with modifiers "public"
at Reflection.ensureMemberAccess(Reflection.java:65)
at Method.invoke(Method.java:578)
at Reflector.main(Reflector.java:11)
这是怎么发生的呢?正如这个异常所显示的,hasNext方法当然是公共的,所以它在任何地方都是可以被访问的。那么为什么这个基于反射的方法调用是非法的呢?这里的问题并不在于该方法的访问级别(access level),而在于该方法所在的类型的访问级别。这个类型所扮演的角色和一个普通方法调用中的限定类型(qualifying type)是相同的[JLS 13.1]。在这个程序中,该方法是从某个类中选择出来的,而这个类型是由从it.getClass方法返回的Class对象表示的。这是迭代器的动态类型(dynamic type),它恰好是私有的嵌套类(nested class) java.util.HashMap.KeyIterator。出现 IllegalAccessException 异常的原因就是这个类不是公共的,它来自另外一个包:访问位于其他包中的非公共类型的成员是不合法的[JLS 6.6.1]。无论是一般的访问还是通过反射的访问,上述的禁律都是有效的。下面这段没有使用反射的程序也违反了这条规则。

Java代码 复制代码
  1. package library;   
  2. public class Api{   
  3.   static class PackagePrivate{}   
  4.   public static PackagePrivate member = new PackagePrivate();   
  5. }   
  6. package client;   
  7. import library.Api;   
  8. class Client{   
  9.   public static void main(String[] args){   
  10.     System.out.println(Api.member.hashCode());   
  11.   }   
  12. }  
package library;
public class Api{
  static class PackagePrivate{}
  public static PackagePrivate member = new PackagePrivate();
}
package client;
import library.Api;
class Client{
  public static void main(String[] args){
    System.out.println(Api.member.hashCode());
  }
}



尝试编译这段程序会得到如下的错误:
Client.java:5: Object.hashCode() isn't defined in a public
class or interface; can't be accessed from outside package
System.out.println(Api.member.hashCode());
^
这个错误与前面那个由含有反射的程序所产生的运行期错误具有相同的意义。Object类型和hashCode方法都是公共的。问题在于hashCode方法是通过一个限定类型调用的,但用户访问不到这个类型。该方法调用的限定类型是library.Api.PackagePrivate,这是一个位于其他包的非公共类型。
这并不意味着Client就不能调用Api.member的hashCode方法。要做到这一点,只需要使用一个可访问的限定类型即可,在这里可以将Api.member转型成Object。经过这样的修改之后,Client类就可以顺利地编译和运行了:
System.out.println(((Object)Api.member).hashCode());
实际上,这个问题并不会在普通的非反射的访问中出现,因为API的编写者在他们的公共API中只会使用公共的类型。即使这个问题有可能发生,它也会以编译期错误的形式显现出来,所以比较容易修改。而使用反射的访问就不同了,object.getClass().getMethod(“methodName”) 这种惯用法虽然很常见,但是却有问题的,它不应该被使用。就像我们在前面的程序中看到的那样,这种用法很容易在运行期产生一个 IllegalAccessException。
在使用反射访问某个类型时,请使用表示某种可访问类型的Class对象。回到我们前面的那个程序,hasNext方法是声明在一个公共类型 java.util.Iterator 中的,所以它的类对象应该被用来进行反射访问。经过这样的修改后,这个Reflector程序就会打印出true:
Method m = Iterator.class.getMethod("hasNext");
你完全可以避免这一类的问题,你应该只有在实例化时才使用反射,而方法调用都通过使用接口进行[EJ Item 35]。这种使用反射的用法,可以将那些调用方法的类与那些实现这些方法的类隔离开,并且提供了更高程度的类型安全。这种用法在“服务提供者框架”(Service Provider Frameworks)中很常见。这种模式并不能解决反射访问中的所有问题,但是如果它可以解决你所遇到的问题,请务必使用它。
总之,访问其他包中的非公共类型的成员是不合法的,即使这个成员同时也被声明为某个公共类型的公共成员也是如此。不论这个成员是否是通过反射被访问的,上述规则都是成立的。这个问题很有可能只在反射访问中才会出现。对于平台的设计者来说,这里的教训与谜题67中的一样,应该让错误症状尽可能清晰地显示出来。对于运行期的异常和编译期的提示都还有些东西需要改进。

分享到:
评论

相关推荐

    河北省唐山市迁安市杨店子镇2015_2016学年八年级物理上学期期中试题含解析新人教版

    - 问题3提到了光污染,这是由过度或不适当的光照导致的问题,如选项C中城市建筑大面积安装玻璃幕墙可能造成光反射污染。 3. 长度单位纳米(nm): - 问题4介绍了纳米是一个极小的长度单位,0.3nm是一个原子半径的...

    有机污染物对真空中高反射率涂层激光诱导损伤阈值的影响

    研究了真空中有机污染物对涂层激光诱导损伤阈值(LIDT)的影响。 通过电子束蒸发法沉积在1064 nm具有高反射率的TiO2 / SiO2介电镜。... 真空中的N-2分子可以减少有机污染物的影响并保护高反射率涂层。

    java cglib和反射demo

    面向切面编程(AOP)是一种编程范式,旨在将关注点分离,比如日志、事务管理等,使其不污染业务逻辑代码。在Java中,AOP通常通过代理实现,即在方法调用前后插入额外的操作。 接下来,我们来看如何用CGLib和反射...

    2019_2020学年八年级物理考点归类训练_镜面反射和漫反射含解析2020041515

    在交通运输领域,镜面反射可能造成白亮污染,影响驾驶安全。光滑的玻璃幕墙和大理石等建筑材料在阳光下会反射强烈的光线,有时甚至能对过往司机造成眩光,影响视觉判断。而漫反射则提供了一种解决办法,例如,通过在...

    大气污染物扩散模式.pptx

    镜像全反射是一种常用的计算方法,可以用于计算污染物的浓度分布和扩散范围。该方法假设污染物浓度在y、z方向上的分布为正态分布,并假设源强是连续均匀稳定的。 大气污染物扩散模式在环境监测和控制中扮演着重要...

    光的反射(提高)巩固练习.doc

    5. 光污染:题目提到的“暗中是人们祈求的,但偶尔也会毁坏人的视觉跟身心健康,成为光污染”,指的是城市中的光污染,如大面积的玻璃幕墙在夜晚反射强烈光线,对环境和生物产生负面影响。 6. 入射角与反射角的关系...

    JAVA的反射机制与动态代理

    动态代理常用于事件监听、事务管理、日志记录等场景,它可以将一些通用逻辑(如事务控制)抽取出来,不污染业务代码。 结合反射和动态代理,开发者可以编写更加灵活和强大的代码。例如,通过反射获取到对象,然后...

    FCR-model.rar_Soil image_光谱反射_光谱反射率_土壤_土壤光谱

    光谱反射是指光线照射到物体表面后被反射回去的比例,是分析土壤性质、植被状态、水体污染等地球表面特征的重要参数。 描述中提到的“光谱反射率模型”是用来计算不同波长下土壤对入射光的反射强度。这种模型可以...

    八年级物理上册第3章光和眼睛第2节探究光的反射规律第2课时光的反射分类应用学案无答案粤教沪版.doc

    (2) 造成光污染,影响居民生活,比如夜间强烈的反射光可能干扰周围居民休息。 通过以上内容的学习,我们可以理解光的反射在我们的日常生活中的重要作用,并能解释和应对一些由反射现象引起的视觉问题。了解并掌握...

    jjx FCO敞开式反射型光栅尺 手册.pdf

    这种方式可以更容易实现较大测量范围,并且在某些情况下具有更好的抗污染能力。 3. 精度问题:光栅尺的测量精度受到多种因素的影响,如光源的稳定性、光栅的刻线质量、电子元件的精度等。通常,精度等级越高,对...

    本溪市大气污染物浓度预测

    此外,地面反射效应也需要被纳入考虑,以确保预测结果的准确性。 最后,研究结果显示,污染主要集中在本溪市的中部地区、特定工业区及其主导风向的下风向地区。居住区只有靠近工业区的部分区域出现了污染物超标现象...

    LED显示屏之“光污染”

    白亮污染指的是建筑物表面反射强烈光线形成的污染;人工白昼是指过度照明造成的自然昼夜节律的干扰;彩光污染则是指由色彩缤纷的人工光源造成的视觉不适。在这些分类中,我国目前仅对建筑物玻璃幕墙造成的白亮污染...

    fiber(5-4).rar_OTDR时域反射_otdr_光时域反射_光时域反射仪_光纤故障

    OTDR(Optical Time-Domain Reflectometer),即光时域反射仪,是一种基于后向散射和菲涅尔反射原理的测试仪器。它通过发射一系列的脉冲激光进入光纤,然后分析返回的光信号来获取光纤的长度、衰减系数、接头损耗、...

    CDMA网络的导频污染问题.pdf

    3. **地形影响**:山区、峡谷等地形会导致信号反射和折射,形成多径效应,从而增加导频污染的可能性。 **后果**: 1. **通话质量下降**:移动台在多个导频信号之间频繁切换,导致通话质量不稳定。 2. **系统容量...

    ASD高光谱遥感环境污染检测研究进展

    大气污染监测中,高光谱遥感技术能够捕捉到污染物在特定波长下的吸收和反射特性,通过对这些数据的分析可以精确地识别出不同类型的污染物及其浓度变化。近年来,随着高光谱遥感技术的发展,科学家们已经能够利用这些...

    大口径反射镜表面颗粒污染物暗场检测算法研究

    针对大口径反射镜表面污染物的成像特点,研究了污染物的暗场检测算法,包括图像采集过程中的自动聚焦算法,图像处理过程中的畸变校正与污染物提取算法等。就自动聚焦算法提出了粗-精结合的峰值搜索策略,并采用Tenengrad...

    面向6G的智能反射面无线通信综述.docx

    只控制反射,耗能少、电磁污染小,符合未来绿色通信要求;可以提高定位精度,增强物理层安全,支持全双工、全频带传输技术;低成本、易实现,便于应用在各种无线网络中,如物联网、车联网等。 IRS 技术与大规模 ...

    ATRFTIR衰减全反射光谱的原理PPT学习教案.pptx

    例如,它可以用于鉴定聚合物的表面改性、生物组织的成分分析、药物的释放研究,甚至是污染物检测等。 总的来说,ATRFTIR是一种高效、便捷的表面分析技术,通过其独特的蒸发波机制,能够在无需复杂样品制备的情况下...

Global site tag (gtag.js) - Google Analytics