【问题标题】:Java byte type is weird?Java字节类型很奇怪?
【发布时间】:2012-02-20 18:22:18
【问题描述】:

谁能解释一下java字节类型?

这不能编译:

byte b1 = 9;
byte b2 = 1;
byte b3 = b1 + b2;

虽然这样做:

byte b4 = 9 + 1;
byte b5 = (char)(9+1);

此外,分配给 long 不起作用,即使值适合一个字节:

byte b7 = (long)127;

包装器会变得更奇怪

这样编译:

Byte b6 = (int)3;

但这不是:

Integer i = (byte)3;

【问题讨论】:

  • 如果没有投诉的错误信息和行号,这很难回答。
  • 另外,byte x = 126 + 1; 有效,但 byte y = 126 + 2; 无效,不知何故,当使用可计算值时,编译器会检查容器是否足够宽。但是,在 JLS 中找不到参考。
  • 在这个问题的答案中详细讨论了这一点:link
  • JLS 5.2:赋值转换
  • 是的,因为 JLS 5.2 说,缩小对话只针对 byte、short、char 和 int 进行。 Long 在这方面很特别。

标签: java


【解决方案1】:

Java 语言规范 5.6.2 二进制数字提升:“否则,两个操作数都转换为 int 类型”。

所以Java将两个操作数都转换为int,所以加法的结果是一个int。

补充:b3 和 b4 的区别在于,在 b4 中是常量表达式(15.28),在 b3 中是字面量。

【讨论】:

  • JVM 规范,满足您的所有需求。 java.sun.com/docs/books/jvms/second_edition/html/…
  • 包装类发生了什么? int 可以放入 Byte,但 byte 不能放入 Integer,这似乎违反直觉
  • 仍在尝试找出包装器。从规格中很难弄清楚会发生什么。
  • 包装行为依赖于整数文字由编译器专门处理的事实(即适合字节范围的整数文字可以用作字节)。如果您使用 128+ 或事先将其分配给变量,它将停止工作。不,不要问我 JLS 中的描述在哪里 :)
【解决方案2】:

b6 由于文字常量的编译时变窄而起作用。 b7 不起作用,因为编译时缩小仅限于所有原语但很长(有点奇怪,不知道为什么)

有趣的部分是§5.2 of the JLS:

In addition, if the expression is a constant expression (§15.28) of type byte, short, char or int :

A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.
A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is :

 - Byte and the value of the constant expression is representable in the
   type byte.

 - Short and the value of the constant expression is representable in
   the type short.     

 - Character and the value of the constant expression is representable in the type char.

If the type of the expression cannot be converted to the type of the variable by a conversion permitted in an assignment context, then a compile-time error occurs.

不知道为什么i 不起作用 - 扩展应该可以正常工作,事实上,编译器应该生成类似Integer.valueOf((byte)3); 的东西。使用显式调用按预期工作,即正在扩大。

有趣的是,使用 eclipse Java 编译器 Integer i = (byte) 3; 编译得很好,这让我相信你刚刚在 javac 中发现了一个错误 - 恭喜! (好吧,要么是 Eclipse 编译器中的错误;但 Eclipse 的行为对我来说似乎是正确的)。 FWIW 我已经向 oracle 报告了针对 javac 的错误..

在 JLS 中找到正确的部分比格式化它更容易阅读 - 如果你点击链接可能会更容易。

【讨论】:

  • 我也把我弄糊涂了...我猜它会被翻译成类似 = new Integer((byte)3));但这实际上会起作用......我只是猜想它在 JLS 中并没有真正澄清
  • @CSE 不,编译器使用 valueOf 方法(任何人都应该使用 Wrapper API,构造函数真的不应该公开),但是对我来说这似乎是一个错误,因为显式调用实际上有效。 Here's 错误报告,尽管在撰写本文时仍未由 oracle 审查 - 可能需要几天时间。
【解决方案3】:

第一个 sn-p 会产生编译错误,因为所有数字常量在 java 中默认为 ints。

【讨论】:

  • 但是前两行应该失败?
  • @CSE:这正是我在这个答案中所描述的。
  • 是的,但是 b1 和 b2 的行可以编译。 b3 失败。
猜你喜欢
  • 1970-01-01
  • 2016-03-26
  • 2013-06-10
  • 2013-04-03
  • 1970-01-01
  • 1970-01-01
  • 2019-01-03
  • 2012-02-19
  • 1970-01-01
相关资源
最近更新 更多