首页 > 解决方案 > Java: 字符串 s = "" + myInteger; - 如何指导远离这种模式?

问题描述

我正在寻找可以让我展示 Java 中的光芒的论点

int myInt = 1;
...
String s = "" + myInt;

确实是一个完全正确且可编译的实现,String.valueOf(myInt)但这样做“不是它在 Java 中完成的规范方式”。

它看起来更好”是我得到的论点,并且“我希望编译器能够处理它”。

我尝试发送一个链接到https://godbolt.org/(编译器资源管理器),它显示了生成的 JVM 指令;争论“规范方式”或“最少惊喜”或“实现模式”或“可维护性”不会有效。

我迷路了 - 有什么建议吗?

标签: java

解决方案


在风格问题上(这是一个风格问题;运行一个微基准来证明和量化运行时性能差异)我会遵循以下规则:

  1. 如果您的项目有一个推荐一个特定选择的样式指南,请遵循样式指南
  2. 如果它的现有代码始终遵循一个选择,请遵循该选择
  3. 如果两者都不适用,请做出选择并坚持下去

JDK 的源代码是免费提供的。在 Java 8 中,我统计了 276 个文件,其中出现了一次或多次"" +(在我查看的文件中,数字通常紧随其后)。当然,有超过 3k 个文件调用了.toString,而我根本没有看过.valueOf,所以这几乎没有定论。因此,"" + 在编写良好的 Java 代码中使用数字到字符串的转换似乎并不罕见或不受欢迎。

并不是说优秀的 Java 开发人员会在循环中连接字符串;频繁使用似乎是为异常生成错误消息。

Oracle古老的 Java 风格指南以及GoogleSpring的最新指南似乎对此事没有发言权。因此,我觉得没有正确的答案,如果在一个项目中一起编码,并且您对此足够关心,则应该应用规则 3:消除折衷,将其记录在项目的样式指南中,并坚持下去。

就个人而言,我发现"" + o比许多替代方案更容易阅读,因为toString()无论类型如何o(甚至何时o为空),调用它的语法糖都有效。


实际上,我在 JDK 11 上使用caliper进行了尝试结果显示,在通过以下 3 种方法执行 1k 整数到字符串的转换时,运行时差异最小,并且没有内存或对象计数差异

 t (ms)   method

 12,30    "" + j
 12,57    Integer.toString(j)
 12.58    String.valueOf(j)

重现代码:

package org.example;

import com.google.caliper.BeforeExperiment;
import com.google.caliper.Benchmark;
import com.google.caliper.Param;
import com.google.caliper.runner.CaliperMain;

public class Main {

    @Param({"10", "100", "1000"})
    int size;

    private String[] output;

    @BeforeExperiment
    void setUp() {
        output = new String[size];
    }

    @Benchmark void quote(int reps) {
        for (int i = 0; i < reps; i++) {
            for (int j = 0; j < size; j++) {
                output[j] = "" + j;
            }
        }
    }

    @Benchmark void toString(int reps) {
        for (int i = 0; i < reps; i++) {
            for (int j = 0; j < size; j++) {
                output[j] = Integer.toString(j);
            }
        }
    }

    @Benchmark void valueOf(int reps) {
        for (int i = 0; i < reps; i++) {
            for (int j = 0; j < size; j++) {
                output[j] = String.valueOf(j);
            }
        }
    }

    public static void main(String[] args) {
        CaliperMain.main(Main.class, args);
    }
}

推荐阅读