JAVA中String、StringBuffer和StringBuider类

String

String类的继承关系图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hA8UV4Em-1645966133352)(E:\Typora笔记\java笔记\img\image-20220208125507192.png)]

基本介绍:

  1. String对象用于保存字符串,也就是一组字符序列

  2. 字符串常量对象是用双引号括起的字符序列。例如:"你好","haikang","168"

  3. 字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节

  4. String类较常用构造器:

5. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-unAh31ib-1645966133353)(E:\Typora笔记\java笔记\img\image-20220213211318084.png)]

String s1 = new String();
String s2 = new String(String moriginal);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
String s5 = new String(byte[] b);
  1. Constructor and Description
    String() 初始化新创建的 String对象,使其表示空字符序列。
    String(byte[] bytes) 通过使用平台的默认字符集解码指定的字节数组来构造新的 String
    String(byte[] bytes, Charset charset) 构造一个新的String由指定用指定的字节的数组解码charset
    String(byte[] ascii, int hibyte) 已弃用 此方法无法将字节正确转换为字符。 从JDK 1.1开始,首选的方法是通过String构造函数获取Charset ,字符集名称,或者使用平台的默认字符集。
    String(byte[] bytes, int offset, int length) 通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String
    String(byte[] bytes, int offset, int length, Charset charset) 构造一个新的String通过使用指定的指定字节子阵列解码charset
    String(byte[] ascii, int hibyte, int offset, int count) 已弃用 此方法无法将字节正确转换为字符。 从JDK 1.1开始,首选的方式是通过String构造函数获取Charset ,字符集名称,或使用平台的默认字符集。
    String(byte[] bytes, int offset, int length, String charsetName) 构造一个新的 String通过使用指定的字符集解码指定的字节子阵列。
    String(byte[] bytes, String charsetName) 构造一个新的String由指定用指定的字节的数组解码charset
    String(char[] value) 分配一个新的 String ,以便它表示当前包含在字符数组参数中的字符序列。
    String(char[] value, int offset, int count) 分配一个新的 String ,其中包含字符数组参数的子阵列中的字符。
    String(int[] codePoints, int offset, int count) 分配一个新的 String ,其中包含 Unicode code point数组参数的子阵列中的 字符
    String(String original) 初始化新创建的String对象,使其表示与参数相同的字符序列; 换句话说,新创建的字符串是参数字符串的副本。
    String(StringBuffer buffer) 分配一个新的字符串,其中包含当前包含在字符串缓冲区参数中的字符序列。
  2. String类中有一个非常重要的属性是private final char value[];value指向的地址是不可以改变的 ,而的存在的单个字符是可以改变的

package wrapper_.string_;

/**
 * @author: 海康
 * @version: 1.0
 */
public class String01 {
    public static void main(String[] args) {
        String name = "湛江";
        name = "海康";//将指向的内容改成:海康
        /**
         * 1.String对象用于保存字符串,也就是一组字符序列
         * 2."湛江"字符串常量,双引号括起的字符序列
         * 3.字符串的字符使用Unicode字符编码,一个字符【不区分字母还是汉字】都是占有两个字节的
         * 4.String类有很多的重载的构造器
             * String s1 = new String();
             * String s2 = new String(String moriginal);
             * String s3 = new String(char[] a);
             * String s4 = new String(char[] a,int startIndex,int count);
             * String s5 = new String(byte[] b);
         *
         * 5.String类实现了Serializable接口【说明String可以串行化:串行化是可以在网络中传输的】
         *      String类实现了Comparable接口【说明String类对象是可以比较大小的】
         *
         * 6.String类是final修饰的说明String是不能被继承的
         * 7.String类中有一个非常重要的属性是``private final char value[];
         * ``的``value``指向的地址是不可以改变的 ,而的存在的单个字符是可以改变的
         */
    }
}

String类中的value值是存在常量池中地址的,就是说value值是用于维护常量池的地址,是不能改变的,改变的只能是常量池的内容,如用new的方式创建对象【才有用value属性维护常量池的地址】

创建String对象的两种方式

方式一:直接赋值 String s = "hsp";

方式二:调用构造器String s = new String("hsp");

两种创建String对象的区别

