泳池啥时候换?

Posted

技术标签:

【中文标题】泳池啥时候换?【英文标题】:When does the pool change?泳池什么时候换? 【发布时间】:2013-01-05 00:55:57 【问题描述】:

我有两个问题:

public static void main(String[] args) 
  String s1 = "bla";
  String s2 = "b" +"l" + "a";
  String s3 = "b".concat("l").concat("a");

  if(s1 == s2) 
        System.out.println("Equal");
  else
        System.out.println("Not equal");
  if(s1 == s3) 
        System.out.println("Equal");
  else
        System.out.println("Not equal");

为什么s1s2 指向同一个对象,而s1s3 却没有? (没有使用new关键字)。

如果我从用户那里得到一个字符串并将这些行添加到上面的代码中:

BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
String name=in.readLine();
if(name.equals("test"))
    s1 = s1 + "xyz";

如果用户输入xyz,程序将打印Not equal,当用户输入另一个东西时,程序输出Equal。这是否意味着池会随着整个程序的执行而改变?优化器是否在编译时工作并runtime中继续工作?

【问题讨论】:

【参考方案1】:

为什么 s1 和 s2 指向同一个对象,而 s1 和 s3 不是吗? (没有使用 new 关键字)。

由于Java中的StringImmutable,所以字符串类的任何方法都会返回一个新的String对象(不过也有一些例外——一个是substring方法)。因此,concat 方法创建了一个新字符串,该字符串进入 Heap,并且不会添加到常量池中。

s1s2 而言,这两个字符串在编译 时都是已知的,因此它们是相同的字符串文字。

注意第二个字符串中的连接操作:-

String s2 = "b" +"l" + "a";

在编译时求值,已知结果与第一个字符串相同,并在常量池中输入一个条目。

【讨论】:

【参考方案2】:

有时(当编译器很明显 String 的值在运行时是什么时)编译器使用字符串池,在其他情况下则不使用。

其实你的代码不应该依赖于使用或不使用池的事实。

你不能总是运行 main,所以如果你想看看你的 String 是否是从池中使用的,你可以用 javap 反编译代码,清单相对不言自明。

【讨论】:

【参考方案3】:

为什么 s1 和 s2 指向同一个对象,而 s1 和 s3 却没有? (没有使用 new 关键字)。

因为连接发生在编译时,因此完成的字符串会像第一个示例一样进入常量池。这是编译器“已知”的特殊情况。这实际上意味着长字符串,以这种方式连接多行,仍然可以获得与简单字符串常量相同的性能改进。

在第二个示例中,您在运行时执行计算,因此它不会成为常量池的一部分。

但是请注意,在 JLS 中,字符串常量池中可以和不可以进入的细节故意保持模糊,因此不同的实现可能会以不同的方式进行优化。它指定了一些关于必须进入其中的规则,但不要依赖这种行为在实现之间保持一致。

【讨论】:

以上是关于泳池啥时候换?的主要内容,如果未能解决你的问题,请参考以下文章

Noi2017 泳池

内存竞技场和内存池有啥区别?

unity 啥时候用到unity 二维动画混合树

大揭秘:游泳池防水材料,泳池胶膜

数据结构与算法之深入解析“水位上升的泳池中游泳”的求解思路与算法示例

家里网络先换掉线 一天掉20次以上 过个几分钟又自动重连了 宽带拨号有时候会说651错误 调制解调器啥的