在循环内或循环外声明字符串变量是否有效?

时间:2016-06-15 19:21:33

标签: java performance space-complexity

public void see_following_values_match_with_cache_values(DataTable table){

        String actual = null;
        String expected = null;
        List <Map<String, String>> maps = table.asMaps(String.class, String.class);
        for (Map<String, String> map : maps) {
            actual = map.get(actual);
            expected = map.get(expected);
            ///some processing with actual and expected

        }

    }

public void see_following_values_match_with_cache_values(DataTable table){


        List <Map<String, String>> maps = table.asMaps(String.class, String.class);
        for (Map<String, String> map : maps) {
            String actual = map.get(actual);
            String expected = map.get(expected);
            ///some processing with actual and expected

        }

    }

4 个答案:

答案 0 :(得分:2)

它不会产生任何性能差异(AFAIK),但是对于语义和敏感性,你最好在使用它的范围内声明一个变量。这里你只使用循环中的变量,因此你也应该在循环中声明它们。在循环中声明它们也意味着您不必将它们初始化为null,这有利于安全性和可维护性。

编辑:您正在使用声明的变量作为map.get()方法调用的参数,这在第二个示例中不起作用,因为尚未声明变量并且在第一个例如,它们将为null,这会导致错误,具体取决于地图的实现。

答案 1 :(得分:2)

第二个版本是要走的路。

原因不是效率 - 如果不是零,两种版本的性能差异都可以忽略不计。

更重要的是保持变量范围尽可能小,避免null初始化。

并且不要害怕在循环中声明变量。声明不是在运行时发生的事情,因此不会减慢程序的速度。

编辑:正如其他人注意到的那样,你的两个代码示例都没有意义,第二个代码示例甚至都不会编译。但我想这是因为你已经简化了原来的代码了。

答案 2 :(得分:0)

第二种选择毫无意义 甚至不编译只是因为你不能声明一个对象(字符串&#34;实际&#34;)并使用自己使用的方法进行初始化...

你应该收到如下错误:

  

本地变量actual可能尚未初始化

答案 3 :(得分:0)

您应该使用第二个,因为它更干净且性能相同。您可以查看生成的JIT代码,以查看编译代码的外观。我做了一个简单的测试并使用java vm选项执行它:-Xcomp -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*Main.f1(和第二个方法的Main.f2)打印本机汇编代码并进行比较。这两种方法没有区别。有趣的是,它没有为第一个版本分配(String actual = null)创建任何代码。

Java字节有点不同,这里版本1应该慢一点,因为在循环之前执行空赋值。存在以下字节码指令:

 LINENUMBER 18 L0
 ACONST_NULL
 ASTORE 3
L1
 LINENUMBER 19 L1
 ACONST_NULL
 ASTORE 4
L2
 LINENUMBER 20 L2

要测试的代码:

public static void main(String[] args) {
    List<Map<String, String>> maps = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        f1(maps, "", "");
        f2(maps, "", "");
    }
}

public static void f1(List<Map<String, String>> maps, String expected, String actual) {
    String actual1 = null;
    String expected1 = null;
    for (Map<String, String> map : maps) {
        actual1 = map.get(actual);
        expected1 = map.get(expected);
        x(actual1, expected1);
    }
}
public static void x(String expected, String actual) { } 
public static void f2(List<Map<String, String>> maps, String expected, String actual) {
    for (Map<String, String> map : maps) {
        String actual1 = map.get(actual);
        String expected1 = map.get(expected);
        x(actual1, expected1);
    }
}