在Java中创建字符串的时间

在Java中创建字符串的时间,java,string,Java,String,我正在为J2ME设备编写一个应用程序,非常关心不必要的字符串创建。 由于使用字符串是内置的,也就是说,没有必要显式地创建它们,我不确定我是否理解正确 例如,返回一个字符串(只需使用双引号)会在返回字符串时创建该字符串,即,如果有多个返回语句返回不同的字符串,则只会创建其中一个。是这样吗 另外,当使用字符串打印带有异常的消息时,如果没有抛出异常,则永远不会创建这些字符串,对吗 很抱歉为这样一个新手问题打扰您。字符串(和其他对象)只有在您调用它们时才会创建 因此,要回答您的问题: 是的,只会创建返回

我正在为J2ME设备编写一个应用程序,非常关心不必要的字符串创建。 由于使用字符串是内置的,也就是说,没有必要显式地创建它们,我不确定我是否理解正确

例如,返回一个字符串(只需使用双引号)会在返回字符串时创建该字符串,即,如果有多个返回语句返回不同的字符串,则只会创建其中一个。是这样吗

另外,当使用字符串打印带有异常的消息时,如果没有抛出异常,则永远不会创建这些字符串,对吗

很抱歉为这样一个新手问题打扰您。

字符串(和其他对象)只有在您调用它们时才会创建

因此,要回答您的问题:

  • 是的,只会创建返回的字符串
  • 是的,只有当抛出异常时,才会创建此字符串

  • 到目前为止,我对你收到的答案一点也不确定。如果您只是返回一个字符串文本,例如

    return "foo";
    
    然后这些值被嵌入到类文件中。JVM确保只创建了该字符串的一个实例(从字面意义上讲),但我认为不能保证它在加载类本身时不会为类中的所有常量创建字符串

    再说一次,因为字符串只创建一次(每个字符串常量),所以不太可能出现问题

    现在,如果您的代码实际上更像这样:

    return "foo" + new Date();
    
    然后,这就是动态创建一个字符串——但只有在实际命中return语句时才会创建它。

    是。如果通过调用构造函数或(对于字符串)计算文本来创建实例的表达式未执行,则不会创建任何内容

    此外,编译器还进行了一些优化。基于字符串文字的字符串对象将只创建一次,之后将被拘留。就像这里:

    public String getHello() {
      return "Hello";  
    }
    
    public void test() {
      String s = getHello();  // String object created
      String t = getHello();  // no new String object created
    }
    


    政府有不同的“观点”:

    在以下情况下,可以隐式创建新的类实例:

    • 加载包含字符串文字的类或接口可能会创建一个新的字符串对象(§2.4.8)来表示该文字。如果已创建字符串对象来表示该文本的上一次出现,或者已在表示与该文本相同的字符串的字符串对象上调用String.intern方法,则可能不会发生这种情况
    所以上面的例子是不正确的(我每天都在学习新的东西)。VM在类加载期间检查是否必须创建“Hello”(如果还不存在,将创建一个字符串实例)

    所以现在我的理解是,VM为每个唯一的字符串文本(在字节码级别!)创建一个字符串实例,而不管它是否被使用


    (在字节码级别上,因为编译器可能会将字符串文本的串联优化为一个文本,例如:表达式
    “一”+“二”
    将被编译为
    “一个两个”

    答案比其他一些答案所建议的要复杂一些

    • 当类被加载时,与源代码中的字符串文本相对应的字符串值将被创建一次。此外,这些字符串会自动“插入”,这意味着,如果同一个文本出现在任何类中的多个位置,则只会保留该字符串的一个副本。(如果创建了任何其他副本,将对其进行垃圾收集。)

    • 当应用程序调用
      新字符串(…)
      时,当它计算字符串连接表达式(即
      +
      运算符)时,或者当它调用在引擎盖下创建字符串的许多库方法之一时,将创建一个新字符串

    因此,要回答您的问题:

    1-以下内容实际上根本不会创建字符串。而是返回加载类时创建的字符串:

            return "some string";
    
    2-以下内容将创建两个字符串。首先,它将调用someObject.toString(),然后将其与文本连接起来,以生成另一个字符串

            return "The answer is :" + someObject;
    
    3-以下内容不会创建字符串;见1

            throw new Exception("Some message");
    
    4-执行时,以下命令将创建两个字符串:;见第2条

            throw new Exception(someObject + "is wrong");
    

    (实际上,3和4掩盖了这样一个事实,即创建异常会导致捕获当前线程调用堆栈的详细信息,这些详细信息包括每个帧的方法名、类名和文件名。表示这些内容的字符串实际创建时没有指定,也没有指定它们是否被占用。因此,有可能创建异常对象的行为会触发许多字符串的创建。)

    这里的主要概念是堆分配(您所说的创建)对于任何字符串,或者更一般地说,在逻辑流使解释器执行该行编译代码之前,任何对象都不会发生。

    它在'String#intern'上说:所有文本字符串和字符串值常量表达式都被intern.。因此,基于文本的字符串只创建一次,至少在第一次exp我怀疑类加载器是否会查看常量池并主动为所有文本创建字符串实例。但你永远不知道;)@Andreas\u D:如果这样做,生活会轻松得多。谢谢Jon!你总是很务实,乐于助人!Andreas,你能解释一下你所说的“我怀疑类加载器会查看常量池并主动为所有文本创建字符串实例”是什么意思吗?@Jon-刚刚查看了,令我惊讶和你放心的是:加载包含字符串文本的类或接口可能会创建一个新的字符串对象(§2.4.8)表示该文字。如果已经创建了字符串对象,则可能不会发生这种情况[…]非常感谢所有的bo