缩小类型转换:为什么允许将int赋值给声明中的字节?

对于中级Java程序员来说,这听起来太微不足道了。 但在我审查Java基础知识的过程中,发现了一个问题:

为什么缩小转换范围如下:

byte b = 13; 

将被允许

 int i = 13; byte b = i; 

会被编译器抱怨吗?

因为byte b = 13 ; 是一个常数的赋值。 它的值在编译时是已知的,因此如果常量值的赋值会导致溢出,编译器可以/应该/将会发出声音(尝试byte b = 123456789 ;看看会发生什么。)

一旦将它分配给变量,就会分配一个表达式的值,虽然它可能是不变的,但编译器并不知道。 该表达式可能导致溢出,因此编译器发出呜呜声。

从这里 :

当表达式的值被赋值(第15.26节)给变量时,就会发生赋值转换:必须将表达式的类型转换为变量的类型。 赋值上下文允许使用标识转换(第5.1.1节),扩展基元转换(第5.1.2节)或扩展引用转换(第5.1.4节)。 此外,如果满足以下所有条件,则可以使用缩小的基元转换:

  • 表达式是byte,short,char或int类型的常量表达式。
  • 变量的类型是byte,short或char。
  • 表达式的值(在编译时已知,因为它是常量表达式)可以在变量的类型中表示。

在您的示例中,满足所有三个条件,因此允许缩小转换。

PS我知道我引用的来源是旧的,但语言的这个方面自那以后没有改变。

因为字面数字没有类型。

一旦你给它一个类型,它必须被铸造到另一个:

 int i = 13; byte b = (byte) i; 

一个字节有8位。 一个int,32位,它是一个带符号的数字。

从具有较小范围的数字(如int到long或long到float)的转换称为加宽。 扩大转换的目标是在保持尽可能多的精度的同时不改变数字的大小。 例如,将int 2147483647转换为float会产生2.14748365e9或2,147,483,650。 差异通常很小,但可能很重要。

相反,有可能丢失有关数字大小信息的转换(如long to int或double to long)称为narrowing。 随着转换范围的缩小,某些信息可能会丢失,但只要有可能就会找到最近的表示。 例如,将float 3.0e19转换为long会产生-9223372036854775807,这是一个非常不同的数字。