Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java编译器能有效地处理内联字符串吗?_Java_String_Optimization_Compiler Construction - Fatal编程技术网

Java编译器能有效地处理内联字符串吗?

Java编译器能有效地处理内联字符串吗?,java,string,optimization,compiler-construction,Java,String,Optimization,Compiler Construction,一, 二, Java编译器会以相同的方式处理这两个(1和2)吗 仅供参考:我指的是运行时内存利用率以及代码执行时间。e、 g.第一种情况是否会在堆栈加载变量memFriendly时花费更多时间?在这种情况下,编译器将处理两种情况 每当在编译时定义字符串时,Java都会优化字符串的存储 如果字符串是在运行时定义的,Java无法进行同样的优化。您的代码是等效的,因为编译器会自动插入字符串文本 如果您真的关心字符串性能,并且将反复使用相同的字符串,那么您应该看看String类上的intern方法 以下

一,

二,

Java编译器会以相同的方式处理这两个(1和2)吗


仅供参考:我指的是运行时内存利用率以及代码执行时间。e、 g.第一种情况是否会在堆栈加载变量memFriendly时花费更多时间?

在这种情况下,编译器将处理两种情况

每当在编译时定义字符串时,Java都会优化字符串的存储


如果字符串是在运行时定义的,Java无法进行同样的优化。

您的代码是等效的,因为编译器会自动插入字符串文本

如果您真的关心字符串性能,并且将反复使用相同的字符串,那么您应该看看String类上的intern方法

以下章节介绍了这一点:

每个字符串文字都是一个引用 (§4.3)到实例(§4.3.1,§12.5) 类别字符串(§4.3.3)。一串 对象具有常量值。一串 文字或更一般的字符串 这是常数的值 表达式(§15.28)-是“实习”的,因此 要共享唯一实例,请使用 方法String.intern

您也可以使用该工具亲自查看

对于此代码:

System.out.println("Efficiently stored String");
public static void main(String[] args) {
    System.out.println("Hello world!");

    String hola = "Hola, mundo!";
    System.out.println(hola);
}
javap提供了以下内容:

System.out.println("Efficiently stored String");
final String memFriendly = "Efficiently stored String";
System.out.println(memFriendly);
以下是javap显示的代码反汇编:

System.out.println("Efficiently stored String");
public static void main(String[] args) {
    System.out.println("Hello world!");

    String hola = "Hola, mundo!";
    System.out.println(hola);
}
看起来第二个字符串正在存储,而第一个字符串只是直接传递给方法

这是用Eclipse的编译器构建的,这可以解释我的答案和McDowell的答案之间的差异

更新:如果将
hola
声明为
final
(结果为no
aload\u 1
,如果我正确阅读此内容,则表示此字符串已存储并内联,如您所料):


我也这么认为,但我找不到一个具体的参考,我的意思是理论上的。谢谢,这是一篇有参考资料的好文章,但不是我要找的:我找不到任何特定的文章或规格,对不起。不,不,不!出于“性能原因”(这个词已经几乎让我呕吐)随意实习字符串是错误的。除非你在做大容量的字符串处理,否则它只会给你带来麻烦。除了厌恶之外,你还有什么东西来支持你毫无根据的主张吗?我给出了使用intern的一个很好的理由,在这种情况下,同一组字符串需要反复使用。为什么每次都要创建新的?intern唯一的缺点是,被intern的字符串永远不能被垃圾收集。我想这就是你所抱怨的。但是如果你想在程序的整个生命周期中重复使用相同的字符串,那么对它们进行intern与每次创建新字符串是有意义的。看看这个,它给出了intern的优缺点。“为什么不调用
intern()
”这一问题的答案就在您提供的“Java词汇表”文章中给出了——编译时出现的所有
String
文本都会自动插入。仔细想想。您有一个在编译时不存在的字符串,但它会根据一些运行时信息(用户输入、控制台参数等)而变化。如果只创建一次字符串并传递它,
intern()
不会给您带来任何好处。如果您重复创建相同的运行时字符串,那么您可能违反了DRY,最好的优化可能是消除重复。这很正常,因为在McDowell中,两个字符串具有不同的文本,而它们是相同的。哇!谢谢你挖这个。我的用例是,我的代码中的字符串(将被多次调用)只使用了一次,想想logger.info(“logthis”);现在让这个字符串成为一个静态的最终会提高性能吗?谢谢你挖掘这个。我的用例是,我的代码中的字符串(将被多次调用)只使用了一次,想想logger.info(“logthis”);现在,将此字符串设置为静态final将提高性能吗?使用对静态final字段的引用不太可能与内联文本有任何性能差异。由于Hotspot在运行时执行了如此多的优化,所以判断是否存在可测量差异的唯一方法就是测量它。关于微基准的一个相关问题:谢谢。我还使用了javap,并将静态final的输出与内联版本进行了比较。两者完全相同。关于Hotspot的运行时优化,您是对的,这正是让我困惑的地方。首先,我如何保证一种方法更好,以便我可以将其用作最佳实践。@Monis:如果您调用
logger.info(“记录此”)在应用程序中,进行方法调用、方法调用,特别是将输出记录到磁盘所花费的时间将远远超过字符串存储方式之间的速度差异。@Grant k,如果字符串很长怎么办?
0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3:   ldc     #22; //String Hello world!
5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8:   ldc     #30; //String Hola, mundo!
10:  astore_1
11:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
14:  aload_1
15:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
18:  return
0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3:   ldc     #22; //String Hello world!
5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8:   ldc     #30; //String Hola, mundo!
10:  astore_1
11:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
14:  ldc     #30; //String Hola, mundo!
16:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
19:  return