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

(避免)为空的装箱

岳安福
2023-03-14
public class Field<T>
{
    public static bool IsNull(T value) => value is null; // or: => value == null;
}
.method public hidebysig static bool  IsNull(!T 'value') cil managed
{
  // Code size       15 (0xf)
  .maxstack  2
  .locals init (bool V_0)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  box        !T
  IL_0007:  ldnull
  IL_0008:  ceq
  IL_000a:  stloc.0
  IL_000b:  br.s       IL_000d
  IL_000d:  ldloc.0
  IL_000e:  ret
} // end of method Field`1::IsNull
public class Field
{
    public static bool IsNull(int? value)
    {
        return value == null;
    }
}

将编译为以下内容而不使用装箱:

.method public hidebysig static bool  IsNull(valuetype [System.Runtime]System.Nullable`1<int32> 'value') cil managed
{
  // Code size       16 (0x10)
  .maxstack  2
  .locals init (bool V_0)
  IL_0000:  nop
  IL_0001:  ldarga.s   'value'
  IL_0003:  call       instance bool valuetype [System.Runtime]System.Nullable`1<int32>::get_HasValue()
  IL_0008:  ldc.i4.0
  IL_0009:  ceq
  IL_000b:  stloc.0
  IL_000c:  br.s       IL_000e
  IL_000e:  ldloc.0
  IL_000f:  ret
} // end of method Field::IsNull

因此,编译器确实特别对待nullable<>,但不是在泛型类上下文中。

共有1个答案

曾新立
2023-03-14

如您更新的问题所示:

public static bool IsNull(T value) => value is null;

编译为以下IL代码:

IL_0000: ldarg.0
IL_0001: box !T
IL_0006: ldnull
IL_0007: ceq
IL_0009: ret

在那里你真的看到了一些拳击。

test ecx, ecx
sete al
movzx eax, al
ret
xor eax, eax
ret

为了完整起见,对于像int?这样的可空值类型,我们得到:

cmp byte ptr [esp+4], 0
sete al
movzx eax, al
ret 8

可空值类型在内部只是一种结构,如果对象实际上有一个值,即不是空值,它就保存实际值和标志。因此,在本机代码中,它访问标志(您可以看到int?存储在堆栈中,标志的偏移量为4),并将其与0进行比较(false)。

在这种情况下,您不必担心装箱,因为实际上不会创建装箱对象。

 类似资料:
  • 我想知道是否有可能在Java中“避免”空检查,以下面的代码为例: 它必须检查4次,否则代码将失败。 是否可以将语句转换为只有在没有NullPointerException时才执行的一行式语句?当出现异常时,该行应该被忽略。 这里我不是在谈论一个通用的语言特性,我是在谈论一个只有当您明确决定这样做时才会上交的特性。 例如:将是建议代码的一个片段。 在Java可能发生这样的事情吗? 如果不可能的话,在

  • 但是,如果camp.start_date为NULL或没有行,那么它将引发异常- ORA-01858:在需要数字的地方发现了一个非数字字符 camp.start_date实际上是一个VARCHAR2,我需要将它转换为日期(是的,我知道它可能应该是一个日期字段,但我没有更改它的选项)。 其中camp.start_date不为null并且to_date(camp.start_date,'mm/dd/yy

  • 我正在使用Guava缓存热数据。当缓存中不存在数据时,我必须从数据库中获取数据: 我的问题是当数据不存在于数据库中时,我希望它返回并且不做任何缓存。但Guava保存与缓存中的关键字,并抛出一个异常,当我得到它: com.google.common.cache.CacheLoader$InvalidCacheLoadExcION: CacheLoader为shisoft键返回null。 我们如何避免

  • 我正在尝试根据我的边2[]数组中的对象编写一个新文档。现在不幸的是,这个数组中的一些索引为空,当它击中其中一个时,它只是给了我一个NullPointerExc的。这个数组有10个索引,但在这种情况下并不需要所有的索引。我已经尝试了try的捕捉语句,希望在它遇到空值后继续,但它仍然停止执行,并且不写新文档。作为对象一部分的堆栈(sire)包含我想打印出来的数据。 这是我的代码:

  • 我有如下所示的JSON 我将文件读成字符串并创建一个JSONObject,如下所示 然而,我认为我可以用try catch将语句括起来 请建议在这种情况下是否有任何合理的理由放一个长的if条件,而不是仅仅try-catch-log然后继续。 您还可以分享使用JSONException在此上下文中是否有任何“优点”吗?

  • 今天,我需要一个解决方案来避免在修补程序安装的上下文中通过install4j Version6.1.3创建安装目录。我编写了一个安装程序,其中包含一些文件来将它们安装到现有的应用程序安装中。这些文件应该与修补程序安装程序捆绑在一起。在install files操作中,我停用了install运行时选择点,但安装程序仍然创建了包含名为.install4j的文件夹的安装目录。在这个文件夹中只有一些ins