为什么默认类型是 double?
这个问题最好问 Java 语言的设计者。他们是唯一知道真相的人real做出该语言设计决定的原因。但我预计其推理大致如下:
他们需要区分这两种类型的文字,因为从数学角度来看,它们实际上意味着不同的值。
假设他们将“float”设置为文字的默认值,请考虑这个示例
// (Hypothetical "java" code ... )
double d = 0.1;
double d2 = 0.1d;
上式中,d
and d2
实际上会有不同的值。第一种情况,精度较低float
值转换为更高的精度double
赋值时的值。但你无法恢复不存在的精度。
I posit这两个语句都是合法的,并且含义不同的语言设计是一个坏主意……考虑到第一个语句的实际含义与“自然”含义不同。
按照他们的做法:
double d = 0.1f;
double d2 = 0.1;
都是合法的,但含义又不同。但在第一个语句中,程序员的意图是明确的,而第二个语句的“自然”含义是程序员得到的。在这种情况下:
float f = 0.1f;
float f2 = 0.1; // compilation error!
...编译器发现不匹配。
我猜测使用浮点数是例外,而不是现代硬件的规则(使用双精度数),因此在某些时候,假设用户在写入时打算使用 0.1f 是有意义的float f = 0.1;
They could已经这样做了。但问题是要提出一组有效的类型转换规则……并且足够简单,您不需要 Java 学学位就可以真正理解。拥有0.1
在不同的上下文中表示不同的事物会令人困惑。并考虑一下:
void method(float f) { ... }
void method(double d) { ... }
// Which overload is called in the following?
this.method(1.0);
编程语言的设计很棘手。一个领域的变化可能会对其他领域产生影响。
UPDATE解决@supercat提出的一些问题。
@supercat:考虑到上述重载,方法(16777217)将调用哪个方法?这是最好的选择吗?
我错误地评论了...编译错误。其实答案是method(float)
.
JLS 是这样说的:
15.12.2.5。选择最具体的方法
如果多个成员方法既可访问又适用于一个
方法调用时,需要选择一个来提供
运行时方法调度的描述符。 Java编程
语言使用选择最具体方法的规则。
...
[符号m1和m2表示适用的方法。]
[如果] m2 不是通用的,并且 m1 和 m2 适用于strict or
松散调用,其中 m1 具有形式参数类型 S1, ..., Sn
m2 具有形参类型 T1, ..., Tn,类型 Si 更多
对于所有 i (1 ≤ i ≤ n, n = k),参数 ei 比 Ti 更具体。
...
上述条件是一种方法的唯一情况
可能比另一个更具体。
对于任何表达式,如果 S <: t s>
在这种情况下,我们正在比较method(float)
and method(double)
这两者都适用于呼叫。自从float
<: double
, it is 更具体,因此method(float)
将被选中。
@supercat:这种行为可能会导致问题,例如一种表达
喜欢int2 = (int) Math.Round(int1 * 3.5)
or long2 = Math.Round(long1 * 3.5)
被替换为int1 = (int) Math.Round(int2 * 3)
or long2 = Math.Round(long1 * 3)
这种变化看起来无害,但前两个表达式是
纠正至613566756
or 2573485501354568
和后两个
以上失败5592405
[上面最后一个完全是假的715827882
].
如果你谈论的是一个做出这种改变的人……嗯,是的。
但是,编译器不会在您背后进行更改。例如,int1 * 3.5
有类型double
(the int
被转换为double
),所以你最终调用Math.Round(double)
.
作为一般规则,Java 算术会隐式地从“较小”数字类型转换为“较大”数字类型,但不会从“较大”数字类型隐式转换为“较小”数字类型。
但是,您仍然需要小心,因为(在您的舍入示例中):
但所有这些都表明,编程语言中的算术支持是很棘手的,对于新的或粗心的程序员来说,不可避免地会遇到一些问题。