当前位置: 首页 > 知识库问答 >
问题:

java中的字符串池,编译时与运行时字符串计算

祁霖
2023-03-14

我正在学习如何通过OCA考试,并坚持这个java字符串池的概念。

考虑以下几点:

public static void main(String[] args) {

    String s1 = "Hello";                // since s1 and s2 are the same literal at compile-time, therefore they will be string pooled
    String s2 = "Hello";

    String s3 = "Hello".trim();

    StringBuilder sb1 = new StringBuilder("Hello");     // although they are the same string, == only checks for object equality
    StringBuilder sb2 = new StringBuilder("Hello");

    System.out.println(s1 == s2);       // true
    System.out.println(s1 == s3);       // true
    System.out.println(sb1 == sb2);     // false

}

s1s2在字符串中是相同的,在对象中也是相同的,因为它是相同的字符串文本,所以JVM在编译时将字符串池s1s2

现在,s3是在运行时计算的,因此应该返回一个新字符串。因此,s1==s3应该为false,但事实并非如此。为什么?

我的一个理论是trim()方法首先检查是否有空白需要删除,如果没有,则简单返回本身。这可以解释为什么s1==s3,但我不确定。

谢啦

共有3个答案

从焱
2023-03-14

以下是trim()的源代码。如果没有要删除的空白,则返回this。因此,它与您trimed的参考相同。

public String trim() {
    int len = value.length;
    int st = 0;
    char[] val = value;    /* avoid getfield opcode */

    while ((st < len) && (val[st] <= ' ')) {
        st++;
    }
    while ((st < len) && (val[len - 1] <= ' ')) {
        len--;
    }
    return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}
卜季萌
2023-03-14

如果您查看trim()方法的源代码,您会发现在删除空格后,将调用子字符串(start,end)。否则,如果没有空格,则返回相同的实例this

public String trim() {
   int len = value.length;
   int st = 0;
   char[] val = value;    /* avoid getfield opcode */

   while ((st < len) && (val[st] <= ' ')) {
       st++;
   }
   while ((st < len) && (val[len - 1] <= ' ')) {
       len--;
   }
   return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
 }

这里st是删除空白后的开始索引,len是新的长度。

现在,如果字符串前面或后面有空格:

String s1 = "hello "; //<-- whietspace at the end
System.out.println(s1.trim() == "hello");

trim()方法调用substring()时,输出为false。如果beginIndexendIndex不相同,子字符串将返回一个新的字符串实例:

return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);

因此,在删除空格(如果有)后,beginIndexendIndex将明显更改,并返回一个new String()实例。

朱硕
2023-03-14

你是正确的。如果trim()方法不更改值,则将返回原始实例。如果所有的Hello都改为Hello,s3将不等于s1,因为trim()将删除空白并返回一个新的字符串实例。

 类似资料:
  • 问题内容: 当我使用定义变量时,该字符串不会添加到字符串池中,对吗? 现在,当我定义另一个而不是时,我将其定义为突然。(或我的大学老师说)。这是为什么?是什么使这个字符串突然变成字符串池字符串? 问题答案: 当我用new定义一个StringBuffer变量时,该字符串没有添加到字符串池中,对吗? 创建a 根本不会创建a 。 现在,当我定义另一个StringBuffer而不是new时,我突然将其定义

  • 我的问题很简单。有什么区别-

  • 看完这些讨论——问题1,问题2,文章 我对Java字符串常量池有以下理解(如果我错了,请纠正我): 编译源代码时,编译器会在我们的程序中查找所有字符串文字(放在双引号中的那些),并在堆区域中创建不同的(无重复)对象,并在称为字符串常量池(方法区域内的区域)的特殊内存区域中维护它们的引用。任何其他字符串对象都是在运行时创建的。 假设我们的代码有以下语句: 当编译上述代码时, 第1行:在堆中创建一个S

  • 问题内容: 我尝试在Android上的Janino上使用这些东西,并得出结论说,它们根本无法在Dalvik VM中运行。 所以我只想问一个简单的问题:在 Android上 ,是否有可能在运行时编译包含代码的字符串以供应用程序使用。如果是这样,是否有让我这样做的库和/或您可以共享一个代码示例来做到这一点? 对于 (一个非常简单的) 示例,如果我有一个包含以下内容的String对象: 作为一根巨大的弦

  • 对性能是否有影响? 不同Java版本的行为是否有差异?

  • 问题内容: 假设字符串a和b: 在幕后,他们是同一回事吗? 这里将concat反编译为参考。我也希望能够反编译该+运算符,以查看其作用。 问题答案: 不,不是。 首先,语义上略有不同。如果a是null,则抛出一个,但a+=b将把原来的值a就好像它是null。此外,该方法仅接受值,而+操作员会将参数无提示地转换为String(使用对象的方法)。因此,该concat()方法在接受方面更加严格。 要深入