- 浏览: 65303 次
- 性别:
- 来自: 北京
最近访客 更多访客>>
最新评论
-
sunwang810812:
这两个方法都对,只不过我个人觉得,泛型方法的主要目的是为了 p ...
java泛型方法的使用 -
a596620989:
第二个方法是不能通过编译的,会报T can't be reso ...
java泛型方法的使用 -
Javakeith:
...
java泛型 -
bannamoon:
两个方法当然有区别了。当你需要应用泛型规则的时候。第二个方法就 ...
java泛型方法的使用 -
luoping0425:
Learning English!
PEACE—宁静
出自《java puzzle》
这个谜题举例说明了一个关于反射的简单应用。这个程序会打印出什么呢?
这个程序首先创建了一个只包含单个元素的集合(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]。无论是一般的访问还是通过反射的访问,上述的禁律都是有效的。下面这段没有使用反射的程序也违反了这条规则。
尝试编译这段程序会得到如下的错误:
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中的一样,应该让错误症状尽可能清晰地显示出来。对于运行期的异常和编译期的提示都还有些东西需要改进。
这个谜题举例说明了一个关于反射的简单应用。这个程序会打印出什么呢?
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]。无论是一般的访问还是通过反射的访问,上述的禁律都是有效的。下面这段没有使用反射的程序也违反了这条规则。
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中的一样,应该让错误症状尽可能清晰地显示出来。对于运行期的异常和编译期的提示都还有些东西需要改进。
评论
2 楼
liu78778
2009-05-06
这个不能称为反射的污染, 应该是反射乱用的隐患
1 楼
liu78778
2009-05-06
加上这一句看看, 放在Method对象invoke之前
可以强制使得java反射机制忽略访问权限控制
m.setAccessible(true);
可以强制使得java反射机制忽略访问权限控制
发表评论
-
有毒的括号垃圾
2009-05-16 17:01 1038出自《java puzzle》 你能否举出这样一个合法的J ... -
诵读困难者的一神论
2009-05-08 15:17 1053出自《java puzzle》 从前有一个人,他认为世上只 ... -
烧焦到无法识别
2009-05-06 00:01 978出自《java puzzle》 下面 ... -
异常为循环而抛
2009-04-22 15:33 990出自《java puzzle》 下面的程序循环遍历了一个i ... -
不情愿的构造器
2009-04-13 23:38 982出自《java puzzle》 尽管 ... -
不受欢迎的宾客
2009-04-10 13:16 790出自《java puzzle》 本谜题中的程序所建模的系统, ... -
极端不可思议
2009-04-09 13:38 818出自《java puzzle》 本 ... -
同一性的危机
2009-04-08 13:46 690出自《java puzzle》 下面的程序是不完整的,它缺 ... -
你的隐私正在被公开
2009-04-07 22:34 679出自《java puzzle》 私 ... -
终极危难
2009-04-03 11:48 716出自《java puzzle》 本谜题旨在检验当你试图隐藏一 ... -
进口税
2009-04-02 11:08 736出自《java puzzle》 在5.0 ... -
一揽子交易
2009-04-01 10:25 964出自《java puzzle》 下面这个程序设计在不同的包 ... -
灰色的阴影
2009-03-24 11:33 946出自《java puzzle》 下面 ... -
对字符串上瘾
2009-03-23 10:38 734出自 《java puzzle》 一个名字可以被用来引用位于 ... -
一件私事
2009-03-21 13:24 634出自 《java puzzle》 在下面的程序中,子类的一 ... -
一种疑似排序的惊人传奇
2009-03-19 10:43 644出自《java puzzle》 下 ... -
名字游戏
2009-03-18 15:35 873出自《java puzzle》 下面 ... -
一行的方法
2009-03-14 16:27 831出自《java puzzle》 现 ... -
差是几个
2009-03-12 13:21 688出自《java puzzle》 下面的程序在计算一个int数 ... -
产生它的散列码
2009-03-11 09:35 693出自 《java puzzle》 本 ...
相关推荐
研究了真空中有机污染物对涂层激光诱导损伤阈值(LIDT)的影响。 通过电子束蒸发法沉积在1064 nm具有高反射率的TiO2 / SiO2介电镜。... 真空中的N-2分子可以减少有机污染物的影响并保护高反射率涂层。
针对大口径反射镜表面污染物的成像特点,研究了污染物的暗场检测算法,包括图像采集过程中的自动聚焦算法,图像处理过程中的畸变校正与污染物提取算法等。就自动聚焦算法提出了粗-精结合的峰值搜索策略,并采用Tenengrad...
针对路面污染物影响热反射沥青路面降温性能的问题,采用自制温度测试箱,选取尘土作为不透光污染物的代表,甘油、机油作为透光污染物的代表进行研究.试验结果表明:不透光污染物对热反射沥青路面降温性能的影响随...
黄铁矿氧化的原位衰减全反射红外光谱表征,张平,陈永亨,黄铁矿是自然界普遍存在的一种矿物,容易发生氧化反应,是酸性矿山废水(AMD)的主要来源,研究黄铁矿氧化有助于揭示其产生污染的机�
微波测量方法是将电磁波作为探测束入射到等离子体中,对等离子体特性进行探测,不会对等离子体造成污染。常规微波反射计也是通过测量电磁波在等离子体截止频率时的反射信号相位来计算等离子密度。当等离子密度较高...
极紫外光刻系统中的碳污染会降低多层膜反射率,在保证光学元件性能的前提下,如何选择碳清洗工艺是一项重要课题。通过对不同清洗工艺的原理分析,揭示了不同工艺对多层膜反射率的影响主要体现在膜层氧化、刻蚀及表面...
根据影像数据及提取物的特点,采用谱间关系法与阈值法综合的方法进行水体提取,依据清洁水体视反射率信息,对比分析水中悬浮泥沙、水华等信息,完成水质分类处理.研究结果表明:通过该实验方法和技术手段,利用TM/ETM+影像...
微波测量方法是将电磁波作为探测束入射到等离子体中,对等离子体特性进行探测,不会对等离子体造成污染。常规微波反射计也是通过测量电磁波在等离子体截止频率时的反射信号相位来计算等离子密度。当等离子密度较高...
利用光腔衰荡光谱法对氧碘化学激光器(COIL)经气流污染及清洁后的高反射镜反射率进行了一系列的测量研究。测量结果显示,气流中的某些物质会对腔镜造成污染而使其反射率下降,采用不同的清洁方式对反射率的提高程度有很...
然而,在极紫外光辐照下的光学元件,薄膜表层的碳化和氧化是导致EUV反射膜反射率下降的两种主要机制。结合EUV光学器件的表面分子动力学理论,研究碳沉积层的作用机理,以便找到抑制污染沉积的有效方法。通过针对碳...
近红外反射光谱法测定路德维希氏菌率Roxb中的铜和锌污染物
提出并实现了一种基于大偏置量熔接的单端反射式光纤...与已报道的同类型器件相比,所提传感器具有折射率灵敏度高、结构紧凑、可单端测量以及稳定性好等优点,在生物化学传感和环境污染监控等领域中具有良好的应用前景。
针对硝酸银容量法、硫氰酸汞分光光度法和离子色谱法监测气态污染源中氯化氢的局限,提出多次反射池傅里叶变换红外(FTIR)光谱法检测氯化氢气体浓度。该方法是在准确测量氯化氢气体红外吸收光谱的基础上,使用非线性...
对多层介质膜光栅以及介质膜反射镜的激光损伤阈值进行了系统的研究。测试方法采用国际测试标准。测试结果表明,介质光栅的损伤阈值远低于未刻蚀的多层介质膜。对样品损伤形貌的扫描电镜照片分析发现,相比于未刻蚀的...
针对河流中污染源定位问题,首先分析了河流污染源扩散模型,给出了一种处理完全吸收边界,不完全反射边界以及完全反射边界的通用河流污染源稳态扩散模型。改进了在边界约束下以测量值与理论值之差的平方和为目标的非...
从顺直铅垂岸大宽度深水水库水面点源等强度排放...结果表明水库铅垂岸地形污染混合区范围与等标污染负荷、流速、边界反射系数以及岸边混合扩散特性等因素有关,其结果可作为铅垂岸水库排污口污染混合区允许范围的计算依
采用位移调节器实现差分大气消光系数测量,具有抗环境污染能力强和测量灵敏度可调等独特优点,有效提高系统的适应性和可靠性。对设计的系统进行精度估算,证明了方法的可行性,为能见度测量提 供了新方法。
极紫外(EUV)反射镜在使用过程中的氧化及表面碳污染沉积,严重影响了极紫外光刻(EUVL)技术的工业应用。为了延长EUV 反射镜的稳定性与使用寿命,一般采取在Mo/Si多层膜表面添加保护层。采用直流反应磁控溅射技术,...
同时避开了MODIS反演算法中计算大气顶光谱反射率理论的缺陷;利用近红外光谱数据降低了近岸二类水体离水辐射的影响,并通过光谱匹配技术实现了近海污染大气气溶胶光学性质的反演。利用气溶胶自动观测网 (AERONET) 的...
利用自行设计的实验装置,研究了同步辐射光活化氧对光学元件表面碳污染的清洗作用。清洗前样品的碳层厚度为10.3 nm,同步辐射光被引入实验用真空室内,真空室内干燥氧气的压强维持在1.0 Pa,研究显示同步辐射活化氧能...