1.方式一:先从常量池查看是否有"hsp"数据空间,如果有,直接指向;如果没有重新创建,然后指向。s(对象引用名)最终指向的是常量池的空间地址

2.方式二:先在堆中创建空间,里面维护了一个value属性值【是用于存在常量的空间地址的】,指向常量池的hsp空间。如果常量池没有hsp,重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址

3.两种方式的jvm内存分布图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yUEzvM8H-1645966133353)(E:\Typora笔记\java笔记\img\image-20220208171946407.png)]

课堂测试题

测试题1:
在这里插入图片描述

String  a  = "abc";
String  b  = "abc";
System.out.println(a.equals(b));//true
System.out.println(a==b);//true
String类中equals方法源码:比较是两个内容是否相同
 public boolean equals(Object anObject) {
        if (this == anObject) {//如果传入的引用指向同一个地址,则返回true
            return true;
        }
        if (anObject instanceof String) {//判断是否是字符串,不是直接返回false
            String anotherString = (String)anObject;//向下强转
            int n = value.length;
            if (n == anotherString.value.length) {//判断长度是否相同,不同直接返回false
                char v1[] = value;//取出value中的值,里面存在的是常量池中的地址[但是取出时是常量池中的内容]
                char v2[] = anotherString.value;//取出value中的值,里面存在的是常量池中的地址[但是取出时是常量池中的内容]
                int i = 0;
                while (n-- != 0) {//一个字符串的比较
                    if (v1[i] != v2[i])//当出现一个不相同时,直接返回false
                        return false;
                    i++;
                }
                return true;//全部比较相同返回true
            }
        }
        return false;//如果传入的类型不是字符串直接返回false
    }

测试题2:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9sj1hlAN-1645966133355)(E:\Typora笔记\java笔记\img\image-20220208172434991.png)]

输出的结果是:
true
false
true
false

测试题3:

知识点:
当调用intern方法时,如果池已经包含一个等于此String对象的字符串【用equals(Object)方法确定】,则返回池中的字符串。否则,将此String对象添加到常量池中,并返回此String对象的引用

总结:对象引用.intern()方法最终返回的是常量池的地址【对象】
String a = "hsp";//指向常量池
String b = new String("hsp");//指向堆中的对象
System.out.println(a.equals(b));//T
System.out.println(a==b);//F
System.out.println(a==b.intern());//T,intern方法是返回常量池中的地址
System.out.println(b==b.intern());//F

在这里插入图片描述

测试题4:

在这里插入图片描述

String s1 = "海康";
String s2 = "java";
String s3 = new String("java");
String s4 = "java";
System.out.println(s2==s3);//F
System.out.println(s2==s4);//T
System.out.println(s2.equals(s3));//T
System.out.println(s1==s2);//F

测试题5:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T1hu2VnK-1645966133356)(E:\Typora笔记\java笔记\img\image-20220208181121089.png)]
在这里插入图片描述

字符串的特性【必须掌握】

题1

1.String是一个final类,代表不可变的字符序列

2.字符串是不可变的,一个字符串对象一旦被分配,其内容是不可变的

以下语句创建了几个对象?画出内存布局图
String s1 = "hello";
s1 = "haha";
创建了再次对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oqSGc0Zz-1645966133357)(E:\Typora笔记\java笔记\img\image-20220208190200783.png)]

面试题目1【必须掌握】

题1:

String  a = "hello" + "abc";
创建了几个对象?只有1对象。
因为是: String a = "hello" + "abc";//底层优化成 String a = "helloabc";

分析是:
1.底层编译器做一个优化,判断创建的常量池对象,是否有引用指向
2.String a = "hello"+"abc"; => String a = "helloabc";

题2

String  a = "hello";//创建了对象a
String  b = "abc";//创建了b对象
String c = a + b;//创建了几个对象?画出内存图?
关键就是分析String  c = a + b;到底是如何执行的
一共有3对象,如图。

总结:底层是:1.StringBuilder sb = new StringBuilder();
2.sb.append(a);
3.sb.append(b);
4.sb是在堆中,并且append是在原来字符串的基础上追加的
5.再调用StringBuilder类中的toString方法
    【所以指向的地址是指向堆中的,堆有一个value维护着常量池的属性】

