请看下面三行代码。
float f = 1;
float g = 1.1;
float h = 1.1f;
第二行有编译错误,而其他行没有编译错误。第一行在没有后缀f的情况下工作正常,第三行在有后缀f的情况下工作。为什么会这样?
Java中的浮点字面量默认为double
值。
JLS 3.10.2 Floating-Point Literals
如果浮点文字后缀有ASCII字母
float
或F
,则其类型为f
;否则,其类型为double
,并且可以选择在其后缀有ASCII字母D
或d
。
如果不进行显式缩小转换,则无法将double
值分配给float
。因此,您有两个选择:
f
或F
表示float
值(float)
后者的一个例子是:
double d = 1.1;
float f = (float) d; // compiles fine!
编译的原因:
float f = 1;
是因为从int
到float
的加宽转换可以在分配的上下文中隐式完成。
JLS 5.2 Assignment Conversion
赋值转换在将表达式的值分配给变量时发生:表达式的类型必须转换为变量的类型。分配上下文允许使用以下之一:
- 扩大原始转换(§5.1.2)
- [...]
JLS 5.1.2 Widening Primitive Conversion
以下针对基本类型的19种特定转换称为扩展基本类型转换:
- [
int
至long
,float
或double
- [...]
如上所述,D
还有d
或double
后缀。考虑以下示例:
static void f(int i) {
System.out.println("(int)");
}
static void f(double d) {
System.out.println("(double)");
}
//...
f(1); // prints "(int)"
f(1D); // prints "(double)"
long
文字还有一个后缀,即L
或l
(小写字母)。 强烈建议使用大写变体。
JLS 3.10.1 Integer Literals
如果整数文字以ASCII字母
long
或L
(l
)结尾,则其类型为ell
;否则为int
类型。后缀L
是首选,因为字母l
(ell
)通常很难与数字1
(one
)区分。
您正在将double
值分配给float
变量。编译器假定1.1
本身(末尾未附加f
)为double
类型。编译器不喜欢进行隐式向下转换,因为那里可能会失去精度。
第一行自动将int
强制转换为float
(确定)。
第二行由于精度损失而无法将double
强制转换为float
。您可以进行显式转换:
float g = (float) 1.1;
第三行不需要修改。
在Java中,每个浮点数(带小数点的任何数字)默认为double
,比float
更精确。默认情况下,由于精度损失,Java不允许您将double
转换为float
。
您仍然可以通过强制转换将double
分配给float
:
float g = (float) 1.1;