【问题标题】:“Type mismatch: cannot convert int to byte”“类型不匹配:无法将 int 转换为 byte”
【发布时间】:2013-11-17 03:42:40
【问题描述】:

我看到有人问有关错误“类型不匹配:无法将 int 转换为字节”的问题。但它们大多是由所涉及的算术运算引起的。

这是我的情况:
(当我想在 Eclipse Kepler 中使用位时会发生这种情况)

//java 7 binary literals

byte a =  0b01111111; //8-bit it compiles 

byte b =  0b10000000;  //8-bit error: Type mismatch: cannot convert int to byte.                        

byte c =  (byte) 0b10000000; //8-bit it works fine if casted.

问题是,如果它是 8 位并且最高位是 1,那么编译器会出错。 我想知道为什么。前缀 0b 表示它是二进制文字,那么为什么编译器将最高位作为有符号整数位或类似的东西?

感谢您的回答。

[编辑3:]

byte a = -128; //a = 0xFF = 11111111 (8 bits), compiler says ok.
byte b = 0b11111111; //compiler error

[Edit2:按位 & 运算也会以某种方式触发错误]

byte a = 0b00000000;  //8 bits
a = (a&0xFF);  //gives same error: Type mismatch: cannot convert int to byte
a = (byte)(a&0xFF); //it is fine to cast

[Edit1:截图更新]

【问题讨论】:

    标签: java byte bit-manipulation


    【解决方案1】:

    你说得对,怀疑这是关于有符号整数的。在 Java 中,所有整数类型(byteshortintlong)总是有符号的。 Java 使用二进制补码来存储有符号(读取“全部”)值。这基本上意味着,如果任何类型的第一位(不是文字中指定的第一位,而是存储的第一位)为 1,则该数字为负数。如果为 0,则为正数。

    第二件重要的事情是:Java 中没有 BYTE 字面量。有 int 文字和 long 文字。写下的每个数字(无论是二进制(0b 前缀)、八进制(0 前缀)、十进制(无前缀)还是十六进制(0x 前缀))都是整数文字,除非您附加 L(小写或大写) ,它是long。没有办法直接写下任何shortbyte

    现在,这意味着您写下的所有这些示例都首先创建了一个int。您不会在那里创建bytes。

    所以,最后一部分是,如果您尝试将 int 存储在 byte 中会发生什么 - 不进行强制转换或使用强制转换。 如果您明确地进行转换,您基本上是告诉 Java 忽略任何不适合的位。它们将被剪切 - 即使这改变了数字的值(例如,见下文)。 如果你不铸造,钻头仍然会被切割。但是 Java 不会这样做,如果它改变了值 - 以确保你真的是在做你正在做的事情。

    要将这一切链接到问题中的示例:
    int 0b01111111 是 127
    byte 0b01111111 是 127
    -> 可以在没有任何溢出的情况下进行转换,因此即使没有显式强制转换,Java 也会这样做

    int 0b10000000 是 128
    byte 0b10000000 是 -128
    -> 转换时出现溢出,所以如果没有显式转换,Java 会抛出错误。

    【讨论】:

    • @jprofitt:哦。斯内普,你就在那儿。那...可能会改变答案...必须对此进行一些阅读。
    • 其实我现在更糊涂了。根据语言规范,没有字节文字。所以这些情况都不应该起作用......
    • @JohannesH。 : 二进制字面量是在 Java 7 中引入的。因此在较低版本中,它们将不可用。
    • @JohannesH。那不应该是“追加L”,而不是“追加L”吗?
    • 明白你的意思。 “Java 中没有 BYTE 文字。有 int 文字和 long 文字。”这让我完全理解了整个事情。
    【解决方案2】:

    我认为 java 中的字节是有符号的,这会使 0b10000000 超出范围。 127 可能是最大的字节,原因是负数的二进制补码表示。

    【讨论】:

    • 二进制补码表示中,0b10000000为-128,在java中仍处于int范围内。
    • 正确,但您试图创建一个字节,因此出现错误。类型字节不能保存值 0b10000000
    • +1 在这里引领潮流,我同意,这必须是答案。对此添加了更多细节,请参阅我的答案。
    • 是的,它缺少导致问题的二进制文字。 +1
    • 我还是没明白为什么一个字节不能容纳0b10000000的值?它是 8 位。它应该代表一些价值,对吧?为什么会溢出?
    【解决方案3】:

    字节变量可以保存值 0b1000000,但由于它们是有符号的,因此表示整数值 -128。它无法转换文字的原因是,当您将其编写为没有强制转换的文字时,编译器会将其视为 (int) 0b10000000,即整数值 POSITIVE 128。

    任何大于 127 的整数值都超出了字节的范围,因为字节是有符号的,并且只能保存从 -128 到 127 的整数值。这就是溢出的来源(要保存 128,您需要第九位为标志)。每当有符号值的最高有效位为 1 时,它就表示一个负数,因此为了将 0b10000000 之类的数字放入一个字节中,您需要在文字中表示一个负值。例如,值 -128 将等效于 int 0b11111111111111111111111110000000,因此您需要将其用作文字,或者更简单,只需将其显式转换为字节,例如: (byte) 0b10000000

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 1970-01-01
      • 2020-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多