java - Java中的隐式转换如何工作?

标签 java casting type-conversion implicit-conversion narrowing

我知道在Java中,整数默认是int,所以如果我写这样的话

byte byteValue = 2;
Java自动将文字值 2 (默认为int)转换为字节。
如果我写同样的东西
byte byteValue = 4/2;
RHS被评估为一个int值,并隐式转换为一个字节。
但是,在以下两种情况下为什么不进行隐式转换?
int n1 = 4;
byte value = n1/2;
或者在这个
byte n1 = 4;
byte value = n1/2;
我知道这两个示例的RHS都被评估为int。但是Java为什么不像前两种情况那样将其隐式转换为字节,仅当有文字时才隐式转换为较小的数据类型?

最佳答案

说明
让我们看一下您的代码和一些修改后的示例:

// Example 1
byte byteValue = 2;

// Example 2
byte byteValue = 4/2;

// Example 3
byte byteValue = 2000;

// Example 4
byte byteValue = 500/2;

// Example 5
int n1 = 4;
byte byteValue = n1/2;

无损转换
您将获得示例3,示例4和示例5的提及的编译时错误。
首先,示例1至4的简单数学运算是在编译时执行的。因此,Java将在编译时计算500 / 2,并使用byte byteValue = 250;基本上替换该代码。
Java中字节的有效值为-128127。因此,超出该范围的任何值都不能仅视为byte,而需要进行显式转换。因此,示例1和示例2通过了。

有损缩小转换
为了理解其余部分为什么失败,我们必须研究Java语言规范(JLS),更具体地说是5.1.3. Narrowing Primitive Conversion5.2. Assignment Contexts一章。
它说从intbyte的转换(如果它不在byte的范围内)是缩小了原始转换,并且它可能会丢失信息(出于明显的原因)。继续说明转换是如何完成的:

A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.


从第二章开始,如果值是常数表达式,则允许进行窄转换的分配

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

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


简而言之,必须向Java明确声明可能会丢失信息(因为值超出范围)的缩小转换。 Java不仅会在不强制您的情况下为您完成任务。这是通过 Actor 阵容完成的。
所以举个例子
byte byteValue = (byte) (500 / 2);
产生值-6

常数表达
您的最后一个示例非常有趣:
int n1 = 4;
byte byteValue = n1/2;
尽管不超出范围,但Java仍将其视为有损缩小转换。为什么会这样?
好吧,Java无法保证n1在执行n1/2之前的第二秒内没有更改。因此,它必须考虑所有代码,以查看是否有人偷偷地访问了n1并对其进行了更改。 Java在编译时不进行这种分析。
因此,如果您可以告诉Java n1保持4且实际上永远不会改变,那么它将可以编译。在这种特定情况下,将其设置为final就足够了。所以用
final int n1 = 4;
byte byteValue = n1/2;
它实际上将进行编译,因为Java知道n1保留为4并且无法再更改。因此,它可以在编译时将n1/2计算为2,并将代码替换为基本上在范围内的byte byteValue = 2;
因此,如前面在5.2. Assignment Contexts中所述,您将n1 / 2设为常数表达式
您可以检查详细信息,以便在15.29. Constant Expressions中具有常量表达式。基本上,所有简单的事情都可以轻松地就地计算,而无需任何方法调用或其他花哨的东西。

关于java - Java中的隐式转换如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62965817/

相关文章:

java - setSelected() 与 JRadioButton r[]=new JRadioButton[3] 不起作用

java - 如何组合下面的 if 循环?

c# - 装箱/拆箱 - 只有值类型? Ref.types - 类型转换?

c++ - 用于验证类型的动态转换

Javascript [Symbol.toPrimitive](hint) 转换函数

python - Pandas 数据透视表将 float 转换为 int

java - 将正则表达式转换为 java 兼容正则表达式的简单方法?

java - 什么会导致 Eclipse 在调试时难以切换到正确的文件和行号

c - 指针和类型转换

c++ - 自动将一种 C++ 类型转换为另一种