出自《java puzzle》
本谜题中的程序所建模的系统,将尝试着从其环境中读取一个用户ID,如果这种尝试失败了,则缺省地认为它是一个来宾用户。该程序的作者将面对有一个静态域的初始化表达式可能会抛出异常的情况。因为Java不允许静态初始化操作抛出被检查异常,所以初始化必须包装在try-finally语句块中。那么,下面的程序会打印出什么呢?
public class UnwelcomeGuest {
public static final long GUEST_USER_ID = -1;
private static final long USER_ID;
static {
try {
USER_ID = getUserIdFromEnvironment();
} catch (IdUnavailableException e) {
USER_ID = GUEST_USER_ID;
System.out.println("Logging in as guest");
}
}
private static long getUserIdFromEnvironment()
throws IdUnavailableException {
throw new IdUnavailableException();
}
public static void main(String[] args) {
System.out.println("User ID: " + USER_ID);
}
}
class IdUnavailableException extends Exception {
}
该程序看起来很直观。对getUserIdFromEnvironment的调用将抛出一个异常,从而使程序将GUEST_USER_ID(-1L)赋值给USER_ID,并打印Loggin in as guest。然后main方法执行,使程序打印User ID: -1。表象再次欺骗了我们,该程序并不能编译。如果你尝试着去编译它,你将看到和下面内容类似的一条错误信息:
UnwelcomeGuest.java:10:
variable USER_ID might already have been assigned
USER_ID = GUEST_USER_ID;
^
问题出在哪里了?USER_ID域是一个空final(blank final),它是一个在声明中没有进行初始化操作的final域[JLS 4.12.4]。很明显,只有在对USER_ID赋值失败时,才会在try语句块中抛出异常,因此,在catch语句块中赋值是相当安全的。不管怎样执行静态初始化操作语句块,只会对USER_ID赋值一次,这正是空final所要求的。为什么编译器不知道这些呢?
要确定一个程序是否可以不止一次地对一个空final进行赋值是一个很困难的问题。事实上,这是不可能的。这等价于经典的停机问题,它通常被认为是不可能解决的[Turing 36]。为了能够编写出一个编译器,语言规范在这一点上采用了保守的方式。在程序中,一个空final域只有在它是明确未赋过值的地方才可以被赋值。规范长篇大论,对此术语提供了一个准确的但保守的定义[JLS 16]。因为它是保守的,所以编译器必须拒绝某些可以证明是安全的程序。这个谜题就展示了这样的一个程序。
幸运的是,你不必为了编写Java程序而去学习那些骇人的用于明确赋值的细节。通常明确赋值规则不会有任何妨碍。如果碰巧你编写了一个真的可能会对一个空final赋值超过一次的程序,编译器会帮你指出的。只有在极少的情况下,就像本谜题一样,你才会编写出一个安全的程序,但是它并不满足规范的形式化要求。编译器的抱怨就好像是你编写了一个不安全的程序一样,而且你必须修改你的程序以满足它。
解决这类问题的最好方式就是将这个烦人的域从空final类型改变为普通的final类型,用一个静态域的初始化操作替换掉静态的初始化语句块。实现这一点的最佳方式是重构静态语句块中的代码为一个助手方法:
public class UnwelcomeGuest {
public static final long GUEST_USER_ID = -1;
private static final long USER_ID = getUserIdOrGuest;
private static long getUserIdOrGuest {
try {
return getUserIdFromEnvironment();
} catch (IdUnavailableException e) {
System.out.println("Logging in as guest");
return GUEST_USER_ID;
}
}
...// The rest of the program is unchanged
}
程序的这个版本很显然是正确的,而且比最初的版本根据可读性,因为它为了域值的计算而增加了一个描述性的名字,而最初的版本只有一个匿名的静态初始化操作语句块。将这样的修改作用于程序,它就可以如我们的期望来运行了。
总之,大多数程序员都不需要学习明确赋值规则的细节。该规则的作为通常都是正确的。如果你必须重构一个程序,以消除由明确赋值规则所引发的错误,那么你应该考虑添加一个新方法。这样做除了可以解决明确赋值问题,还可以使程序的可读性提高。
分享到:
相关推荐
尽管会员忠诚度计划广受欢迎,但实际与酒店品牌建立起长期关系的活跃会员并不多。当前,会员忠诚度计划的核心正在从单纯的积分奖励转向更深层次的宾客互动和个性化体验。 随着2020年新冠疫情对旅游业造成的巨大冲击...
- **特殊天气应对**:雨雪天气下,为宾客提供雨伞服务,确保客人不受恶劣天气影响。 - **礼貌告别**:无论宾客选择何种出行方式离开,都要礼貌地告别,并表示欢迎下次光临。 #### 二、前厅服务流程及注意事项 **...
品酒会是一种独特的社交活动,主要特点是客人需自带饮料,尤其在年轻人群体中颇受欢迎。这种形式不仅降低了举办酒会的经济压力,也让聚会更频繁,增强了参与者间的互动与共享精神。在品酒会上,每个人都承担一部分...
如何撰写一篇既得体又具有吸引力的欢迎词是一门艺术,它需要考虑到场合、听众和主题的契合,避免过于平淡或过于正式,以确保宾客感到受到重视和欢迎。 【导游欢迎词的特点】 对于导游来说,出团欢迎词不仅需要表达...
2. **主持人暖场**:主持人正式登场,向宾客介绍自己和婚礼主题,欢迎宾客的到来。 3. **新人登场**:新郎先出场,接着新娘在伴娘的陪伴下入场,新郎向新娘献花。 4. **新人走T台**:新人携手走过T台,象征着共同...
规范、系统的服务礼仪培训不仅能够塑造服务人员的专业形象,还能培养出受客户欢迎的服务技巧,增强企业的竞争力。 服务人员学习和应用服务礼仪,不仅是提升个人职业形象的必要条件,也是企业提高效率、增强市场竞争...
【婚礼来宾致贺词】是婚礼仪式中一个重要的环节,它是对新人的祝福与期许的表达,也是向宾客展示敬意的一种方式。...在准备婚礼课件时,这个环节应当受到足够的重视,以确保婚礼仪式的顺利进行和宾客的满意体验。
确认宾客身份时可借助胸卡或自我介绍,同时展示欢迎横幅或接站牌。热情握手、简单寒暄并提供必要的帮助,如安排住宿,都是展现良好迎宾礼仪的关键。如果由于特殊原因不能亲自接待,应有礼貌地向宾客解释。 其次,**...
证婚人通常由新人信任且受尊重的人担任,他们在婚礼上正式宣布新人的婚姻合法有效,并向新人及宾客传达祝福。 1. **证婚人的角色**: - 证婚人是婚礼仪式中的关键人物,他们在法律上有权证明新人的婚姻关系,确保...
在正餐后的酒会,虽然不是必须提供食物,但如有提供会更受欢迎。然而,考虑到大多数客人可能刚用过餐,食物不宜过早出现。理想的酒会食物应该是易于食用且能刺激食欲的,比如各种果仁、鸡尾酒软饼、泡菜、长面包、...
上班时间不应扎堆闲聊、使用手机做私事,更不能对宾客不尊重,如不理问、大声喧哗或表现出不雅行为。违反这些规则将被扣2-5分。对待顾客应始终保持礼貌,不得有与客人赌气、争吵、讲脏话等行为,否则将面临更严厉的...
因此,主人应以热情的态度款待每一位客人,让他们感受到被重视和欢迎。 其次,宴请的环境至关重要。一个宽敞舒适、空气流通、光线适宜的用餐空间,可以让客人放松心情,更好地享受聚会的乐趣。如果场地狭窄、闷热,...
开场白中,司仪自我介绍并表示荣幸能主持这场婚礼,同时也代表新人及家人向宾客表达感激和欢迎之情。 2. **新人爱情故事**: 在新人入场前,司仪讲述新人的爱情故事,增加婚礼的情感深度,让宾客更深入了解这对...
1. **开场白**:主持人的开场通常是对宾客的欢迎和自我介绍,比如“各位来宾、各位亲朋好友、女士们先生们”,以及对新人的简单介绍,如“非常荣幸受到我们尊敬的余总的委托,在这里主持 xx 小姐和 xx 先生的婚礼”...
- **电子请柬**:随着科技的发展,电子请柬越来越受欢迎,可以通过电子邮件、微信、QQ等方式发送,环保且快捷。 - **传统纸质请柬**:如果选择纸质请柬,要确保纸张质量好,印刷清晰,还可以添加一些装饰,如丝带...
3. **家庭的期望**:父母在祝酒词中对孩子的期望不仅仅是身体健康和学业进步,还希望他们能成为有知识、有能力、受人喜爱的人。这反映了中国家庭教育的核心价值观,即培养孩子的品德、学识和社交能力。 4. **感恩之...
根据给定的信息,本文将详细解析“酒桌上的礼仪”这一主题,并从不同的角度深入探讨在酒桌上应遵循的行为准则。 ### 酒桌上的基本礼仪 ...掌握了这些基本要点后,相信每个人都能成为受欢迎的社交达人!
这需要掌握好分量,做到分配均匀,不能因为某道菜受欢迎而偏袒某些客人。 6. **一勺准原则**:每次派菜时,叉匙中的食物应只属于一位客人,不能将一勺菜分给两位客人,更不能从宾客的盘中取出食物,这是对客人尊重...
12. 演讲技巧:最受欢迎的方式是“借助讲稿但不完全依赖”,既能准备充分,又能灵活应对。 13. 西方手势:拇指朝下表示否定,拇指与食指形成环状则表示“好”或“同意”。 14. 握手的含义:右手相握,左手搭肩表示...
传统上,金戒和铜戒是常见的选择,但现在,钻石戒指越来越受欢迎。新人可以选择在戒指上刻上名字或特别日期,使其成为独一无二的纪念品。 【订婚宴】是仪式结束后的重要环节,通常由女方家庭主办,以款待宾客。现代...