当前位置: 首页 > 知识库问答 >
问题:

引擎盖下Java开关是如何工作的?

谢俊力
2023-03-14

Java的switch语句是如何工作的?它如何将所使用变量的值与案例部分中给出的值进行比较?它是否使用==。等于(),还是完全是其他原因?

我主要对1.7之前的版本感兴趣。

共有3个答案

尹俊贤
2023-03-14

从这里复制的

在字节码中有两种形式的开关:表开关和lookupswitch。一种假设键集密集,另一种假设键集稀疏。请参阅JVM规范中编译开关的描述。对于枚举,找到序号,然后代码继续为int大小写。我不完全确定JDK7中提议的在String上切换的小功能将如何实现。

然而,大量使用的代码通常在任何合理的JVM中编译。乐观主义者并不完全愚蠢。不用担心,按照通常的启发式方法进行优化

你可以在这里找到详细的答案

卢权
2023-03-14

从这个答案中可以看出,Java开关(至少在1.7之前)并不总是编译成==. equals()。相反,它使用表查找。虽然这是一个非常小的微优化,但在进行大量比较时,表查找几乎总是更快。

请注意,这仅用于检查密集键的开关语句。例如,检查枚举值的所有可能性可能会产生这种主要实现(内部称为tablesitch)。

如果检查更稀疏的密钥集,JVM将使用另一种系统,称为查找开关(lookupswitch)。相反,它将简单地比较各种键和值,对每种可能性进行优化的比较。为了说明这两种方法,请考虑以下两个switch语句:

switch (value1) {
case 0:
    a();
    break;
case 1:
    b();
    break;
case 2:
    c();
    break;
case 3:
    d();
    break;
}

switch (value2) {
case 0:
    a();
    break;
case 35:
    b();
    break;
case 103:
    c();
    break;
case 1001:
    d();
    break;
}

第一个示例很可能使用表查找,而另一个示例(基本上)使用==比较。

赫连俊雄
2023-03-14

也不它使用JVM指令lookupswitch,它本质上是一个表查找。查看以下示例的字节码:

public static void main(String... args) {
  switch (1) {
  case 1:
    break;
  case 2:
    break;
  }
}

public static void main(java.lang.String[]);
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   iconst_1
   1:   lookupswitch{ //2
                1: 28;
                2: 31;
                default: 31 }
   28:  goto    31
   31:  return
 类似资料:
  • 但我对西农在台面下是如何工作仍有一些疑问。我想我是在说Sinon,但这个问题可能适用于所有其他设计为mock/stub/spy的库。 在过去的几年里,我工作最多的语言是Java。在Java中,我使用Mockito来模拟/存根依赖项和依赖项注入。我曾经导入这个类,用注释这个字段,并将这个mock作为param传递给被测试的类。对我来说,很容易看出我在做什么:模仿一个类,并将模仿作为param传递。

  • 新的Java17型模式匹配开关如何在引擎盖下工作?由于该功能相当新,本问题不讨论它。 提醒:要使此代码在Java 17下工作,需要启用预览功能 使用javap-c对上述代码进行了反汇编: 鉴于这一关键点: 看起来Java在自动生成的int-typeSwitch(object,int)方法中将对象转换为int,我看不到生成的代码。这种转换的目标是能够在int值上使用常规的切换表。 起初,我认为使用了

  • 除了阅读github中的代码之外,是否有关于signalr.redis包如何工作的白皮书类型的文档?具体地说,我想知道它为Redis添加了哪些键、更新/删除策略等。当查看Redis内部时,我只看到以下调用中指定的一个键(即“signalr.Redis.sample”): 这把钥匙好像是Redis的柜台。我假设正在创建其他键并迅速删除,以方便连接到Redis的每个应用服务器之间的消息。

  • @Component表示给定的类将是给定上下文中的单例,@aspect表示在运行时/编译期间,一个方面类的内容将以某种方式编织到目标类中--例如,这个目标类不是单例而是原型。我最后的结局是什么?

  • 此函数生成数组的排列。我已经把笔放在纸上,在开发工具中放置断点,并煞费苦心地逐步完成每个函数调用,但我仍然不明白这是如何工作的。 具体来说,就是 for 循环。一旦 do It 函数拼接了数组中的所有数字,它将临时数组的切片副本推送到答案数组中。然后,它将项拼接到参数数组中,从临时数组中弹出相同的项,并返回 for 循环第一次迭代的答案。因此,在遍历数组一次后,答案 = [1,2,3] 温度 =

  • 问题内容: 在阅读了戴夫·切尼(Dave Cheney)关于Go的地图的博客文章之后,对我来说,还有几件事尚不清楚。 TLDR: 为什么它们无序? 实际值存储在哪里? 深入研究运行时程序包后,我发现基本的映射结构如下: -是存储区数组,其中索引是键的哈希值的低位,其中存储区为: ..好吧,这只是每个项目是键的哈希值的第一个字节的数组。键值对存储为(每个存储桶八对)。但是到底在哪里?考虑到映射可能包