String、StringBuffer与StringBuilder类详解

您所在的位置:网站首页 string和steingbuilder String、StringBuffer与StringBuilder类详解

String、StringBuffer与StringBuilder类详解

2023-12-10 21:12| 来源: 网络整理| 查看: 265

目录 一、String简介:二、String的创建方式:面试题一:String s = new String("abc");方式创建对象,在内存中创建了几个对象?四、一个笔试题:五、字符串的常用方法:String和基本类型数据的转换:String 与char[]之间的转换:String 与byte[]之间的转换:String、StringBuffer与StringBuilder之间区别:String、StringBuffer与StringBuilder底层源码分析:String与StringBuffer/StringBuilder之间转换:总结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 } }

在这里插入图片描述

注意:jdk1.6的时候字符串常量池在方法区。 jdk1.7的时候,字符串常量池已经被安排在堆里面了。 jdk1.8中 字符串常量池是在堆里面。

二、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



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3