重要规则:
String c = "ab"+"cd";常量相加,看的是常量池
String c = a + b;变量相加,是在堆中【一个变量一个常量相加,也是堆中】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ozH1sf5X-1645966133358)(E:\Typora笔记\java笔记\img\image-20220208190919184.png)]

重要规则:
String c = “ab”+“cd”;常量相加,看的是常量池
String c = a + b;变量相加,是在堆中【一个变量一个常量相加,也是堆中】

代码:

package wrapper_.string_;

/**
 * @author: 海康
 * @version: 1.0
 */
public class StringExercise01 {
    public static void main(String[] args) {
        /**
         * 1. 先创建一个 StringBuilder  sb = new StringBuilder();
         * 2.执行 sb.append("abc");
         * 3.sb.append("def");
         * 4.String c = sb.toString();方法
         * 最后其实是c指向堆中的对象(String)value[] --> 池中 "abcdef"
         */
        String a = "abc";
        String b = "def";
        String c = a + b;
        //下面的一个变量一个常量相加的作用效果是一样的
        String d = a + "gh";
        System.out.println(d);
    }
}

题3:

下面代码输出什么,并说明原因?
String s1 = "海康";
String s2  "java";
String s3 = "海康java";
String s4 = (S1+s2).intern();
System.out.println(s3==s4);//T
System.out.println(s3.equals(s4));//T

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IqxvmFj8-1645966133358)(E:\Typora笔记\java笔记\img\image-20220209102932412.png)]

题4:

下列程序运行的结果是什么?尝试画出内存布局图?

public class Test1{
	String str = new String("hsp");
	final char[] ch = {'j','a','v','a'};
	public void  change(String str,char ch[]){
		str = "java";
		ch[0] = 'h';
	}
	
	public static void main(String[] args){
		Test1 ex = new Test1();
		ex.change(ex.str,ex.ch);
		System.out.println(ex.str + "and");
		System.out.println(ex.ch);
	}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4zra3vFi-1645966133358)(E:\Typora笔记\java笔记\img\image-20220209104247199.png)]

上面的final char[] ch = {'j','a','v','a'};代码,用于final修饰说明的是ch指向的地址是不能修改的,可以修改的是ch中的内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8oW9OY45-1645966133359)(E:\Typora笔记\java笔记\img\image-20220209105628402.png)]

String类常用方法

说明:

String类是保存字符串常量的。每次更新都需要重新开辟空间,效率较低,因此java设计者提供了StringBuilderStringBuffer来增强String的功能,并提高效率。

看看代码?

String s = new String("");
for(int i=0;i<80000;i++){
	s += "hello";//由于每次拼接都会在常量池中开辟新的空间效率低
}

String类的常见的方法一览

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZsO3uC4U-1645966133359)(E:\Typora笔记\java笔记\img\image-20220209123814753.png)]

1.equals //区分大小写,判断内容是否是相等

2.equalslgnoreCase //忽略大小写的判断内容是否相等

    public boolean equalsIgnoreCase(String anotherString) {
            return (this == anotherString) ? true
                    : (anotherString != null)
                    && (anotherString.value.length == value.length)
                    && regionMatches(true, 0, anotherString, 0, value.length);
        }
3.length //获取字符个数 ,字符串的长度

    public int length() {
            return value.length;
        }
   
4.indexOf //获取字符在字符串中的第1次出现的索引,索引从0开始,如果找不到,返回-1
    public int indexOf(String str) {
        return indexOf(str, 0);
    }

5.lastIndexOf //获取字符在字符串中最后1次出现的索引,索引从0开始,如找不到,返回-1
    public int lastIndexOf(String str) {
            return lastIndexOf(str, value.length);
        }
       
6.subString  //截取指定范围的字串

    public String substring(int beginIndex) {
    //表示从beginIndex的位置开始截取到最后一个字符
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }
    
    
    
     public String substring(int beginIndex, int endIndex) {
     //表示从beginIndex的位置开始到endIndex-1的位置
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }
    
    
7.trim  //去前后空格

    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;
    }
    
8.charAt //获取某索引处的字符,注意不能使用str[index]的方式
    public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2vKkIdtP-1645966133359)(E:\Typora笔记\java笔记\img\image-20220209123741933.png)]

