• 第十八天


    相信String这个类是Java中使用得最频繁的类之一,今天就来和大家一起学习一下StringStringBuilderStringBuffer

     

    一、从源码的角度初步了解String

    想要了解一个类,最好的办法就是看这个类的实现源代码,打开这个类的源码文件就会发现String类是被final修饰的:

    进一步分析可以看出几点:

    1String类是final类,也即意味着String类不能被继承,并且它的成员方法都默认为final方法。在Java中,被final修饰的类是不允许被继承的,并且该类中的成员方法都默认为final方法。在早期的JVM实现版本中,被final修饰的方法会被转为内嵌调用以提升执行效率。而从Java SE5/6开始,就渐渐摈弃这种方式了。因此在现在的Java SE版本中,不需要考虑用final去提升方法调用效率。只有在确定不想让该方法被覆盖时,才将方法设置为final

     

    2源码中String类中的成员属性可以看出,String类其实是通过char数组来保存字符串的。

     

     

    3从上面的两个方法可以看出,无论是sub还是concat操作都不是在原有的字符串上进行的,而是重新生成了一个新的字符串对象。也就是说进行这些操作后,最原始的字符串并没有被改变。

      在这里要永远记住一点:

      String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象

      在了解了于String类基础的知识后,下面来看一些在平常使用中容易忽略和混淆的地方。

     

     

    .深入理解StringStringBufferStringBuilder

    1.String str="hello world"String str=new String("hello world")的区别

    import java.util.Objects;
    
    public class Demo {
        public static void main(String[] args) {
        String s1 = "hello";
        String s2 = new String("hello");
        String s3 = "hello";
        String s4 = new String("hello");
        System.out.println(s1 == s2);//false
        System.out.println(s1 == s3);//true
        System.out.println(s2 == s4);//false
        }
    }

    2.StringStringBuffer以及StringBuilder的区别

    StringBuffer以及StringBuilder的功能和String一样都是可以进行字符串的操作。

    既然在Java中已经存在了String类,那为什么还需要StringBuilderStringBuffer类呢?

    那么看下面这段代码:

    import java.util.Objects;
    
    public class Demo {
        public static void main(String[] args) {
            String string = "";
            for (int i = 0; i < 100; i++) {
                string += "hello";// string = string + hello
                //传统的String做字符串拼接,循环100次,new100字符串对象
            }
            System.out.println(string);
        }
    }

    从上面String的源码中我们可以分析出:这句 string += "hello";的过程相当于将原有的string变量指向的对象内容取出与"hello"作字符串相加操作再存进另一个新的String对象当中,再让string变量指向新生成的对象。也就是说这个循环执行完毕new出了10000个对象,试想一下,如果这些对象没有被回收,会造成多大的内存资源浪费。

    再看下面这段代码:

    import java.util.Objects;
    
    public class Demo {
        public static void main(String[] args) {
            StringBuilder sbBuilder = new StringBuilder();
            for (int i = 0; i < 100; i++) {
                sbBuilder.append("hello");
            }
        System.out.println(sbBuilder.toString());
        }
    }

    这断代码和前面的功能一样,但是这里的10000次循环new操作只进行了一次,也就是说只生成了一个对象,append操作是在原有对象的基础上进行的。因此在循环了10000次之后,这段代码所占的资源要比上面小得多。这就是StringstringBuilder的最最主要的区别。

    其实:字符串拼接从jdk5开始编译器就已经完成了自动优化,当String+常量的代码在编译的时候就会自动被优化为new一个StringBuilder,再调用append方法。

    那么有人会问既然有了StringBuilder类,为什么还需要StringBuffer类?查看源代码便一目了然,事实上,StringBuilderStringBuffer类拥有的成员属性以及成员方法基本相同,区别是StringBuffer类的成员方法前面多了一个关键字:synchronized,不用多说,这个关键字是在多线程访问时起到安全保护作用的,也就是说StringBuffer是线程安全的。有关线程的问题,我们讲多线程的时候在详细讲解!

    总结:这三个类是各有利弊,应当根据不同的情况来进行选择使用

    1、循环外字符串拼接可以直接使用String+操作,没有必要通过StringBuilder进行append.

    2、有循环体的话,好的做法是在循环外声明StringBuilder对象,在循环内进行手动append

    不论循环多少层都只有一个StringBuilder对象。

    3、当字符串相加操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer

     

     

     

     

     

     

    相信String这个类是Java中使用得最频繁的类之一,今天就来和大家一起学习一下StringStringBuilderStringBuffer

     

    一、从源码的角度初步了解String

    想要了解一个类,最好的办法就是看这个类的实现源代码,打开这个类的源码文件就会发现String类是被final修饰的:

     

    进一步分析可以看出几点:

    1String类是final类,也即意味着String类不能被继承,并且它的成员方法都默认为final方法。在Java中,被final修饰的类是不允许被继承的,并且该类中的成员方法都默认为final方法。在早期的JVM实现版本中,被final修饰的方法会被转为内嵌调用以提升执行效率。而从Java SE5/6开始,就渐渐摈弃这种方式了。因此在现在的Java SE版本中,不需要考虑用final去提升方法调用效率。只有在确定不想让该方法被覆盖时,才将方法设置为final

     

    2源码中String类中的成员属性可以看出,String类其实是通过char数组来保存字符串的。

     

     

    3从上面的两个方法可以看出,无论是sub还是concat操作都不是在原有的字符串上进行的,而是重新生成了一个新的字符串对象。也就是说进行这些操作后,最原始的字符串并没有被改变。

      在这里要永远记住一点:

      String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象

      在了解了于String类基础的知识后,下面来看一些在平常使用中容易忽略和混淆的地方。

     

     

    .深入理解StringStringBufferStringBuilder

    1.String str="hello world"String str=new String("hello world")的区别

    public class Main {         

        public static void main(String[] args) {

            String str1 = "hello world";

            String str2 = new String("hello world");

            String str3 = "hello world";

            String str4 = new String("hello world");

             

            System.out.println(str1==str2);

            System.out.println(str1==str3);

            System.out.println(str2==str4);

        }

    }

    这段代码的输出结果为

     

    2.StringStringBuffer以及StringBuilder的区别

    StringBuffer以及StringBuilder的功能和String一样都是可以进行字符串的操作。

    既然在Java中已经存在了String类,那为什么还需要StringBuilderStringBuffer类呢?

    那么看下面这段代码:

    public class Main {

        public static void main(String[] args) {

            String string = "";

            for(int i=0;i<10000;i++){

                string += "hello";

            }

        }

    }

    从上面String的源码中我们可以分析出:这句 string += "hello";的过程相当于将原有的string变量指向的对象内容取出与"hello"作字符串相加操作再存进另一个新的String对象当中,再让string变量指向新生成的对象。也就是说这个循环执行完毕new出了10000个对象,试想一下,如果这些对象没有被回收,会造成多大的内存资源浪费。

     

    再看下面这段代码:

    public class Main {      

        public static void main(String[] args) {

            StringBuilder stringBuilder = new StringBuilder();

            for(int i=0;i<10000;i++){

                stringBuilder.append("hello");

            }

        }

    }

    这断代码和前面的功能一样,但是这里的10000次循环new操作只进行了一次,也就是说只生成了一个对象,append操作是在原有对象的基础上进行的。因此在循环了10000次之后,这段代码所占的资源要比上面小得多。这就是StringstringBuilder的最最主要的区别。

    其实:字符串拼接从jdk5开始编译器就已经完成了自动优化,当String+常量的代码在编译的时候就会自动被优化为new一个StringBuilder,再调用append方法。

     

    那么有人会问既然有了StringBuilder类,为什么还需要StringBuffer类?查看源代码便一目了然,事实上,StringBuilderStringBuffer类拥有的成员属性以及成员方法基本相同,区别是StringBuffer类的成员方法前面多了一个关键字:synchronized,不用多说,这个关键字是在多线程访问时起到安全保护作用的,也就是说StringBuffer是线程安全的。有关线程的问题,我们讲多线程的时候在详细讲解!

     

     

     

    总结:这三个类是各有利弊,应当根据不同的情况来进行选择使用

    1、循环外字符串拼接可以直接使用String+操作,没有必要通过StringBuilder进行append.

    2、有循环体的话,好的做法是在循环外声明StringBuilder对象,在循环内进行手动append

    不论循环多少层都只有一个StringBuilder对象。

    3、当字符串相加操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer

     

     

     

     

     

     

  • 相关阅读:
    面试时面试官想要听到什么答案(关于一些vue的问题)
    Redis主从复制以及主从复制原理
    当面试官问你:如何进行性能优化?
    swoole通往大神之路——swoole任务中心说明及进程任务架构搭建
    全局句柄表
    句柄表(私有句柄表)
    关于VAD的两种内存隐藏方式
    通过修改VAD属性破除锁页机制
    R3环申请内存时页面保护与_MMVAD_FLAGS.Protection位的对应关系
    利用内存锁定技术防止CE修改
  • 原文地址:https://www.cnblogs.com/jikebin/p/12623862.html
Copyright © 2020-2023  润新知