【Java进阶】关于String的一些思考(集合类)

本文探讨了Java中String对象的不可变性,当修改String时实际上是创建新对象,而非原地修改。举例说明了`upCase()`方法如何处理String并返回新对象。此外,解释了在JDK5到JDK8中,`+`操作符用于字符串连接时,Javac会转换为StringBuilder方式,避免了大量的中间对象,从而提高效率。在JDK9及以后,使用了动态方法调用来优化字符串连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

String

String对象是不可变,当我们要修改String的值的时候,实际上我们是新建了一个String的对象,而开始的对象则并没有发生改变.我们也可以简单的认为String只是具有可读性。

    public static String upCase(String s){
        return s.toUpperCase();//将小写字母转化为大写

    }

    public static void main(String[] args) throws Exception {
        String q = "baishao";
        System.out.println(q);
        String p = upcase(q);
        System.out.println(p);
        System.out.println(q);

    }


//输出结果
baishao
BAISHAO
baishao

        该代码中,当q传值入upCase()时,实际上传递的引用是一个拷贝,每当把String对象作为方法的参数的时,都会复制一份引用,而该引用所指向的对象会一直保留再原先的物理位置上,从未动过。

        回到我们的upCase()方法里,当引入传入时候就有了名字s,而只有当upCase()方法正在运行的时候,局部引用s才存在.一旦upCase()运行结束,s就消失了.当然,upCase()的返回值,其实只是最终结果的引用,而且该引用已经指向了一个新的对象,而原本的q还在原地。

        不可变性会带来一定的效率问题。其中String对象中的重载“+”操作符就是一个很好的例子,重载的意思是,一个操作符应用在特定的类时,被赋予了特殊的意义。我们通过一个例子来看观察。

/*
*这是一个用“+”连接String的例子
*/

public class Demo1 {
    public static void main(String[] args) {
        String s1 = "baishao";
        String s2 = s1 + "abc" + "hello" + 46;
        System.out.println(s2);
    }
}

        我们可以大胆猜想一下,有没有可能String中有一个append的方法,它会生成一个新的String对象,用来包含s1与“adc”拼接后的字符串,然后该对象又与“hello”相连,再次形成了一个新的String对象,但是如果是这样的话,这样的话不就会产生一大堆需要垃圾回收的对象吗?而这频繁的触发GC势必会引起程序执行的效率下降。为了一探究竟,我们可以试着反编译该代码

依次执行以下命令:

//生成对应的字节码文件
javac Demo1.java
//对字节码文件进行反编译
javap -c Demo1

执行该命令的字节码如下:

public class Demo.Demo1 {
  public Demo.Demo1();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #7                  // String baishao
       2: astore_1
       3: aload_1
       4: invokedynamic #9,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
       9: astore_2
      10: getstatic     #13                 // Field java/lang/System.out:Ljava/io/PrintStream;
      13: aload_2
      14: invokevirtual #19                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      17: return
}

        在JDK5-JDK8,Javac会把字符串连接语句转译成StringBuilder调用,而在JDK9之后中变成了动态方法调用。那么这个#0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;是什么呢?

      动态指令invokedynamic指令会调用makeConcatWithConstants方法进行字符串的连接。
该方法位于java.lang.invoke.StringConcatFactory类中。

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诗竹白芍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值