9. toUpperCase //转成大写字母
    public String toUpperCase() {
        return toUpperCase(Locale.getDefault());
    }

10. toLowerCase //转成小写字母
    public String toLowerCase() {
        return toLowerCase(Locale.getDefault());
    }

11. concat //拼接字符串
    public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }

12. replace //替换字符串中的字符
    public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */

            while (++i < len) {
                if (val[i] == oldChar) {
                    break;
                }
            }
            if (i < len) {
                char buf[] = new char[len];
                for (int j = 0; j < i; j++) {
                    buf[j] = val[j];
                }
                while (i < len) {
                    char c = val[i];
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, true);
            }
        }
        return this;
    }

13. split //分割字符串,对于某此分割字符,我们需要 转义比如 【| \\等】
对于分割后是返回一个数组,在对字符串进行分割时,如果有特殊字符,需要加入转义符【\】
    public String[] split(String regex) {
        return split(regex, 0);
    }

14. compareTo  //比较两个字符串的大小
1.如果长度相同,并且每个字符也相同,就返回0
2.如果长度相同或者不相同,但是在进行比较时,可是区分大小
	就返回 if(c1 != c2){
		return c1 - c2;
	}
3.如果前面的部分相同,就返回 str1.len - str2.len;

    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }


15.toCharArray  //转换成字符数组
    public char[] toCharArray() {
        // Cannot use Arrays.copyOf because of class initialization order issues
        char result[] = new char[value.length];
        System.arraycopy(value, 0, result, 0, value.length);
        return result;
    }
    
16. format //格式字符串,%s字符串 %c字符  %d整型  %.2f浮点型
%s,%d,%.2f,%c称为占位符
这些占位符由后面变量来替换
%S表示后面由字符串来替换
%d是整数来替换
%.2f表示使用小数来替换,替换后,只会保留小数点两位,并且进行四舍五入的处理
%c使用char类型来替换

	
	public static String format(String format, Object... args) {
        return new Formatter().format(format, args).toString();
    }

String name = "海康";
int age = 18;
double score = 99.9168;
char gender = '男';
String info = "我的姓名:%s\t年龄:%d\t分数:%.2f\t性别";
System.out.println(String.format(info,name,age,score,gender));
StringBuffer

基本介绍:java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删。

很多方法与String相同,但是StringBuffer是可变长度的

StringBuffer是一个容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JqQEcUU6-1645966133359)(E:\Typora笔记\java笔记\img\image-20220209215022222.png)]

package wrapper_.stringBuffer;

/**
 * @author: 海康
 * @version: 1.0
 */
public class StringBuffer01 {
    public static void main(String[] args) {
        /**
         * 1.StringBuffer的直接父类是 AbstractStringBuffer
         * 2.StringBuffer实现了Serializable接口,即StringBuffer的对象可以串行化
         * 3.在父类中 AbstractStringBuffer有属性 char[] value,不是final
         *      该 value 数组存放在字符串内容,引出存在在堆中的
         * 4.StringBuffer是一个final类,不能被继承
         * 5.因为StringBuffer字符内容是存在 char[] value,所有在变化【增加,删除】
         *      不用每次都更换地址【即不是每次创建新对象,所以效率高于String】
         */
        StringBuffer buffer = new StringBuffer("海康");
    }
}
StringVSStringBuffer的比较

1.String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低,根本原因是:private final char value[]

2.StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率较高,根本原因是:char[] value;是放在堆中的

StringBuffer的构造器【必须掌握】
Constructor and Description
StringBuffer() 构造一个没有字符的字符串缓冲区,初始容量为16个字符。
StringBuffer(CharSequence seq) 构造一个包含与指定的相同字符的字符串缓冲区 CharSequence
StringBuffer(int capacity) 构造一个没有字符的字符串缓冲区和指定的初始容量。 【就是可以指定大小capacity容量】
StringBuffer(String str) 构造一个初始化为指定字符串内容的字符串缓冲区。【初始化的大小是:str长度加上16】

StringBuffer中的toString方法源码【必须掌握】

说明:将StringBuffer最终转成的String

public synchronized String toString() {
    if (toStringCache == null) {
        toStringCache = Arrays.copyOfRange(value, 0, count);
    }
    return new String(toStringCache, true);
}

