我很好奇为什么必须这样声明float文字:
float f = 0.1f;
代替
float f = 0.1;
为什么默认类型是双精度类型,为什么编译器不能通过查看赋值的左侧来推断它是浮点型的?Google仅提供关于默认值的解释,而不是为什么如此。
为什么默认类型是双精度型?
Java语言的设计者最好问这个问题。他们是唯一知道做出语言设计决定的 真正 原因的人。但我希望推理遵循以下几条原则:
他们需要区分两种类型的文字,因为从数学的角度来看,它们实际上的含义是不同的值。
假设他们将“ float”作为文字的默认值,请考虑以下示例
// (Hypothetical "java" code ... )
double d = 0.1;
double d2 = 0.1d;
在上面,d
和d2
实际上将具有不同的值。在第一种情况下,将低float
精度double
值在分配点转换为较高精度值。但是您无法恢复不存在的精度。
我 认为 ,这两个语句都合法且含义不同的语言设计是一个错误的想法……考虑到第一个语句的实际含义与“自然”含义不同。
通过按照他们的方式来做:
double d = 0.1f;
double d2 = 0.1;
既合法又意味着不同的事情。但是在第一个语句中,程序员的意图很明确,而第二个语句的“自然”含义就是程序员得到的。在这种情况下:
float f = 0.1f;
float f2 = 0.1; // compilation error!
…编译器发现不匹配。
我猜测使用浮点数是例外,而不是现代硬件的规则(使用双精度代替),因此在某些时候可以假设用户在编写时打算使用0.1f
float f = 0.1;
他们已经 可以
做到这一点。但是问题在于提出了一组有效的类型转换规则,这些规则非常简单,您不需要Java学的学位就能真正理解。0.1
在不同的背景下具有不同的意思会令人困惑。考虑一下:
void method(float f) { ... }
void method(double d) { ... }
// Which overload is called in the following?
this.method(1.0);
编程语言设计很棘手。一个领域的改变可能对其他领域产生影响。
更新 以解决@supercat提出的一些问题。
@supercat:鉴于上述重载,将为method(16777217)调用哪个方法?那是最好的选择吗?
我错误地评论了…编译错误。实际上答案是method(float)
。
JLS这样说:
15.12.2.5。选择最具体的方法
如果可以访问多个成员方法并将其应用于方法调用,则必须选择一个成员方法来为运行时方法分派提供描述符。Java编程语言使用选择最具体方法的规则。
…
[符号m1和m2表示适用的方法。]
[如果] m2不是通用的,并且m1和m2可通过 严格 或 宽松调用来应用
,并且其中m1具有形式参数类型S1,…,Sn,而m2具有形式参数类型T1,…,Tn,则该类型对于所有i(1≤i≤n,n =
k),对于参数ei,Si比Ti更具体。…
以上条件是一种方法可能比另一种方法更具体的唯一情况。
如果S <:T(第4.10节),则对于任何表达式,类型S都比类型T更具体。
在这种情况下,我们是在比较method(float)
和method(double)
它们都是适用于呼叫。由于float
<:,double
它
更具体 ,因此method(float)
将被选择。
@supercat:如果例如这样的表达式被
int2 = (int) Math.Round(int1 * 3.5)
或long2 = Math.Round(long1 * 3.5)
替换为int1 = (int) Math.Round(int2 * 3)
或long2 = Math.Round(long1 * 3)
所做的更改看起来无害,但前两个表达式直到
613566756
或为止都是正确的,后两个表达式2573485501354568
在5592405
[上面完全
失败]失败715827882
。
如果您正在谈论做出改变的人,那么是的。
但是,编译器不会在后面进行任何更改。例如,int1 * 3.5
has类型double
(将int
转换为double
),因此最终调用Math.Round(double)
。
通常,Java算术将隐式地将数字类型从“较小”转换为“较大”,而不是从“较大”转换为“较小”。
但是,您仍然需要小心,因为(在您的取整示例中):
整数和浮点数的乘积可能无法以足够的精度表示,因为(例如)a float
的精度比a 的精度低int
。
将结果Math.round(double)
转换为整数类型可导致转换为整数类型的最小/最大值。
但是所有这些都说明了编程语言中的算术支持是棘手的,对于一个新手或粗心的程序员来说,不可避免地会遇到一些麻烦。
问题内容: 当使用Eclipse从表中生成JPA实体时(对于Java EE Developers,它是Juno 4.2),它建议作为我设置为的属性的默认映射类型。 这很烦人,因为我必须将它们全部手动设置。 有人遇到过这种问题并且知道该怎么办吗?这是错误吗?Eclipse Indigo的行为并非如此。 这是来自:(但根据此文件应映射到此文件,必须是错误的文件- 但是如何找出正确的文件?) 我的SQL
我正在标准中寻找对这一事实的正式解释。我找到了3.9.1/9所说的,并试图用该部分给出解释。 第3.9.1/9节,N3797: void类型有一组空值。void类型是不完整的类型,无法完成。它用作不返回值的函数的返回类型。任何表达式都可以显式转换为cv void类型(5.4)。void类型的表达式只能用作表达式语句(6.2)、逗号表达式的操作数(5.18)以及?的第二个或第三个操作数:(5.16)
这样一个看似简单的数字怎么会“太大”而无法在64位内存中表达呢?
问题内容: 目前,我正在研究Sams出版的《 24小时自学Android应用程序开发》一书。我是Java,Android或其他方面的新手。我在ActionScript 3中具有非常扎实的背景,该语言与Java具有足够的相似性,因此该语言本身并不难掌握,但对于本书中某些代码示例的基本原理,我仍然存在一些疑问。例如,以下是第9小时的示例代码随附的函数: 在此函数签名中,作者已将scoreTable参数
问题内容: 为什么即使该类中没有抽象方法,也将类声明为抽象? 问题答案: 这是因为它遵循模板方法设计模式。这些方法具有返回HTTP 405 未实现方法 错误的所有默认行为。如果所有这些方法都是抽象的,那么即使您的业务需求根本不需要它们,也将不得不覆盖所有这些方法。这只会导致样板代码和不确定/不直观的行为。
我正在讨论以下问题:使用Java 8的可选和stream::FlatMap并希望向自定义的添加一个方法,然后检查它是否工作。 更准确地说,我希望向我的添加一个。如果不存在值,则返回一个空流,如果存在,则返回一个包含单个元素的流。 但是,我得出的结论是,声明为final。 为什么会这样呢?有一些类没有声明为final,我个人认为这里没有理由声明final。 作为第二个问题,为什么不是所有的方法都是f