首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java代码优化,它会优化这个吗?

Java代码优化,它会优化这个吗?
EN

Stack Overflow用户
提问于 2012-11-09 22:01:28
回答 6查看 1.2K关注 0票数 3

使用较新的编译器,我发现自己试图编写更容易阅读的代码,但如果我希望在幕后进行的优化实际上并没有完成,那么可能需要更多的内存。以下面的代码为例,非常简单的情况

代码语言:javascript
复制
while (scanner.hasNextLine() && !result)
{
    String line = scanner.nextLine();
    result = line.indexOf(searchString) >= 0;
}

假设(使用Eclipse Juno,Java 7)生成的字节码与

代码语言:javascript
复制
while (scanner.hasNextLine() && !result)
{
    result = scanner.nextLine().indexOf(searchString) >= 0;
}

前者虽然只有2行代码,但减少了第二行的长度,使它看起来更美观。但是它是否也会导致创建一个不安全的字符串对象呢?希望不是..。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-11-09 22:03:54

您无法转义正在创建的String。将其赋给局部变量在这里是无关紧要的,实际上在字节码级别,这一事实甚至不会被注意到:在该级别,无论有没有显式变量,对结果的引用都必须放在堆栈上,以便传递到链中的下一个方法调用中。

创建不必要的String实例的想法可能源于另一种语言的本能,例如C:赋值String s = ...只将引用复制到唯一的string实例。这是因为所有Java对象都驻留在堆中,所以您总是需要显式地复制一个对象才能真正涉及到另一个实例。例如,如果您编写了String line = new String(scanner.nextLine()),那么确实会创建一个不必要的String实例。

总而言之,您的代码的任何版本都不涉及优化,因此仅根据样式偏好进行选择。

票数 7
EN

Stack Overflow用户

发布于 2012-11-09 22:05:11

一些一般原则:

  • 过早优化在这些次要情况下是没有意义的
  • 大多数时候优化来自于改变算法及其复杂性
  • 当你试图优化一些不是算法的东西时,你永远不会是一个好的编译器
  • 要确定任何优化只有两种方法:查看字节码或基准测试性能,其他一切通常都是推测

<代码>F211

在您的特定情况下:变量声明在优化方面不会改变任何东西,因为在这两种情况下,字符串都是由nextLine()初始化并放在堆栈上的,将其赋给一个变量(该变量在字节码中消失,除非它是实例变量,因为它的用处仅限于您的眼睛)不会改变任何东西。

票数 7
EN

Stack Overflow用户

发布于 2012-11-09 22:21:08

为什么不问一下Java Class File反汇编程序--每个JDK中都包含的javap程序?

具有以下源代码:

代码语言:javascript
复制
public class Foo {

    static void m1(Scanner scanner, String searchString, boolean result) {
        while (scanner.hasNextLine() && !result) {
            String line = scanner.nextLine();
            result = line.indexOf(searchString) >= 0;
        }
    }

    static void m2(Scanner scanner, String searchString, boolean result) {
        while (scanner.hasNextLine() && !result) {
            result = scanner.nextLine().indexOf(searchString) >= 0;
        }
    }
}

运行反汇编程序时:

代码语言:javascript
复制
javap -c Foo.class

您将获得以下字节码:

代码语言:javascript
复制
static void m1(java.util.Scanner, java.lang.String, boolean);
Code:
   0: goto          22
   3: aload_0
   4: invokevirtual #33                 // Method java/util/Scanner.nextLine:()Ljava/lang/String;
   7: astore_3
   8: aload_3
   9: aload_1
  10: invokevirtual #39                 // Method java/lang/String.indexOf:(Ljava/lang/String;)I
  13: iflt          20
  16: iconst_1
  17: goto          21
  20: iconst_0
  21: istore_2
  22: aload_0
  23: invokevirtual #45                 // Method java/util/Scanner.hasNextLine:()Z
  26: ifeq          33
  29: iload_2
  30: ifeq          3
  33: return

static void m2(java.util.Scanner, java.lang.String, boolean);
Code:
   0: goto          20
   3: aload_0
   4: invokevirtual #33                 // Method java/util/Scanner.nextLine:()Ljava/lang/String;
   7: aload_1
   8: invokevirtual #39                 // Method java/lang/String.indexOf:(Ljava/lang/String;)I
  11: iflt          18
  14: iconst_1
  15: goto          19
  18: iconst_0
  19: istore_2
  20: aload_0
  21: invokevirtual #45                 // Method java/util/Scanner.hasNextLine:()Z
  24: ifeq          31
  27: iload_2
  28: ifeq          3
  31: return

如果您比较这两个方法的字节码,您会发现唯一的区别是m1包含这两条额外的指令:

代码语言:javascript
复制
7: astore_3
8: aload_3

这只是将对堆栈顶部对象的引用存储到一个局部变量中,没有其他内容。

编辑:

反汇编程序还可以显示方法的局部变量的数量:

代码语言:javascript
复制
javap -l Foo.class

以下哪项输出:

代码语言:javascript
复制
static void m1(java.util.Scanner, java.lang.String, boolean);
LocalVariableTable:
  Start  Length  Slot  Name   Signature
         0      34     0 scanner   Ljava/util/Scanner;
         0      34     1 searchString   Ljava/lang/String;
         0      34     2 result   Z
         8      14     3  line   Ljava/lang/String;

static void m2(java.util.Scanner, java.lang.String, boolean);
LocalVariableTable:
  Start  Length  Slot  Name   Signature
         0      32     0 scanner   Ljava/util/Scanner;
         0      32     1 searchString   Ljava/lang/String;
         0      32     2 result   Z
}

这基本上证实了上面看到的唯一区别- m1方法只分配了一个局部变量- String line。它不会创建更多的对象,它只会创建一个对一个对象的引用,这个对象是以的方式分配的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13309493

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档