- 浏览: 67219 次
- 性别:
- 来自: 北京
最近访客 更多访客>>
最新评论
-
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 1069出自《java puzzle》 你能否举出这样一个合法的J ... -
诵读困难者的一神论
2009-05-08 15:17 1079出自《java puzzle》 从前有一个人,他认为世上只 ... -
烧焦到无法识别
2009-05-06 00:01 1013出自《java puzzle》 下面 ... -
异常为循环而抛
2009-04-22 15:33 1026出自《java puzzle》 下面的程序循环遍历了一个i ... -
不情愿的构造器
2009-04-13 23:38 1012出自《java puzzle》 尽管 ... -
不受欢迎的宾客
2009-04-10 13:16 824出自《java puzzle》 本谜题中的程序所建模的系统, ... -
极端不可思议
2009-04-09 13:38 852出自《java puzzle》 本 ... -
同一性的危机
2009-04-08 13:46 730出自《java puzzle》 下面的程序是不完整的,它缺 ... -
你的隐私正在被公开
2009-04-07 22:34 716出自《java puzzle》 私 ... -
终极危难
2009-04-03 11:48 749出自《java puzzle》 本谜题旨在检验当你试图隐藏一 ... -
进口税
2009-04-02 11:08 770出自《java puzzle》 在5.0 ... -
一揽子交易
2009-04-01 10:25 996出自《java puzzle》 下面这个程序设计在不同的包 ... -
灰色的阴影
2009-03-24 11:33 982出自《java puzzle》 下面 ... -
对字符串上瘾
2009-03-23 10:38 780出自 《java puzzle》 一个名字可以被用来引用位于 ... -
一件私事
2009-03-21 13:24 674出自 《java puzzle》 在下面的程序中,子类的一 ... -
一种疑似排序的惊人传奇
2009-03-19 10:43 679出自《java puzzle》 下 ... -
名字游戏
2009-03-18 15:35 907出自《java puzzle》 下面 ... -
一行的方法
2009-03-14 16:27 865出自《java puzzle》 现 ... -
差是几个
2009-03-12 13:21 722出自《java puzzle》 下面的程序在计算一个int数 ... -
产生它的散列码
2009-03-11 09:35 728出自 《java puzzle》 本 ...
相关推荐
- 问题3提到了光污染,这是由过度或不适当的光照导致的问题,如选项C中城市建筑大面积安装玻璃幕墙可能造成光反射污染。 3. 长度单位纳米(nm): - 问题4介绍了纳米是一个极小的长度单位,0.3nm是一个原子半径的...
在题目中,白亮污染是由镜面反射引起的现象,如玻璃幕墙和磨光大理石等光滑表面在阳光下反射强烈光线,影响交通安全和居民的生活。皮鞋擦过鞋油变亮是因为鞋油填补了皮革表面的凹凸,增加了表面的光滑度,从而增强了...
研究了真空中有机污染物对涂层激光诱导损伤阈值(LIDT)的影响。 通过电子束蒸发法沉积在1064 nm具有高反射率的TiO2 / SiO2介电镜。... 真空中的N-2分子可以减少有机污染物的影响并保护高反射率涂层。
面向切面编程(AOP)是一种编程范式,旨在将关注点分离,比如日志、事务管理等,使其不污染业务逻辑代码。在Java中,AOP通常通过代理实现,即在方法调用前后插入额外的操作。 接下来,我们来看如何用CGLib和反射...
镜像全反射是一种常用的计算方法,可以用于计算污染物的浓度分布和扩散范围。该方法假设污染物浓度在y、z方向上的分布为正态分布,并假设源强是连续均匀稳定的。 大气污染物扩散模式在环境监测和控制中扮演着重要...
5. 光污染:题目提到的“暗中是人们祈求的,但偶尔也会毁坏人的视觉跟身心健康,成为光污染”,指的是城市中的光污染,如大面积的玻璃幕墙在夜晚反射强烈光线,对环境和生物产生负面影响。 6. 入射角与反射角的关系...
动态代理常用于事件监听、事务管理、日志记录等场景,它可以将一些通用逻辑(如事务控制)抽取出来,不污染业务代码。 结合反射和动态代理,开发者可以编写更加灵活和强大的代码。例如,通过反射获取到对象,然后...
光谱反射是指光线照射到物体表面后被反射回去的比例,是分析土壤性质、植被状态、水体污染等地球表面特征的重要参数。 描述中提到的“光谱反射率模型”是用来计算不同波长下土壤对入射光的反射强度。这种模型可以...
(2) 造成光污染,影响居民生活,比如夜间强烈的反射光可能干扰周围居民休息。 通过以上内容的学习,我们可以理解光的反射在我们的日常生活中的重要作用,并能解释和应对一些由反射现象引起的视觉问题。了解并掌握...
这种方式可以更容易实现较大测量范围,并且在某些情况下具有更好的抗污染能力。 3. 精度问题:光栅尺的测量精度受到多种因素的影响,如光源的稳定性、光栅的刻线质量、电子元件的精度等。通常,精度等级越高,对...
通过这个教案的学习,学生可以掌握光的反射现象、反射定律、光路的可逆性、镜面反射和漫反射的区别,以及光反射在实际中的应用和可能带来的光污染问题。这些知识对于理解和解决日常生活中的光学问题至关重要。
此外,地面反射效应也需要被纳入考虑,以确保预测结果的准确性。 最后,研究结果显示,污染主要集中在本溪市的中部地区、特定工业区及其主导风向的下风向地区。居住区只有靠近工业区的部分区域出现了污染物超标现象...
白亮污染指的是建筑物表面反射强烈光线形成的污染;人工白昼是指过度照明造成的自然昼夜节律的干扰;彩光污染则是指由色彩缤纷的人工光源造成的视觉不适。在这些分类中,我国目前仅对建筑物玻璃幕墙造成的白亮污染...
通过本节学习,学生可以掌握光的反射现象、反射定律、光路的可逆性、漫反射和镜面反射的基本概念,以及光反射在实际生活和科技中的应用及可能产生的光污染问题。这有助于提升他们对光学现象的理解和应用能力。
OTDR(Optical Time-Domain Reflectometer),即光时域反射仪,是一种基于后向散射和菲涅尔反射原理的测试仪器。它通过发射一系列的脉冲激光进入光纤,然后分析返回的光信号来获取光纤的长度、衰减系数、接头损耗、...
3. **地形影响**:山区、峡谷等地形会导致信号反射和折射,形成多径效应,从而增加导频污染的可能性。 **后果**: 1. **通话质量下降**:移动台在多个导频信号之间频繁切换,导致通话质量不稳定。 2. **系统容量...
大气污染监测中,高光谱遥感技术能够捕捉到污染物在特定波长下的吸收和反射特性,通过对这些数据的分析可以精确地识别出不同类型的污染物及其浓度变化。近年来,随着高光谱遥感技术的发展,科学家们已经能够利用这些...
针对大口径反射镜表面污染物的成像特点,研究了污染物的暗场检测算法,包括图像采集过程中的自动聚焦算法,图像处理过程中的畸变校正与污染物提取算法等。就自动聚焦算法提出了粗-精结合的峰值搜索策略,并采用Tenengrad...