5个Java开发人员中有4个未能解决此问题

Java Deathmatch的结果–开发人员的益智迷你游戏

几个月前,我们发布了一个名为Java Deathmatch的微型站点 ,作为我们的新辅助项目,自那时以来,已有20,000多名开发人员进行了尝试。 该站点包含20个选择题Java的问题,今天我们收集了所有已玩游戏的统计信息后,很高兴与您分享一些结果和解决方案。

总体而言,我们收集了61,872个答案,对于20个问题中的每个问题,我们总共提供了3,094个答案。 每个Java Deathmatch会话随机选择5个问题,并给您90秒的时间来解决每个问题。 每个问题都有4个可能的答案。 我们一直被批评说,问题太难了,但是,没有理由将其称为死亡竞赛! 使用这些统计信息,我们能够确定哪些是最难的问题,哪些是最简单的问题。 在这篇文章中,我们想分享这个实验中的5个最棘手的问题,并将它们一起解决。

平均而言,尝试的答案中有41%是正确的,这一点也不差。此处提供按索引显示的结果和问题的实时统计信息。这篇文章的统计数据是7月26日的快照。

平均而言,尝试的答案中有41%是正确的,这一点也不差。 结果和按索引的问题的实时统计信息可在此处获得 这篇文章的统计数据是7月26日的快照。

1. Java死亡竞赛的最棘手问题

让我们从最难破解的螺母开始,这是我们从布加勒斯特收到的Alexandru-Constantin Bledea提出的问题。 这是一个真正的脑筋急转弯。 只有20%的参与者能够解决此问题。 这意味着,如果您会随机选择一个答案,则可能有更好的机会找到正确的答案。 Java泛型对此具有这种品质。

最棘手的问题

好吧,那我们这里有什么? 我们有涉及类型擦除的泛型,还有一些例外。 这里要记住几件事:

  1. RuntimeExceptionSQLException都从Exception继承,而RuntimeException是未检查的,而SQLException是已检查的异常。
  2. Java泛型未进行泛化,这意味着在编译时,泛型类型信息会“丢失”,并视为将代码替换为类型的绑定,如果不存在则替换为Object 。 这就是您所说的类型擦除。

我们天真地希望第7行会导致编译错误,因为您无法将SQLException强制转换为RuntimeException,但事实并非如此。 发生的是用Exception替换了T,所以我们有:

throw (Exception) t;  // t is also an Exception

由于pleaseThrow期望一个Exception ,并且TException替换,因此强制类型被消除,就好像它没有被编写一样。 我们可以在字节码中看到:

private pleaseThrow(Ljava/lang/Exception;)V throws java/lang/Exception
L0
LINENUMBER 8 L0
ALOAD 1
ATHROW
L1
LOCALVARIABLE this LTemp; L0 L1 0
// signature LTemp<TT;>;
// declaration: Temp<T>
LOCALVARIABLE t Ljava/lang/Exception; L0 L1 1
MAXSTACK = 1
MAXLOCALS = 2

只是为了好玩,我们试图查看不涉及泛型的字节码的样子,并且强制转换出现在ATHROW语句之前:

CHECKCAST java/lang/RuntimeException

现在我们已经确定不涉及任何强制转换,我们可以从以下两个答案中解脱出来:

  • “编译失败,因为我们无法将SQLException强制转换为RuntimeException”
  • “由于SQLException不是RuntimeException的实例而抛出ClassCastException”

因此,我们毕竟抛出了SQLException,并且您希望它被catch块捕获并获得其堆栈跟踪。 好吧,不是真的。 该游戏被操纵。 事实证明,编译器和我们一样感到困惑,代码使它认为catch块不可访问。 对于毫无戒心的旁观者, 没有SQLException 。 正确的答案是编译失败,因为编译器不希望从try块引发SQLException-实际上,确实会引发该异常!

再次感谢Alexandru与我们分享这个问题!

2. toString()或不是toString(),这就是问题

仅获得正确答案的24%,接下来的问题是艰难的挑战。

q9

