【问题标题】:byte byteVar = 100 works but int intVar = 100L results in compilation error. Why?byte byteVar = 100 有效,但 int intVar = 100L 会导致编译错误。为什么?
【发布时间】:2020-10-31 22:09:04
【问题描述】:

整数字面量可以分配给字节或短变量只要字面量的值在字节/短的范围内

但是将long literal赋值给int变量时,即使long literal的值在int范围内也会报编译错误

解释这个的逻辑是什么?

例子,

下面这行编译成功

byte byteVar =  100;   //works, here 100 is integer literal.

但是

int intVar = 100L;   // fails, here 100L is long literal

导致编译时错误。

谁能解释一下驱动这个的底层逻辑。

【问题讨论】:

  • even when the value of long literal is within the range of int. 不,long (64b) 大于 int (32b) docs.oracle.com/javase/tutorial/java/nutsandbolts/…
  • int intVar = 100L; 永远不会编译。您需要将其声明为长类型。您不能将 64 位长填充到 32 位整数中。
  • 第二个赋值是从 long 到 int 的缩小转换,因此需要根据 JLS 进行显式转换。请参阅:docs.oracle.com/javase/specs/jls/se7/html/jls-5.html
  • 我想作者想知道为什么编译器不理解常量 100L 在不丢失信息的情况下适合 int。我想他们知道 Java 类型的提升以及何时需要转换,因为信息会丢失,例如当有小数位时从 double 到 long。我认为这是一个有趣的问题,尤其是因为 100L 是恒定的,不能改变。
  • @Fred 只是 Java 设计者的决定。

标签: java


【解决方案1】:

实际原因比其他一些答案所暗示的要复杂一些。

JLS 5.2 陈述了以下关于赋值上下文中允许的转换。

另外,如果表达式是一个常量表达式(§15.28) 输入byteshortcharint

  • 如果变量的类型为byteshortchar,并且常量表达式的值为 可以用变量的类型来表示。

  • 如果变量的类型为 ByteShortCharacter,则可以使用紧缩原语转换后跟装箱转换,并且 常量表达式的值可以用类型表示 分别为byteshortchar

声明/初始化

byte byteVar =  100;  // OK

因为满足所有先决条件而有效:

  • 100 是一个常量表达式
  • 它的类型是int
  • 它的值在byte的范围内;即它可以表示为byte
  • 它被分配给byte 变量。

声明/初始化

byte byteVar =  100L;  // FAIL

失败,因为 100L 的类型是 long 而不是 int

【讨论】:

    【解决方案2】:

    逻辑

    int intVar = 100L;
    

    不编译只是“如果你希望它是int,为什么要明确地说L?可能是某个地方的错误,但我们不知道是类型还是值错误”。

    更有趣的部分是为什么

    byte byteVar = 100;
    

    编译而不是要求您编写类似100b 的内容。而且我相信至少有两个原因:

    1. 右边部分可能是一个常量表达式,而不仅仅是一个字面量:in

      byte byteVar = SOME_CONST + 3;
      

      您不能使用后缀,即使 SOME_CONSTbyte,右侧也是 int

    2. 只是 C++ 没有它,Java 从 C++ 继承了很多。

    【讨论】:

      【解决方案3】:

      L 表示 64 位 int 整数原语。

      int intVar = 100L;

      以下行将无法编译,因为您试图将 64 位长的原始文字放入 32 位 int 变量中。它将给出: // BAD — 编译器失败 — 不能将 64 位 long int 原语放入 32 位 int 变量中。

      【讨论】:

      • 如果这就是全部原因,byte byteVar = 100; 也不起作用。问题是为什么会有差异
      • 如果这是原因,那么为什么 int 字面量(32b)可以进入字节变量(8b)?
      • 只是为了消除混淆,在Java中字节范围是-128127。您可以将该范围内的整数存储在一个字节中而不会溢出。所以,字节 byteVar = 100;会工作,但如果你尝试:byte byteVar = 128; 它不会工作。
      【解决方案4】:

      字节格式是 8 位整数格式,可以接受 -128 到 127 范围内的有符号整数值。因为整数值 100 适合此范围,

      byte byteVar = 100;
      

      编译;整数文字对于您尝试将其存储在其中的内容具有有效的比例。https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html 列出了原始数据类型的默认值,并且该表显示 byte、short 和 int 都共享相同的值结构;一个与文字没有任何关联的整数。

      int 和 100L 不起作用的原因是 L 后缀创建了一个 long 或 Int64 文字。 int 是 Int32,32 位 2 的补码有符号整数格式。通过指定值 100 应该是 64 位 2 的补码有符号整数格式,这将不适合 32 位而不会溢出,这就是编译器不允许该赋值的原因。

      【讨论】:

        猜你喜欢
        • 2011-06-25
        • 2011-06-09
        • 1970-01-01
        • 2019-08-30
        • 2014-05-23
        • 1970-01-01
        • 2018-04-08
        • 2020-04-26
        • 2016-05-13
        相关资源
        最近更新 更多