当前位置: 首页 > 面试题库 >

用Java如何完成最终字符串的连接?

夏侯野
2023-03-14
问题内容

当我编译此代码片段时。

public class InternTest {
    public static void main(String...strings ){
        final String str1="str";
        final String str2="ing";
        String str= str1+str2;

    }
}

产生以下字节码

public static void main(java.lang.String...);
   flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
   Code:
     stack=1, locals=4, args_size=1
        0: ldc           #16                 // String str
        2: astore_1
        3: ldc           #18                 // String ing
        5: astore_2
        6: ldc           #20                 // String string
        8: astore_3
        9: return

因此常量池中已经存在字符串文字“ string”,该常量池6: ldc #20 // String string在此行被压入堆栈。

引用JSL

从JLS§4.12.4-最终变量:

基本类型或String类型的变量是最终变量,并使用编译时常量表达式(第15.28节)进行了初始化,该变量称为常量变量。

同样来自JLS§15.28-ConstantExpression:

使用String#intern()方法,始终将String类型的编译时常量表达式“ interned”,以便共享唯一的实例

所以我知道str1和str2将在创建后立即被插入。“ str”和“ ing”将在行上共享相同的内存,String str= str1+str2;
但是str1 + str2如何在常量字符串池中直接产生“ string”。 没有调用任何String
Builder类,就像我不写时那样final
?看看它和实习生有什么关系

我写了这个片段

public class IntermTest {
    public static void main(String...strings ){
         String str1=("str").intern();
        String str2=("ing").intern();
        String str= str1+str2;

    }
}

但是当我生成字节码时我得到了

public static void main(java.lang.String...);
    flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
    Code:
      stack=3, locals=4, args_size=1
         0: ldc           #16                 // String str
         2: invokevirtual #18                 // Method java/lang/String.intern:
()Ljava/lang/String;
         5: astore_1
         6: ldc           #24                 // String ing
         8: invokevirtual #18                 // Method java/lang/String.intern:
()Ljava/lang/String;
        11: astore_2
        12: new           #26                 // class java/lang/StringBuilder
        15: dup
        16: aload_1
        17: invokestatic  #28                 // Method java/lang/String.valueOf
:(Ljava/lang/Object;)Ljava/lang/String;
        20: invokespecial #32                 // Method java/lang/StringBuilder.
"<init>":(Ljava/lang/String;)V
        23: aload_2
        24: invokevirtual #35                 // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        27: invokevirtual #39                 // Method java/lang/StringBuilder.
toString:()Ljava/lang/String;
        30: astore_3
        31: return

实际上,它也stringBuilder用于串联。因此,它与final有关系。关于final字符串,我绝对不知道有什么特别的地方吗?


问题答案:

http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28说

引用常量变量(第4.12.4节)的简单名称(第6.5.6.1节)是常量表达式。

http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28还说:

常量表达式是表示原始类型或String的值的表达式,该值不会突然完成,并且仅使用以下内容组成:

  • 基本类型的文字和字符串类型的文字(§3.10.1,§3.10.2,§3.10.3,§3.10.4,§3.10.5)
  • […]
  • 加法运算符+和-(§15.18)
  • […]
  • 引用常量变量(第4.12.4节)的简单名称(第6.6.5.6.1节)。

示例15.28-1 常数表达式

[…]

“整数” + Long.MAX_VALUE +“很大。

由于这两个变量是常量表达式,因此编译器进行串联:

String str = str1 + str2;

编译方式与

String str = "str" + "ing";

编译方式与

String str = "string";


 类似资料:
  • 问题内容: 我使用来了解Java与运算符的工作方式。 它是用同样的操作? 问题答案: 不。使用和做不一样。 在Java中,字符串实例是不可变的。 因此,如果您这样做: 每次连接时都在创建新的字符串。 另一方面,StringBuilder就像一个缓冲区,可以在追加新Strings时根据需要增长。 经验法则是(由于我的评论而改变): 如果要进行大量连接(例如,在循环内进行连接,或生成由多个字符串连接的

  • 问题内容: 嗨, 我正在尝试编写一个递归函数来计算Java中字符串的长度, 我知道已经存在str.length()函数,但是问题语句想要实现一个递归函数 在C编程语言中,终止字符为“ \ 0”,我只想知道如何知道字符串是否以Java结尾 当我在测试字符串中输入“ \ n”时,我的程序运行良好。请告诉我。谢谢! 输出: 问题答案: 请记住,此代码效率很低,但是它以递归方式计算String的长度。

  • 如果您构建了一个对象,说“intruder”并将其定义为final,那么您仍然可以更改类定义中不是final的对象字段(即intruder.power=50;)。在这种情况下,限制将是关于入侵者的对象引用,而不是内部值。 我的问题是:字符串作为一个例子呢?如果您创建了一个字符串对象,比如“String s=new String(”str“);是否有一种方法可以更改字符串的”str“值?如果没有,为

  • 问题内容: 我使用的是Oracle 10g,并具有以下表结构:id,段落 我想按ID分组并连接段落。每个段落可能超过1500个字符。 当我尝试wm_concat函数时,它抱怨字符串缓冲区太小。实际上,我在Oracle网站上尝试了许多示例,但所有示例均因字符串缓冲区太小而失败。 我该如何解决? 问题答案: 因此,我猜是错误的所在,我可以看到您在这种情况下如何认为这不适用于您。 但是,这是的错。这是一

  • 问题内容: 如何在python中连接字符串? 例如: 将其与形成字符串: 问题答案: 最简单的方法是 但为了提高效率,请参阅:https : //waymoot.org/home/python_string/

  • 我有一个对象,它在初始化时接受一个字符串来标识它的名称。 在上面的示例中,名称遵循一个约定,即整数与字符串“MyObject”连接在一起。一位同事抱怨说,由于int到字符串的转换,我编写这段代码的方式从性能角度来看其实很糟糕。这个数字是作为一个int接收的,我对此无能为力。object参数必须包含字符串。我怎么能让这更快?使用字符串格式会有帮助吗?