StringBuffer构造器的使用

package wrapper_.stringBuffer;

/**
 * @author: 海康
 * @version: 1.0
 */
public class StringBufferConstructor {
    public static void main(String[] args) {
        //构造器使用
        //1.创建一个 大小为16的 char[],用于存在字符序列
        StringBuffer stringBuffer = new StringBuffer();

        //2.通过构造器指定 char[] 大小
        StringBuffer stringBuffer1 = new StringBuffer(168);

        //3.通过给定一个String 创建 StringBuffer,char[] 大小就是 str.length()+16
        StringBuffer buffer = new StringBuffer("海康");
    }
}
StringStringBuffer相互转换
package wrapper_.stringBuffer;

/**
 * @author: 海康
 * @version: 1.0
 */
public class StringAndStringBuffer {
    public static void main(String[] args) {
        /**
         * String 和 StringBuffer的相互转换
         * 在开发中,我们经常需要将String 和 StringBuffer进行转换
         */
        // String 转换成 StringBuffer
        //方式一:使用构造器
        String str = "海康";
        StringBuffer sb1 = new StringBuffer(str);

        //方式二:使用append方法
        StringBuffer sb2 = new StringBuffer();
        String str2 = "湛江";
        StringBuffer append = sb2.append(str2);
        
        // StringBuffer 转换成 String
        //方式一:使用 StringBuffer 中的 toString方法
        StringBuffer sb3 = new StringBuffer("南宁");
        String s = sb3.toString();
        
        //方式二:使用 String 中的构造器
        StringBuffer sb4 = new StringBuffer("广州");
        String s2 = new String(sb4);
    }
}
StringBuffer类常见的方法
1.append(String str);

2.delete(start,end);【start:开始位置,end:结束位置】
/**
 * 删除索引为 >= start && end 处的字符 【包头不包尾】
 */
 
3.replace(start,end,String);//将strat到end间的内容替换成String,不包含end位置

4.indexOf(String str);//查找子串在字符串中第1次出现的索引,如果找不到返回-1

5.insert(int offset, String str);//在指定的位置插入字符串str

6.获取长度  length

常见的方法源码

//增
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

//删
public synchronized StringBuffer delete(int start, int end) {
        toStringCache = null;
        super.delete(start, end);
        return this;
 }
 
 //改
public synchronized StringBuffer replace(int start, int end, String str) {
     toStringCache = null;
     super.replace(start, end, str);
     return this;
 }
 
//查
public int indexOf(String str) {
        // Note, synchronization achieved via invocations of other StringBuffer methods
        return super.indexOf(str);
 }

//插
public synchronized StringBuffer insert(int offset, String str) {
        toStringCache = null;
        super.insert(offset, str);
        return this;
 }
 
//获取长度
public synchronized int length() {
        return count;
    }

案例演示:

package wrapper_.stringBuffer;

/**
 * @author: 海康
 * @version: 1.0
 */
public class StringBufferMethod {
    public static void main(String[] args) {
        //增
        StringBuffer sb1 = new StringBuffer("hello");
        sb1.append(',');
        sb1.append("海康");
        sb1.append(168);
        sb1.append(3.14159);
        System.out.println(sb1);

        //删
        /**
         * 删除索引为 >= start && < end 处的字符
         * 注意是:包含头,不包含尾
         */
        sb1.delete(0,6);
        System.out.println(sb1);//默认调用是toString方法【将StringBuffer类型转成String类型】

        //改
        /**
         * 修改的是包含头,不包含尾
         * 将前2字符 ”海康“ 替换成 ”湛江“
         */
        sb1.replace(0,3,"湛江");
        System.out.println(sb1);

        //查找
        /**
         * 查询子串在字符串中第一次出现的位置,如果没有查到返回 -1
         */
        int i = sb1.indexOf("湛江");
        System.out.println(i);

        //插
        /**
         * 在索引为 0 的位置插入 “海康”,原来索引为0的内容自动往后移
         */
        sb1.insert(0,"海康");
        System.out.println(sb1);//默认调用toString方法

        //获取长度
        int length = sb1.length();
        System.out.println(length);

        /**
         * 返回结果是:
         * hello,海康1683.14159
         * 海康1683.14159
         * 湛江683.14159
         * 0
         * 海康湛江683.14159
         * 13
         */
    }
}

