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 源代码,我一个字都没有写,你在原问题中也没有。你问的是为什么,而不是如何。简而言之:因为它是这样指定的。