哪种方式是最优化的?

6

也许这是一个简单的问题,但我很困惑

哪段代码是优化的?我应该使用哪个?

内部流程有什么区别?

String str = editText.getText().toString();     
str =str.trim().toLowerCase();
textView.setText(str);

textView.setText(editText.getText().toString().trim().toLowerCase());

6
这是一种微小到不重要的超微优化。使用你认为更易读的代码。(虽然我并不是那个给你点踩的人) - JB Nizet
2
我 (代词) - Sa Dec
6个回答

4
不要认为将所有内容放在一行中比将语句分为多行更好。通常情况下,Java编译器足够聪明以在这两种情况下生成完全相同的字节码。现代编译器进行了许多微观优化。
您可以通过编译它们,然后使用命令javap -c反编译字节码来检查是否有区别。
编辑:
我刚进行了测试,以下是结果:
String str = editText.getText().toString();     
str = str.trim().toLowerCase();
textView.setText(str);

编译结果:

       0: aload_0       
       1: getfield      #7                  // Field textView:Landroid/widget/TextView;
       4: aload_0       
       5: getfield      #4                  // Field editText:Landroid/widget/EditText;
       8: invokevirtual #8                  // Method android/widget/EditText.getText:()Landroid/text/Editable;
      11: invokevirtual #9                  // Method java/lang/Object.toString:()Ljava/lang/String;
      14: invokevirtual #10                 // Method java/lang/String.trim:()Ljava/lang/String;
      17: invokevirtual #11                 // Method java/lang/String.toLowerCase:()Ljava/lang/String;
      20: invokevirtual #12                 // Method android/widget/TextView.setText:(Ljava/lang/CharSequence;)V
      23: return        

还有第二个:

textView.setText(editText.getText().toString().trim().toLowerCase());

得到以下结果:

       0: aload_0       
       1: getfield      #7                  // Field textView:Landroid/widget/TextView;
       4: aload_0       
       5: getfield      #4                  // Field editText:Landroid/widget/EditText;
       8: invokevirtual #8                  // Method android/widget/EditText.getText:()Landroid/text/Editable;
      11: invokevirtual #9                  // Method java/lang/Object.toString:()Ljava/lang/String;
      14: invokevirtual #10                 // Method java/lang/String.trim:()Ljava/lang/String;
      17: invokevirtual #11                 // Method java/lang/String.toLowerCase:()Ljava/lang/String;
      20: invokevirtual #12                 // Method android/widget/TextView.setText:(Ljava/lang/CharSequence;)V
      23: return        

正如您所见,我猜对了,它们是相同的。Java编译器优化了第一个示例并完全删除了变量,因为它是无用的。

因此,结论是您应该使用您认为更易读的代码。


2
[1] 创建字符串String str会占用设备内存,但它可以在稍后使用;因此,如果您稍后需要它,则进行了优化。
[2] 不使用内存,因此非常优化,但是如果您稍后需要此字符串,则必须每次获取它,这将导致处理过程需要更多的机器周期,在这种情况下,第二个选项较少优化。

@Swan 对不起,你能解释一下吗?我没听懂你的意思! - Chintan Raghwani
区别仅在于对象引用。对象引用存在于线程的堆栈上,而不是堆上。线程已经分配了一个固定的堆栈。我真的认为你不能说它消耗更多的内存。 - Sean Owen

1
在这里,首先将输出存储在字符串变量中,因此它会占用一定的空间,然后将其转换为小写并设置到文本视图中。而在第二个选项中,您可以直接设置到文本视图中,不必将其存储到任何变量中。所以如果您不想在进一步的编码中使用它,那么第二个选项是更可取的。

1

在第一个中,您使用额外的变量会比第二个使用更多的内存。就内存效率而言,第二个有优势。


两者分配完全相同的对象。 - Sean Owen

-1

嗯,第二种虽然具有更高的内存效率优势,但不太易读。不为对象分配引用变量使它们更适合进行垃圾回收。

但毫无疑问,您应该首选可读性而非这些小优化。


我没有给自己投反对票,但是回答一下:JVM 可以判断出在方法中后续不再使用的本地引用,并使其所指对象成为垃圾可回收。 - Sean Owen
嗯...我认为只有当本地变量从堆栈中弹出时,对象才能被垃圾收集。很可能您链接了方法调用并且引用已经存在,这样会延迟您的对象进行垃圾回收。 - Ahmad
垃圾收集器可以在堆栈帧被丢弃之前知道一个对象引用未使用。http://nerds-central.blogspot.co.uk/2012/04/deep-dive-java-performance-and-escape.html - Sean Owen
我不需要为我的投票反对进行“辩解”,但我可以“解释”一下:你是错的。 - Matsemann

-2

首先,你使用了一个额外的变量,这比第二种方法占用更多的内存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接