查询 1:
byte a = 0; // int to byte implicit conversion happens, correct!, no CTE [compile time error]
setByte(0); // CTE!, why ? implicit conversion do not happen here
void setByte(byte b){}
查询 2:
byte b_byte = 128 - 1; // integer literal computation results to 127 int which implicitly casts to byte and as 127 is in range of byte so no CTE, Correct!
int a_int = 2147483647; // in range of int, so no CTE
int b_int = 2147483648 - 1; // still in range of int but CTE, why ?
请解释,同时指向定义这些规则的 JLS 部分。
最佳答案
首先,Assignment Conversions, JLS 5.2涵盖了可以分配的值。
In addition, if the expression is a constant expression (§15.28) of type
byte
,short
,char
, orint
:
- A narrowing primitive conversion may be used if the variable is of type
byte
,short
, orchar
, and the value of the constant expression is representable in the type of the variable.
对于 byte a = 0;
,常量表达式是 int
0
,它被缩小为 byte
.
接下来,Invocation Contexts, JLS 5.3涵盖哪些值可以传递给方法。
Neither strict nor loose invocation contexts include the implicit narrowing of integer constant expressions which is allowed in assignment contexts.
因此,您的代码存在调用上下文(方法调用)中不允许的常量表达式缩小转换的编译器错误。
setByte(0); // no implicit narrowing conversion, even if it's a constant expression
void setByte(byte b){}
您的代码 128 - 1
是一个缩小到 byte
的常量表达式。
但是,2147483648 - 1
是不允许的,因为 2147483648
本身 is not a valid int
literal, Section 3.10.1, "Integer Literals" .
It is a compile-time error if the decimal literal 2147483648 appears anywhere other than as the operand of the unary minus operator; or if a decimal literal of type int is larger than 2147483648 (231).
如果你真的想使用一个不必要的复杂表达式来初始化一个int
,你可以使用一个long
字面量来使表达式合法:
2147483648L - 1
但是您必须明确地将表达式转换为 int
;没有从任何比 int
宽的东西隐式缩小到 int
:
(int) (2147483648L - 1)
奇怪的是,您不必在表达式两边放置圆括号以便强制转换应用于整个表达式,尽管为了清楚起见我强烈建议使用圆括号。
(int) 2147483648L - 1 // It's 2147483647!
在int
范围之外的long
文字上的int
将产生-2147483648,一个有效的int
值。此处减 1 涉及负方向溢出,产生预期值 2147483647。
关于java - 为什么我们不能将整数文字作为参数传递给以字节作为形式参数的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57858640/