String StringBuffer StringBuider 三者都有很多相同的方法,可以查看API

StringBuffer类课堂测试题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dhlQGnRe-1645966133360)(E:\Typora笔记\java笔记\img\image-20220211120657800.png)]

此题需要看看源码:解答

输出内容:
4
null
抛出空指针异常NullPointerException

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-chRDFEdv-1645966133360)(E:\Typora笔记\java笔记\img\image-20220211121912308.png)]

练习题2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mAVAYRdW-1645966133360)(E:\Typora笔记\java笔记\img\image-20220211121944196.png)]

package wrapper_.stringBuffer;

/**
 * @author: 海康
 * @version: 1.0
 */
public class StringBufferExercise01 {
    public static void main(String[] args) {
        /**
         * 对象输入的数据进行格式化:
         * 如输入:123456.88 格式化为:123,456.88
         */
        /**
         * 思路分析:
         * 1.定义一个Scanner对象,接收用户输入的价格【输入应用用String接收】
         * 2.希望使用到StringBuffer的 insert,需要交将 String 转成 StringBuffer
         * 3.然后使用相关的方法进行字符串的处理
         */

        String price = "1234506.88";//价格
        //将String 转成 StringBuffer
        StringBuffer sb = new StringBuffer(price);
        //找到小数点的位置
//        int i = sb.indexOf(".");
//        StringBuffer insert = sb.insert(i - 3, ",");
//        System.out.println(sb);
        //将其做成循环
        for (int i = sb.indexOf(".")-3; i > 0; i -= 3) {
            sb.insert(i,",");
        }
        System.out.println(sb);
    }
}
StringBuilder

基本介绍:

1.一个可变的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同步【StringBuilder不是线程安全的】。该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可以,建议优先采用该类,因为在大多数实现中,它比StringBuffer要快。

2.在StringBuilder上的主要操作是appendinsert方法,可重载这些方法,以接受任意类型的数据

StringBuilder类的继承关系图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Duys9Nlp-1645966133361)(E:\Typora笔记\java笔记\img\image-20220211125326030.png)]

StringBuffer常用方法

StringBuilderStringBuffer均代表可变的字符序列,方法是一样的,所以使用和StringBuffer一样

package wrapper_.strinhBuilder;

/**
 * @author: 海康
 * @version: 1.0
 */
public class StringBuilder01 {
    public static void main(String[] args) {
        /**
         * 1.StringBuilder 继承了 AbstractStringBuilder 抽象类
         * 2.实现 Serializable 接口,说明StringBuildr 对象是可以串行化的【对象可以在网络传输,可以保存到文件】
         * 3.StringBuilder 是final类 ,不能被继承
         * 4.StringBuilder 对象字符序列仍然是存在放在 AbstractStringBuilder 的 char[] value;
         *      因此,字符序列是在堆中
         * 5.StringBuilder 的方法,没有做互斥处理,即没有 synchronized 关键字,因此在单线程的情况下使用 StringBuilder类
         */
        StringBuilder sb = new StringBuilder("hello");
    }
}
StringStringBufferStringBuilder

1.StringBuilderStringBuffer非常类似,均代表可变的字符序列,而且方法也一样的

2.String:是不可变字符序列,效率低,但是复用率高

3.StringBuffer:可变字符序列,效率较高【增删】,线程安全,看源码

4.StringBuilder:可变字符序列,效率最高,线程不安全

5.String使用注意说明

  • String s = "a";//创建了一个字符串
  • s += "b";//实际上原来的a字符串已经丢弃了,现在又产生了一个字符串s+b【也就是"ab"】。如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能 ==》结论:如果我们对String做大量修改,不要使用String
StringStringBufferStringBuilder的选择
  1. 如果字符串存在大量的修改操作,一般使用 StringBuffer【多线程情况下】或 StringBuilder【单线程情况下】
  2. 如果字符串存在大量的修改,并在单线程的情况下,使用StringBuilder
  3. 如果字符串存在大量的修改,并在多线程的情况下,使用StringBuffer
  4. 如果我们字符串很少修改,被多个对象引用,使用String,比如配置文件等

StringBuilder的方法使用和StringBuffer一样

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值