String、StringBuffer与StringBuilder类详解

一、String简介:

String:字符串,使用一对“”引起来表示。

1.String 声明为final的,不可被继承。
2.Stirng 实现了了Serializable接口:表示字符串是支持序列化的。实现了Comparable接口:b表示String可以比较大小。
3.String内部定义了final char[] value 用于存储字符串数据。
4.String:代表不可以变的字符序列。
5.通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
6.字符串常量池中是不会存储相同内容的字符串。

注意:不可变性主要体现三点:
1.对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
2.当对现有的字符串赋值时,有需要重新指定内存区域赋值,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
3.当调用String的replace()方法修改指定字符或者字符串时,也需要重新指定内存区域重新赋值。

代码演示:

package com.fan.domain;

import org.junit.Test;

public class StringTest {
    @Test
    public void test1(){
        String s1 = "abc";
        String s2 = "abc";
        //1.对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
        s1 = "hello";
        System.out.println(s1 == s2);//比较的是地址
        System.out.println(s1);
        System.out.println(s2);
        System.out.println("***************");
        //2.当对现有的字符串赋值时,有需要重新指定内存区域赋值,
        // 也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
        String s3 ="abc";
        s3 += "def";
        System.out.println(s3);//abcdef
        System.out.println(s2);
        System.out.println("***************");
        //3.当调用String的replace()方法修改指定字符或者字符串时
        // ,也需要重新指定内存区域重新赋值。
        String s4 = "abc";
        String s5 = s4.replace('a','m');
        System.out.println(s4);//abc
        System.out.println(s5);//mbc
    }
}

在这里插入图片描述

二、String的创建方式:

常见的两种方式:
方式一:通过字面量的方式定义。
方式二:通过new + 构造器 的方式。

面试题一:String s = new String(“abc”);方式创建对象,在内存中创建了几个对象?

回答:两个。前提是常量池中没有字符串常量“abc”;其中一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:“abc”;
在这里插入图片描述
三、String内存结构:
在这里插入图片描述

在这里插入图片描述
字符串拼接:
结论:

1.常量与常量的拼接结果在常量池。且常量池中不会存在相同的常量。
2.只要其中有一个是变量,结果就在堆中。
3.如果拼接的结果调用intern()方法,返回值就在常量池中。
在这里插入图片描述
在这里插入图片描述

四、一个笔试题:

在这里插入图片描述

内存图详解:
在这里插入图片描述

上述代码解释:最终输出good和best

注意:栈中存的是局部变量和对象的引用。
堆中存的是对象本身(包含对象的属性)

先从main方法开始执行。创建了一个本类的对象,然后对象调用其方法change().==这里特别注意,change()参数中是一个新的局部变量str,和ch,不是成员变量str和ch,局部变量的范围是在其{}内。方法执行完后局部变量失效。传递的本质都是地址值。

jvm中常量池到底在哪里:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
总结:jvm中字符串常量池存放位置说明:
jdk1.6:字符串常量池存储在方法区(永久区)
jdk1.7:字符串常量池存在于堆空间中
jdk1.8:字符串常量池存在于方法区(元空间)

五、字符串的常用方法:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.charAt(int index)类似于数组中取指定位置的元素一样,通过字符串的封装取指定索引处 的元素。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

String和基本类型数据的转换:

基本数据类型,包装类—>String类型

基本数据类型,包装类—>String类型:调用String.valueOf(基本类型);
int num1=10;
方法1:
String str1= num1+"";
方法2:调用String的valueOf()
float f1=12.3f;
String str2 = String.valueOf(f1);

String类型–>基本数据类型和包装类:都需要调用包装类的parseXXX(String s)
String s=“123”;
int num2 = Integer.parseInt(s);
Integer a1 = Integer.parseInt(s);

在这里插入图片描述

String 与char[]之间的转换:

String --> char[] :调用String的toCharArray()方法
char[] --> String :调用String的构造器String(char value[])

String 与byte[]之间的转换:

