Java8: double, float 字面量,后缀为小写和大写;类型构造函数和类型 boxing/unboxing
Java8: double, float literals with suffix in lowercase and uppercase; type constructor and type boxing/unboxing
我看到 float 和 double 在不同情况下有后缀。
那么浮点数的后缀 F 和 f,双精度数的后缀 D 和 d 有什么区别?
这种行为的任何历史?
还有关于类型构造函数的问题,例如 float 类型(double 的行为相同):
为什么我可以用"new Float(1L);"而不能用"new Float("1L");"但是 "new Float(1.1F);" 和 "new Float("1.1F");" - 工作正常吗?
还有一个关于 autoboxing/unboxing 的问题。
为什么 "float float23 = 1L";工作正常 "Float float12 = "1L";" - 不是吗?
谢谢。
代码示例:
package com.oca;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
class Floats {
Float float11 = 1.1f;
Float float12 = 1.1F;
float float21 = 1.1f;
float float22 = 1.1F;
float float23 = 1L;
Float float31 = new Float(1.1F);
Float float32 = new Float(1.1f);
Float float33 = new Float(1L);
Float float41 = new Float("1.1F");
Float float42 = new Float("1.1f");
}
public class Main {
public static void main(String[] args) {
Floats floats = new Floats();
System.out.println(floats);
}
}
输出:
Floats(float11=1.1, float12=1.1, float21=1.1, float22=1.1, float23=1.0, float31=1.1, float32=1.1, float33=1.0, float41=1.1, float42=1.1)
Float 构造函数需要 float、double 或 string 值(有 3 种不同的构造函数)。您正在尝试传递 long
,这意味着 long
将在调用构造函数之前转换为浮点数。
当您将值作为字符串传递(传递给需要字符串的构造函数)时 - 它期望您传递 float
- 而不是 long
或其他任何东西,这就是为什么您当您尝试调用时,您会得到一个 NumberFormatException
:例如 new Float("1L")
。
旁注:所有这 3 个构造函数将在 Java 9 中生成弃用警告,并声明您应该改用 Float.valueOf()
。
阅读文档。 Float(String) 导致 Float.valueOf(String),最终导致 Double.valueOf(String),描述什么被接受,什么不被接受,它提供文本描述和实际的正则表达式。
它是这样结束的,只允许 f、F、d 和 D:
"[fFdD]?))" +
"[\x00-\x20]*");// Optional trailing "whitespace"
它还指出了 langspec 的相关部分 (3.10.2),如果您对该语言的细节感兴趣,无论如何(langspec 本身)都是建议阅读。
对于赋值部分:您可以将整数类型存储为浮点类型,这就是它起作用的原因。 1L 不是要在运行时解析的文本,而是在编译时评估为数字的文本,可以将其存储在自动转换的 float 中。这同样适用于 Float(1L),因为它甚至在调用构造函数之前就变成了浮点值(可能是双精度值,但我不确定)(Float 只有 float、double 和 String 构造函数)。
装箱-拆箱是个有趣的东西,它根本不自动转换,因此输入必须已经是浮点数了。实际上你可以选择
Float f1=(float)1L;
Float f2=new Float(1L);
如果你绝对想从 1L 得到一个 Float。
编辑:如果您知道答案,请不要问。
如果你打开 Float(String) 的 Java 9 文档,它说
Deprecated. It is rarely appropriate to use this constructor. Use [...] valueOf(String) to convert a string to a Float object.
这导致
[...] To avoid calling this method on an invalid string and having a NumberFormatException be thrown, the documentation for Double.valueOf lists a regular expression which can be used to screen the input.
和 link 导致 Java 9 文档中的描述完全相同,我已经 link 编辑了 Java 7(Java 7在 link 和页面上都可见,并且当我从互联网上 link 编辑它时,它并没有真正说明 Java 版本 "I am on" 的任何信息) ,包含与我在此处引用的完全相同的摘录。
Ps:关于 JDK 源代码,我一个字都没有写,你在原问题中也没有。你问的是为什么,而不是如何。简而言之:因为它是这样指定的。
我看到 float 和 double 在不同情况下有后缀。 那么浮点数的后缀 F 和 f,双精度数的后缀 D 和 d 有什么区别? 这种行为的任何历史?
还有关于类型构造函数的问题,例如 float 类型(double 的行为相同): 为什么我可以用"new Float(1L);"而不能用"new Float("1L");"但是 "new Float(1.1F);" 和 "new Float("1.1F");" - 工作正常吗?
还有一个关于 autoboxing/unboxing 的问题。 为什么 "float float23 = 1L";工作正常 "Float float12 = "1L";" - 不是吗?
谢谢。
代码示例:
package com.oca;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
class Floats {
Float float11 = 1.1f;
Float float12 = 1.1F;
float float21 = 1.1f;
float float22 = 1.1F;
float float23 = 1L;
Float float31 = new Float(1.1F);
Float float32 = new Float(1.1f);
Float float33 = new Float(1L);
Float float41 = new Float("1.1F");
Float float42 = new Float("1.1f");
}
public class Main {
public static void main(String[] args) {
Floats floats = new Floats();
System.out.println(floats);
}
}
输出:
Floats(float11=1.1, float12=1.1, float21=1.1, float22=1.1, float23=1.0, float31=1.1, float32=1.1, float33=1.0, float41=1.1, float42=1.1)
Float 构造函数需要 float、double 或 string 值(有 3 种不同的构造函数)。您正在尝试传递 long
,这意味着 long
将在调用构造函数之前转换为浮点数。
当您将值作为字符串传递(传递给需要字符串的构造函数)时 - 它期望您传递 float
- 而不是 long
或其他任何东西,这就是为什么您当您尝试调用时,您会得到一个 NumberFormatException
:例如 new Float("1L")
。
旁注:所有这 3 个构造函数将在 Java 9 中生成弃用警告,并声明您应该改用 Float.valueOf()
。
阅读文档。 Float(String) 导致 Float.valueOf(String),最终导致 Double.valueOf(String),描述什么被接受,什么不被接受,它提供文本描述和实际的正则表达式。
它是这样结束的,只允许 f、F、d 和 D:
"[fFdD]?))" +
"[\x00-\x20]*");// Optional trailing "whitespace"
它还指出了 langspec 的相关部分 (3.10.2),如果您对该语言的细节感兴趣,无论如何(langspec 本身)都是建议阅读。
对于赋值部分:您可以将整数类型存储为浮点类型,这就是它起作用的原因。 1L 不是要在运行时解析的文本,而是在编译时评估为数字的文本,可以将其存储在自动转换的 float 中。这同样适用于 Float(1L),因为它甚至在调用构造函数之前就变成了浮点值(可能是双精度值,但我不确定)(Float 只有 float、double 和 String 构造函数)。
装箱-拆箱是个有趣的东西,它根本不自动转换,因此输入必须已经是浮点数了。实际上你可以选择
Float f1=(float)1L;
Float f2=new Float(1L);
如果你绝对想从 1L 得到一个 Float。
编辑:如果您知道答案,请不要问。
如果你打开 Float(String) 的 Java 9 文档,它说
Deprecated. It is rarely appropriate to use this constructor. Use [...] valueOf(String) to convert a string to a Float object.
这导致
[...] To avoid calling this method on an invalid string and having a NumberFormatException be thrown, the documentation for Double.valueOf lists a regular expression which can be used to screen the input.
和 link 导致 Java 9 文档中的描述完全相同,我已经 link 编辑了 Java 7(Java 7在 link 和页面上都可见,并且当我从互联网上 link 编辑它时,它并没有真正说明 Java 版本 "I am on" 的任何信息) ,包含与我在此处引用的完全相同的摘录。
Ps:关于 JDK 源代码,我一个字都没有写,你在原问题中也没有。你问的是为什么,而不是如何。简而言之:因为它是这样指定的。