嗨,大家好,
就像我在上一期通讯中所承诺的那样,我一直非常忙于为您创建东西。 难道不是个让你闲逛六周的好借口吗? 😉除了一堆链接外,我还有两个故事要讲-一个关于例外,一个关于征服宇宙。
我将这个通讯寄给每个星期五。 或其他日子。 有时不会持续数周。 但是作为实际的电子邮件。 因此, 订阅 !
您是否曾经在IDE的调试器中寻找异常的根本原因,并在扩展每个异常的cause
同时开始盘旋运行,因为在某个时候异常将自身称为其原因? 那是怎么回事?!
病征
事实证明,我们不是第一个对此感到好奇的人。 实际上,对于至少包含两个异常的圈子,它甚至在JDK内引起了问题:在这种情况下,有一个Bug, Throwable::printStackTrace
会进入无限循环。 还建议在Throwable.initCause(Throwable)
检测这种情况,这个错误甚至更老了,该错误已经防止了throwable指向自身的原因。
等待,什么是initCause
? 而且,如果它阻止了“自我成因”,那么为什么有那么多异常引用自己作为其原因。 就像NullPointerException
一样。 和IllegalStateException
。 甚至是StackOverflowError
(具有讽刺意味的)。 实际上,我找不到任何不执行此操作的核心异常。
初始化原因
好吧,也许这是常态? 默认情况下,异常应该是由自身引起的吗? 不,又错了。 这是Throwable
cause
字段上的Javadoc所说的:
导致引发该throwable的throwable;如果此throwable不是由另一个throwable引起的,或者因果的throwable未知,则为null。 如果此字段等于此throwable本身,则表明此throwable的原因尚未初始化。
在这一点上,我有些困惑。 这是我重构时的逻辑流程:
-
Throwable
初始化,cause
指向自身标记为“尚未初始化” - 如果构造函数因原因被调用,它将覆盖默认值
- 但是,如果调用构造函数是没有原因的,则该字段不会设置为
null
–稍后有人需要通过调用initCause
(使用null
或其他方式)对其进行初始化。
第三步是美中不足。 我没有发现调用initCause
核心异常! Throwable
合同强烈建议,非this
原因应该成为规范,并且有一种设置它的方法,但是Java的中央异常类型在很大程度上未使用它。 WTF,为什么?
看一下其来源可得出以下提示:
公共同步Throwable initCause(Throwable原因){
如果(this.cause!= this)
抛出新的IllegalStateException(“ ...”);
如果(原因==这个)
抛出新的IllegalArgumentException(
“不允许自因”,此);
this.cause =原因;
返回这个
}
这不是立即显而易见的,但是您只能调用initCause
一次(没有得到异常),并且我认为这就是我找不到的重要异常实际调用它的原因。 事实证明,一些文档暗示了这一点–这是RuntimeException
构造函数的Javadoc,它不接受任何原因:
原因尚未初始化,并且随后可以通过调用
initCause
进行初始化。
似乎没有确定原因是让我们稍后确定原因的一种让步。 但是在什么情况下? 当我们发现未创建的异常时,但是原因从何而来呢? 🤔如果这是一项功能,我不明白…
根本原因
对于许多异常无法初始化原因的原因,我已经走到了尽头。 但是为什么它首先如此复杂? 在搜寻JDK的过程中,我至少找到了该问题的答案。 这是Throwable
内部的上下文注释:
为了使
Throwable
对象成为不可变的并由JVM安全地重用,例如OutOfMemoryErrors
,可响应用户操作而写入的Throwable
字段,cause
,stackTrace
和stackTrace
遵循以下协议:
- 这些字段被初始化为一个非
null
前哨值,该值指示逻辑上尚未设置该值。 - 向该字段写入
null
表示禁止进一步写入。 - 标记值可以替换为另一个非
null
值。
例如,HotSpot JVM的实现已预先分配了
OutOfMemoryError
对象,以提供对该情况的更好的可诊断性。 创建这些对象时无需调用该类的构造函数,并且所涉及的字段将初始化为null
。 为了支持此功能,添加到Throwable
任何新字段都需要初始化为非null
值,需要协调的JVM更改。
啊哈
这是过去两周我一直在忙的事情:
- 📽️揭开有效Java系列的序幕,第三版
- Static️静态工厂方法-有效的Java,项目1
- For迁移到Java 11所需了解的一切
- Java️Java 11:新曙光—发行版,Oracle JDK与OpenJDK和LTS
- Use️使用构建器…谨慎—有效的Java,项目2
- 11 Java 11 HTTP / 2 API教程
- 📽️首次接触Java 12中的开关表达式
- Java Java 11中的响应式HTTP / 2请求和响应
- 📽️Maven 3/4/5与罗伯特·舒尔特

蒸汽中的恒星
探索充满奇迹的广阔星系! 悖论发展工作室,十字军国王和欧罗巴环球影业的制造商…
store.steampowered.com
一,赞美
Stellaris是一款经典的4X大战略游戏,您可以在其中创建一个即将触及星星的种族,在那里它将遇到各种微小的异常现象,有用和有害的事件,强大的远古生物,休眠的堕落帝国,但是,最重要的是,其他种族与您同在:统治银河系。
您可以专注于扩展,技术,社会进步,战争或外交。 您可以独自行动,也可以结成联盟; 您可以和平或进取; 您甚至可以将其视为角色扮演游戏,尝试忠实于您的种族角色或发展其以应对挑战。 无论您是想灵通灵能,遗传进化,还是用机器人代替肉包,都是您的选择。
如您所知,我对Stellaris感到非常满意,但除此之外,我想向您介绍我周六开始的特定游戏。
纯净的天堂
在创建种族时,有很多特征可供选择,其中大多数是渐进式的(更多的研究,更好的战争),但有些是完全定义的。 其中之一是吞噬群 :您不仅要统治整个星系,不,您还想从字面上吃掉所有其他物种。 😋毫不奇怪,他们真的不喜欢那样,所以您被禁止一切外交。 一路都是银河战!
我的转折之处在于,我还尝试“扮演高个子”,这意味着只殖民一些极好的行星,专注于高科技并建造环形世界,戴森球或太空栖息地等巨型结构。
这导致了一个相当有趣的情况,我的帝国几乎没有生命,随着我在银河系中前进,总人口下降了。 一方面,理智与另一方面的虚无之间存在边界:几年后,我征服的一切都躺在废墟中,再也不会被另一个灵魂居住。
当我做完之后,天堂将没有肉体的害虫。 它将是纯净的! 哇哈哈哈!! 1
您应该尝试一下,这很有趣。
- 阿尔巴尼亚病毒
- Twitter处于最佳状态
- 写作过程
- 找个驱魔人
- 数羊
- “法师施放机器学习!”
- 迪拜沙漠
(抱歉,他们大多是Twitter。)
PS:别忘了 订阅 或 推荐 ! 🙂
