Java 声明浮点,为什么默认类型为double?

Java 声明浮点,为什么默认类型为double?,java,Java,我很好奇为什么必须声明浮点文字: float f = 0.1f; 而不是 float f = 0.1; 为什么默认类型是double,为什么编译器不能从赋值的左侧推断它是float?谷歌只给出了默认值是什么的解释,而没有解释为什么会这样 为什么默认类型是double 这是一个最好向Java语言设计者提出的问题。他们是唯一知道做出语言设计决定的真正原因的人。但我认为原因大致如下: 他们需要区分这两种文字,因为它们实际上意味着不同的值。。。从数学的角度来看 假设他们对文本进行了“浮点”默认,考虑

我很好奇为什么必须声明浮点文字:

float f = 0.1f;
而不是

float f = 0.1;
为什么默认类型是double,为什么编译器不能从赋值的左侧推断它是float?谷歌只给出了默认值是什么的解释,而没有解释为什么会这样

为什么默认类型是double

这是一个最好向Java语言设计者提出的问题。他们是唯一知道做出语言设计决定的真正原因的人。但我认为原因大致如下:

他们需要区分这两种文字,因为它们实际上意味着不同的值。。。从数学的角度来看

假设他们对文本进行了“浮点”默认,考虑这个例子

// (Hypothetical "java" code ... )
double d = 0.1;
double d2 = 0.1d;
在上面的例子中,
d
d2
实际上具有不同的值。在第一种情况下,低精度
浮点值
在赋值点转换为高精度
双精度值。但你无法恢复没有的精确度

我认为,如果语言设计中这两种说法都是合法的,并且意思不同,那是个坏主意。。。考虑到第一句话的实际含义不同于“自然”含义

按照他们的方式来做:

double d = 0.1f;
double d2 = 0.1;
两者都是合法的,而且意义不同。但是在第一条语句中,程序员的意图是明确的,而第二条语句的“自然”含义是程序员得到的。在这种情况下:

float f = 0.1f;
float f2 = 0.1;    // compilation error!
。。。编译器将拾取不匹配项


我猜在现代硬件中使用浮点数是个例外,而不是规则(而是使用双精度浮点数),因此在某些情况下,假设用户在编写
float f=0.1时打算使用0.1f是有意义的

他们已经可以这样做了。但问题是出现了一套有效的类型转换规则。。。而且非常简单,您不需要获得Java语言学学位就可以真正理解。让
0.1
在不同的上下文中表示不同的内容会让人困惑。考虑这个问题:

void method(float f) { ... }
void method(double d) { ... }

// Which overload is called in the following?
this.method(1.0);
编程语言设计很棘手。一个领域的变化可能会对其他领域产生影响


更新以解决@supercat提出的一些问题


@supercat:给定上述重载,将为方法(16777217)调用哪个方法?这是最好的选择吗

我错误地评论了。。。编译错误。事实上,答案是
方法(float)

联合联络小组说:

如果多个成员方法可访问且适用于 方法调用时,必须选择一个来提供 运行时方法分派的描述符。Java编程 语言使用的规则是选择最具体的方法

[符号m1和m2表示适用的方法。]

[如果]m2不是通用的,m1和m2通过严格或 松散调用,其中m1具有形式参数类型S1,…,Sn m2有形式参数类型T1,…,Tn,类型Si更多 所有i(1)的参数ei比Ti具体≤ 我≤ n、 n=k)

上述条件是唯一可以使用一种方法的情况 可能比另一个更具体


对于任何表达式,S型都比T型更具体。如果SHa,这只是冰山一角,我的朋友

来自其他语言的程序员当然不介意在文字中添加一点
F
,而不是:

SomeReallyLongClassName x = new SomeReallyLongClassName();
相当多余,对吧

确实,为了获得更多的背景知识,您必须与核心Java开发人员自己交谈。但作为一种纯粹的表面解释,需要理解的一个重要概念是表达式是什么。在Java中(我不是专家,所以对此持保留态度),我相信在编译器级别,您的代码是根据表达式进行分析的;因此:

float f
有一个类型,并且

0.1f
还有一个类型(
float

一般来说,如果要将一个表达式指定给另一个表达式,则类型必须一致。在一些非常特殊的情况下,此规则会被放宽(例如,在引用类型(如
Integer
)中装箱一个类似
int
的基元);但总的来说,这是正确的

在这种情况下,它可能看起来很愚蠢,但这里有一个非常类似的情况,它看起来并不那么愚蠢:

double getDouble() {
    // some logic to return a double
}

void example() {
    float f = getDouble();
}
现在在本例中,我们可以看到编译器发现错误是有意义的。
getDouble
返回的值将具有64位精度,而
f
只能包含32位;因此,如果没有显式强制转换,程序员可能会犯错误

从人类的角度来看,这两种情况明显不同;但我关于表达式的观点是,当代码首先分解为表达式,然后进行分析时,它们是相同的

我确信编译器的作者可以编写一些不那么聪明的逻辑,根据他们被分配到的表达式类型重新解释文本;他们根本没有。与其他功能相比,它可能不值得这么做

对于透视图,很多语言都能够进行类型推断;例如,在C#中,您可以执行以下操作:

var x = new SomeReallyLongClassName();
编译器将根据该赋值推断
x
的类型


不过,对于文字而言,C#在这方面与Java相同。

float
的精度很低,因此更有趣的问题是;为什么会得到支持?很少有情况下,
float
可以使用相同的内存(如果您有数百万个),或者您需要它们来与需要float的对象交换数据

一般来说,使用
double
是一种b