将 int 文字分配给字节变量时是不是需要强制转换?

Posted

技术标签:

【中文标题】将 int 文字分配给字节变量时是不是需要强制转换?【英文标题】:Is a cast necessary when assigning an int literal to a byte variable?将 int 文字分配给字节变量时是否需要强制转换? 【发布时间】:2017-09-26 16:07:33 【问题描述】:

我读了一本书有一行:

byte rounds = 12, fighters = (byte) 2;

说明

字节原语有一个四字节有符号整数作为其有效 文字。如果不执行显式转换,则整数为 隐式转换为一个字节。

根据Oracle doc,一个字节不应该是一个字节吗?

【问题讨论】:

Java 语言规范有时似乎非常狭隘/低级。 byte b = 300; 会报错,但一般来说,int 常量可能会缩小到一个字节。 300 是一个整数。就是这个意思。 至少相关,如果不是欺骗目标:***.com/questions/39886332/… 你看的书是错的。也许,将来避免同一作者的书。另外,请考虑将文本中的错误报告给出版商,以便他们可以在下一版图书中修复它(如果有的话)。 这是一个误导性的陈述,充其量。文字 12 总是int 文字。您只能在 分配(包括初始化)byte 变量时使用 int 文字,前提是文字值适合 byte 值集。但是,例如,您不能将文字 12 作为参数传递给需要 byte 参数的方法。从intbyte 没有隐式转换。请注意,这通常适用于整数常量,例如你也可以写byte b = 'a';,因为它适合字节值集,或者char c = 97; 【参考方案1】:

Java 提供了用于初始化原始数据类型的特殊文字,例如

int a = 1234;
double b = 12.34;
float c = 56.78f;
char d = 'x';

文档说byte 类型没有特殊的文字。相反,原始类型byteint 共享其文字。当带符号的 32 位 int 文字“适合”单个字节时,Java 将执行隐式转换;否则会产生编译时错误。

【讨论】:

是5.1.3. Narrowing Primitive Conversion的意思吗? @RexT 5.1.3 讨论了您通过手动添加强制转换来强制转换。如果你写byte x = (byte)12345,那将是一个狭窄的转换,这是Java允许的。当您编写byte x = 12345 时,这将是一种隐式缩小转换的尝试,Java 不允许这样做,因为12345 不适合byte。当您编写byte x = 45 时,Java 允许进行隐式缩小转换,因为45 适合byte 我仍然不确定。根据语句“如果未执行显式转换,则整数被隐式转换为一个字节。”。所以fighters = (byte) 2;中的2是4字节,byte rounds = 12中的12是1字节? @Rex T:变量 roundsfighters 具有声明的类型byte,仅此而已。 212 的值始终是 int 值。 @RexT 对于 Java 编译器,212 都是 int 文字,表示前三个字节设置为零的四字节整数。在没有强制转换的情况下,转换是隐式的,因此四字节值必须表示一个适合有符号字节的数字。添加强制转换时,转换是显式的,因此对 32 位整数常量的值没有限制。【参考方案2】:

如果不执行显式转换,则整数被隐式转换为一个字节。

如果一本书这么说,那是不正确的。或者至少,它并没有讲述整个故事。

(从技术上讲,这些是转换而不是强制转换。强制转换涉及 Java (<type>) 语法。)

implicit缩小conversions的整个故事如下:

它们仅适用于分配上下文;见JLS 5.2。 它们仅适用于被强制转换的值是(编译时)常量表达式的情况;见JLS 15.28。 它们仅适用于值类型为 bytecharshortint 它们仅适用于目标类型为 bytecharshort,或相应的包装器类型(ByteCharacterShort)。 它们仅适用于值将“适合”目标类型而不截断的情况。

例如:

   byte b = -1;      // OK
   Byte b1 = -1;     // OK
   byte b2 = 255     // Error: value is not in range of 'byte'
   byte b3 = 1 + 1;  // OK
   byte b4 = b + 1;  // Error: not a constant expression

   public void test (byte b) ...

   test(byte(12));   // OK: explicit narrowing conversion
   test(12);         // Error: not an assignment context.

总而言之,只有当编译器可以确定它永远不会导致任何信息丢失时,才允许这种转换。

【讨论】:

“演员阵容涉及 Java (<type>) 语法。)” 这也不是全部;使用泛型代码时存在隐式转换,例如,如果您有一个 List<String> 并且您编写了 String s = theList.get(0);,则类型为 String 的隐式转换;如果元素碰巧不是String(可能,例如,如果您从原始List 开始),那么它会以ClassCastException 失败。当然,这不是同一种隐式转换,我只是观察到并非所有强制转换在源代码中都是显式的。 嗯......你在这里谈论的“隐式类型转换”(这是一个真实的东西)实际上是一个缩小引用转换,我认为;参见 JLS 5.1.6,第 2 段。JLS 中不使用短语“隐式类型转换”。我的观点是,引用的书本在术语上玩得又快又松。 (但这可能是引用被断章取义。我们实际上并不知道 OP 正在阅读哪本书......所以我们无法检查。) JLS 不称其为演员表,但鉴于它以ClassCastException 失败,我认为将其称为演员表是合理的;并且theList.get(0) 的字节码与为(String) theList.get(0) 生成的字节码相同,因此即使JLS 没有将其称为隐式转换,它也具有真实的技术意义。另一个例子是byteVar += intVar;,JLS 说它“等同于”byteVar = (byte)(byteVar + intVar);,它们生成相同的字节码,尽管 JLS 将其称为“转换”而不是“转换”。 也就是说,我同意 OP 书中引用的句子并不完全正确。 1) 我不同意你基于类名的推断。一个更简单的解释是,他们认为追溯 添加另一个名为ValueConversionException 的类是一个坏主意。 2) 在赋值表达式的情况下,文本说明实际执行的是值集转换,参见 15.26.2。那时它没有说“类型转换”。本节开头提到的等效性(在我看来)旨在作为一种便于阅读的手波摘要,而不是规范性的。【参考方案3】:

一个字节就是一个字节。但是文字 12 是整数类型,即 4 个字节。这句话的意思是,当你写byte rounds = 12 时,存在一个隐式转换,将整数 12 转换为一个字节。

【讨论】:

这肯定有欺骗目标吗?

以上是关于将 int 文字分配给字节变量时是不是需要强制转换?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA中int强制转换byte

无法将 128 分配给字节,为啥它会出错而不是溢出?

java 强制类型转换的规则是啥?

java--基本数据类型的转换(强制转换)

为啥可以将切片分配给空接口但不能将其强制转换为相同的空接口

5指针