编码:String–> byte[]:调用String的getBytes()方法
解码:byte[] --> String: 调用String的构造器 String(byte[] bytes)
代码演示:

在这里插入图片描述
在这里插入图片描述
StringBuffer与StringBuilder:

String、StringBuffer与StringBuilder之间区别:

在这里插入图片描述
String:不可变的字符序列,使用final修饰;底层使用char[]存储。
StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储。
StringBuilder:可变的字符序列:jdk5.0新增。线程不安全,效率高;底层使用char[]存储;

String、StringBuffer与StringBuilder底层源码分析:

源码分析:
String源码分析:构造器中显式容量是多少容量,就是多少容量
String str = new String();//底层是:char[] value = new char[0];
String str1 = new String(“abc”);//底层char[] value = new char[]{‘a’,‘b’,‘c’};

而StringBuffer不一样:
StringBuffer sb1 = new StringBuffer();//底层char[] value = new char[16],底层创建了一个长度16容量。StringBuffer空参构造默认容量是16个

println(sb1.length());
sb1.append(‘a’);//value[0] = ‘a’;
sb1.append(‘b’);//value [1] = ‘b’;

//带字面量的方式:此种方式容量是字面量的容量加上16
StringBuffer sb2 = new StringBuffer(“abc”);//char[] value = new char[’‘abc’.length()+16];

问题一:println(sb2.length());//3,底层是数组的有效元素的个数count.
问题二:扩容问题:如果要添加的数据底层数组放不下,那就需要扩容底层数组容量。默认情况下,扩容为原来容量的2倍 + 2,同时将原有数组中的元素复制到新的数组汇总。

指导意义:开发中减一大家使用StringBuffer(int capacity) 或者StringBuilder(int capacity) 来预测并制定大概容量。

String与StringBuffer/StringBuilder之间转换:

String–> StringBuffer/StringBuilder:调用StringBuffer/StringBuilder构造器StringBuffer(String str)

StringBuffer/StringBuilder–>String:(方式1)调用StringBuffer/StringBuilder的toString(),方式2:调用String的构造器String(StringBuffer buffer)

代码演示:

 @Test
    public void test3(){
        //String--> StringBuffer/StringBuilder:调用StringBuffer/StringBuilder构造器
        String str = "hehe";
        StringBuffer stringBuffer = new StringBuffer(str);
        System.out.println(stringBuffer);

        //StringBuffer/StringBuilder-->String:
        StringBuilder sb = new StringBuilder("hello");
        //方式一
        String s = new String(sb);
        //方式二
        String s1 = sb.toString();
        System.out.println(s1);
    }

总结String与常用类型之间的转换:

在这里插入图片描述

StringBuffer/StringBuilder常用方法:

1.StringBuffer append(char c):添加参数到StringBuffer对象中
2.StringBuffer insert( int offset,String str):将字符串中的offset位置插人字符串str
3.StringBuffer deleteCharAt(int index):移除此序列指定位置的字符
4.StringBuffer delete(int start,int end):删除StringBuffer对象中指定范围的字符或字符串序列
5.StringBuffer replace( int start,int end,String s):在Stringuffer对象中替换指定的字符或字符串序列
6.void setCharAt(int index, char ch):修改指定位置index处的字符序列
7.String toString():返回StringBuffer缓冲区中的字符串
8.StringBuffer reverse():将此字符序列用其反转形式取代

在这里插入图片描述
在这里插入图片描述

常用方法总结:

增:append(xxx)
删:delete(int start ,int end)
改:setCharAt(int i,char ch)修改单个字符/replace(int start,int end ,String str):替换多个字符串
查:charAt(int i):查找制定索引处的字符
插:intsert(int offset ,xxx):将制定字符从哪里开始插入
长度:length();
遍历:for() + charAt(int i) /toString()

对比三者的效率:

从高到低排列:StringBuilder > StringBuffer > String

猜你喜欢

转载自blog.csdn.net/weixin_38568503/article/details/113794751
今日推荐