这实际上要简单得多,仅通过查看第12行,我们可以看到此代码打印出m1和m2,而不是m1.name和m2.name。 这里最棘手的部分是要记住,当打印出一个类时,Java使用其toString方法。 人为地添加了“名称”字段。 如果您错过了它并正确地遵循了其余代码,则可能会被诱骗选择m1和新名称。

此行将两个名称都设置为“ m1”:

m1.name = m2.name = "m1";

然后callMe将m2的名称设置为新名称,我们完成了。

但是,此代码段实际上将打印出如下内容,包括类名和哈希码:

MyClass@3d0bc85 & MyClass@7d08c1b7

正确的答案将是“以上皆非”。

3. Google Guava Sets

这个问题实际上并不需要特定的番石榴集知识,但大多数受访者感到困惑。 只有25%的人正确回答了该问题,这与随机选择答案相同。

66

那么我们在这里看到什么? 我们有一种方法可以返回一个包含一个人的最好朋友的“陈词滥调”的集合。 我们看到有一个循环,用于检查一个人是否有最好的朋友,并将其添加到结果集中。 如果一个人确实有一个最好的朋友,它将为他们重复该过程,因此我们最终会拥有一组最好的朋友,直到我们找到一个没有最好朋友的人,或者它的最好朋友已经存在。 最后一部分可能有些棘手-我们无法添加已经在集合中的人,因此没有无限循环的可能。

这里的问题是我们冒着内存不足异常的风险。 集合上没有限制,因此我们可以不断添加和添加人员,直到内存用完为止。

顺便说一句,如果您喜欢Google Guava,请查看我们写的这篇文章,其中介绍了一些鲜为人知但有用的功能

4.双括号初始化,大声笑吗?

这是最短的问题之一,但足以使大多数开发人员感到困惑。 只有26%的人做对了。

q12

尽管需要一些常量, 没有很多开发人员知道需要初始化常量集合时使用的这种语法。 实际上,缺乏人气可能是一件好事。 那么当WAT? 效果消失了,您可以看到我们在列表中添加了一个元素,然后尝试将其打印出来。 通常,您希望它能打印出[John],但双括号初始化还有其他计划。 我们在这里看到的是一个用于初始化List的匿名类。 当它尝试打印出NAMES时,实际上显示为null。 由于尚未使用初始化程序,因此列表为空。

您可以在此处阅读有关双括号初始化的更多信息。

5.运行时地图的奇怪情况

这是来自以色列的Barak Yaish提出的另一个由社区提出的问题。 只有27%的参与者能够解决此问题。

22

好了,compute在地图中查找一个值。 如果为null,则将其添加并返回其值。 由于列表为空,因此不存在“ foo”,v为空,我们将“ foo”映射到新的ArrayList <Object>()ArrayList为空,因此将输出[]

对于第二行,“ foo”确实存在于地图中,因此我们评估右侧的表达式。 ArrayList已成功转换为List,并向其中添加了“ ber”。 add返回true,这就是它输出的内容。

正确答案是[] true 。 再次感谢Barak与我们分享这个问题!

奖金:最简单的问题是……

这次,我们有一个来自OpenHFTPeter Lawrey的问题,他也发表了Vanilla Java博客。 彼得在StackOverflow的前50名名单中,这次他移到另一边,问一个问题:你们中有76%的人正确。

最简单的问题

答案C比A简单,B&D不编译。

结论

有时我们真的很喜欢玩这种谜题以增强我们的Java知识,但是如果您发现自己在自己的代码库中花了太多时间在这些谜题上,那可能就不那么理想了。 特别是如果有人在半夜打电话来解决严重的生产错误。 对于这种情况,我们为Java构建了Takipi 。 Takipi是一个Java代理,它知道如何在生产中的服务器上跟踪未捕获的异常,捕获的异常以及记录错误。 它使您可以查看导致错误的变量值(遍及整个堆栈),并将其覆盖在代码中。

翻译自: https://www.javacodegeeks.com/2015/08/4-out-of-5-java-developers-failed-to-solve-this-question.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值