Java 中的类型转换歧义



我对Java很陌生。遇到问题,想更深入地了解它。

以下代码无法编译:

byte a = 10;
byte b = 20;
byte c = a + b;

编译错误 -> 类型不匹配:无法从 int 转换为字节

这是一个编译错误,因为:

在 Java 中,所有整数文本都被视为整数。

因此,a+b 会产生一个整数文本,在存储在字节类型变量中之前,需要将其类型转换为字节,因为可能会丢失精度。我完全理解上述概念。

让我感到困惑的是浮点变量的类似概念。以下代码片段编译成功:

float d = 1.2;
float e = 2.3;
float f = d + e;

根据Java:

在 Java 中,所有十进制文字都被视为十进制。

因此,在类似的注释 (d + e) 中,必须产生一个十进制文本,该文本将被视为十进制类型并存储在浮点型变量中。在这里,我们也有精度的损失。为什么编译器不像前面的情况那样强迫我们在这里进行显式类型转换?为什么这里不是编译错误?

Java 中的类型转换歧义

您发布的代码中没有类型转换。

以下代码无法编译:

byte a = 10;
byte b = 20;
byte c = a + b;
Compilation error -> Type mismatch: cannot convert from int to byte

这是一个编译错误,因为:

在 Java 中,所有整数文本都被视为整数。

不,不是。这是一个编译错误,因为类型之间的所有操作都比int窄,都会生成int值。JLS #4.2.2 整数运算:

如果移位运算符以外的整数运算符至少有一个 long 类型的操作数,则使用 64 位精度执行运算,并且数值运算符的结果为 long 类型。如果另一个操作数不长,则首先通过数字提升 (§5.6) 将其加宽 (§5.1.5) 以键入 long。

否则,将使用 32 位精度执行运算,并且数值运算符的结果为 int 类型。如果任一操作数不是 int,则首先通过数字提升将其扩大为类型 int。

如果你声称的Java规则真的是Java规则,那么所有三行都无法编译。但是在Java中没有像你声称的那样的规则。你只是编造的。

因此,a+b 会产生一个整数文本

不,它没有。它生成一个整数值。

在存储在字节类型变量中之前,需要将其类型转换为 Byte,因为可能会丢失精度。我完全理解上述概念。

不,你根本不明白。

让我感到困惑的是浮点变量的类似概念。以下代码片段编译成功:

float d = 1.2;
float e = 2.3;

不,它没有。两行都会产生编译错误:error: incompatible types: possible lossy conversion from double to float

float f = d + e;

这将编译。

根据Java:

在 Java 中,所有十进制文字都被视为十进制。

没有这样的规则。再一次,你刚刚编造了这个。Java中没有"十进制文字"这样的东西,也没有Decimal

因此,在类似的注释 (d + e) 上必须产生十进制文本

不。它会产生一个float值。

将被视为十进制类型

Java中没有"十进制类型"。有BigDecimal,它是一个类,不是一个类型,但它与这个问题没有任何关系。

并存储在浮点型变量中。在这里,我们也有精度的损失。

不,我们没有。JLS #4.2.4 '浮点运算:

如果数值运算符的至少一个操作数是双精度类型,则使用 64 位浮点运算执行,数值运算符的结果是双精度类型的值。如果另一个操作数不是双精度数,则首先将其加宽 (§5.1.5) 以通过数字提升键入 double(§5.6)。

否则,使用 32 位浮点运算执行运算,数值运算符的结果是浮点类型的值。(如果另一个操作数不是浮点数,则首先通过数字提升将其扩大为浮点类型。

你写道:

为什么编译器不像前面的情况那样强迫我们在这里进行显式类型转换?为什么这里不是编译错误?

因为这不是错误。它不是上一个错误的实例,因为它不涉及小于int的类型。

不要只是制定规则,然后问为什么Java不遵守它们。检查实际规则。

在 java 中,您不能将浮点值声明为 :

float d = 1.2;
float e = 2.3;

因为编译器推断1.22.3为双精度。你必须将它们投射到浮动:

float d = (float) 1.2;
float e = (float) 2.3;

float d = 1.2f;
float e = 2.3f;

最新更新