当前位置: 首页 > news >正文

字符串(java不死)

第十一天

因为拉了几天,两天全补回来了

字符串

1.String、String StringBuffer 和 StringBuilder 的区别是什么?

  1. String是只读字符串,它并不是基本数据类型,而是一个对象。1.8之前从底层源码来看是一个final类型的 字符数组,1.8后使用final类型的byte数组加上编码标志字段,所引用的字符串不能被改变,一经定义,无法再增删改。每次对String的操作都会生成 新的String对象。

  2. StringBuffer和StringBuilder他们的底层都是可变的字符数组,所以在进行频繁的字符串操作时,建议使用StringBuffer和 StringBuilder来进行操作。

  3. 另外StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所 以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。

2.字符串常量池是如何实现的?

  1. 字符串常量池(String Constant Pool)是Java中一块特殊的内存区域,用于存储字符串常量。

  2. 当程序中出现字符串常量时,Java编译器会将其放入字符串常量池中。字符串常量是不可变的,因此可以共享。如果字符串常量池中已存在相同内容的字符串,编译器会直接引用已存在的字符串常量,而不会创建新的对象。

  3. 在HotSpot虚拟机中:在JDK 1.6及之前的版本,字符串常量池通常被实现为方法区的一部分,即永久代(Permanent Generation),用于存储类信息、常量池、静态变量、即时编译器编译后的代码等数据。

  4. 从JDK 1.7开始,字符串常量池的实现方式发生了重大改变。字符串常量池不再位于永久代,而是直接存放在堆(Heap)中,与其他对象共享堆内存。之所以要挪到堆内存中,主要原因是因为永久代的 GC 回收效率太低,只有在FullGC的时候才会被执行回收。但是Java中往往会有很多字符串也是朝生夕死的,将字符串常量池放到堆中,能够更高效及时地回收字符串内存

3.字符串常量池,不可变和共享的理解?

/***  字符串的拼接以及常量池*  1. 字符串常量池:*      jvm为了提升性能和减少内存开销,专门为字符串的一些操作,在内存中专门提供了*      一块区域,用于存储字符串对象。该内存区域就是字符串常量池(字符串缓冲区,缓冲池)**      什么时候会用到字符串常量池?*      当使用字面量给变量赋值时,会先去常量池中寻找是否该字面量的对象,如果有,就将其地址直接*      给变量。如果没有,就将该字面量对象创建在常量池中,然后将其地址赋值给变量。*/
public class StringDemo01 {public static void main(String[] args) {String s1 = "abc"; //String s2 = "abc"; ////判断s1和s2的对象地址是不是同一个System.out.println(s1 == s2); //true/** 两个字面量做拼接操作时,编译器在编译期间就做了优化操作* 直接计算出结果,即s3="abcd"*/String s3 = "abc"+"d";String s4 = "abcd";System.out.println(s3 == s4); //true
​String s5 = "d";// 拼接操作只要有变量参与,那么javac不会进行优化。只能在运行期间进行计算,// 计算后的结果,存储在堆中,并不是常量池里String s6 = "abc"+s5;System.out.println(s6 == s4); //false
​String s7 = "ab"+"c"+s5;  // 优化成了"abc"+s5. 但是依然在运行期间与s5做的计算. 不会去堆里找,是新对象System.out.println(s7 == s6); // false
​String s8 = new String("d");String s9 = "abc"+s8;System.out.println(s7 == s9);//false
​String s10 = new String("abc");String s11 = new String("abc");System.out.println(s10 == s11);//falseString s15 = new String("abc");String s16 = "abc";System.out.println(s15 == s16);//false1. String s11 = "abc" 的创建过程JVM会首先检查字符串常量池中是否存在"abc"这个字符串对象如果不存在,则在字符串常量池中创建一个新的"abc"字符串对象如果已存在,则直接返回常量池中该对象的引用s11直接指向字符串常量池中的这个对象2. String s10 = new String("abc") 的创建过程同样会先检查字符串常量池中是否存在"abc"无论常量池是否存在,都会在堆内存中创建一个新的String对象这个新对象的内容与常量池中的"abc"相同,但是是独立的对象s10指向堆内存中的这个新对象字符串常量池: "abc"  <--- s11指向这里↑ | (复制关系,不是同一对象)堆内存:   String对象  <--- s10指向这里 (包含从常量池复制的value数组)//假如只有下面三行代码:问 内存中总共有多少个对象   5个对象String s12 = "h";String s14 = "abc"+s12+"o";String s13 = new String(s14);}
}
序号构造器解析
1String()初始化一个新创建的空字符序列的字符串对象
2String(String str)初始化一个新创建的字符串对象,使其字符序列与参数相同。换句话说,新创建的对象是该参数的副本
3String(byte[] bytes)使用默认编码集解码byte数组,构建一个字符串对象
4String(byte[] bytes,String charsetName)使用指定编码集charsetName 解码byte数组,构建一个字符串对象
5String(byte[] bytes, int offset, int length)使用默认编码集解码byte数组的从offset开始,length个元素,构建一个字符串对象
6String(char[] value)初始化一个字符串对象,使其字符序列包含参数的元素
String concat(String str)将this字符串与字符串str进行拼接,返回一个新的字符串对象。 相当于 两个字符串使用+号做拼接操作
static String join(String delimiter,String... elements)将指定的所有字符串元素使用delimiter字符连接起来,返回一个新的字符串
int length()返回字符串中的字符个数。 注意与数组的length区分开。
char charAt(int index)返回指定索引处的char字符
int indexOf(String subStr)返回指定字符串在此字符串中第一次出现的索引,找不到返回-1
int indexOf(String str,int fromIndex)从指定位置fromIndex开始向后检索,返回指定字符串在此字符串中第一次出现的索引,找不到返回-1
int lastIndexOf(String str)用于返回指定字符串在此字符串中最后一次出现的索引,找不到返回-1
int lastIndexOf(String str,int endIndex)从开始检索到指定位置endIndex,用于返回指定字符串在此字符串中最后一次出现的索引,找不到返回-1
String toUpperCase()将字符串中的所有字母转换成大写
String toLowerCase()将字符串中的所有字母转换成小写
char[] toCharArray()将字符串转变成字符数组
boolean startsWith(String str)检查一个字符是否以指定的字符串为前缀
boolean endsWith(String str)检查一个字符是否以指定的字符串为后缀
String substring(int beginIndex)从指定位置beginIndex开始截取,截取到最后一个字符,并返回
String substring(int beginIndex,int endIndex)从指定位置beginIndex开始截取,截取到指定位置endIndex,并返回,包前不包后。
String trim()去掉一个字符串的前与后的空字符,不会去掉中间的空字符
String replace(String target,String replacement)使用replacement字符串替换掉target字符串
byte[] getBytes()
byte[] getBytes(String charset)
boolean isEmpty()
boolean contains(String subStr)
int compareTo(String str)
int compareToIgnoreCase(String str)
static String valueOf(int value)将其他类型转换成字符串类型
static String valueOf(double d)
static String valueOf(char[] ch)
static String valueOf(Object obj)
boolean matches(String regex)
String[] split(String regex)
replaceAll(String regex, String replacement)
replaceFirst(String regex, String replacement)

4.StringBuilder和StringBuffer

  1. StringBuilder():构造一个不带任何字符的字符串生成器,其初始容量为16个字符

  2. StringBuilder(String str):构造一个字符串生成器,其初始化为指定的字符串内容

常用方法作用
StringBuilder append(String str)将指定字符串追加到this字符串后面,返回this
StringBuilder insert(int index,String str)将指定字符串插入到this字符串的指定索引处,返回this
StringBuilder delete(int start, int end)删除字符串中的一部分
StringBuilder reverse()将字符序列进行反转(左右颠倒)
String toString()将StringBuilder对象转变成String对象

5.以下代码创建了几个 String 对象?

String s1 = new String("hello");
String s2 = "hello";
  1. 如果常量池中没有字符串hello,String s1 = new String("hello");他会在常量池和堆内存创建对象,如果有字符串hello,就会在堆中创建对象并且将字符串中的值复制过来。

  2. 如果常量池中有字符串hello,String s2 = "hello";就不会在字符串创建对象,如果常量池中没有字符串hello就会在常量池创建对象。

6.equals() 和 equalsIgnoreCase() 方法有什么区别

方法区分大小写比较规则适用场景
equals()完全匹配(包括大小写)需要精确匹配时
equalsIgnoreCase()忽略大小写比较不关心大小写时

7.如何比较两个字符串的大小?有哪些方法?

  • 使用 compareTo() 方法最常用的字符串比较方法,按字典顺序比较:

  • 使用 compareToIgnoreCase() 方法忽略大小写的比较:

  • 使用 Comparator 接口

  • 使用 Arrays.sort() 对字符串数组排序

8.如何将字符串转换为基本数据类型(int, double等)?

  • 方法1:使用Integer.parseInt()

String str = "123";
int num = Integer.parseInt(str);
  • 方法2:使用Integer.valueOf()

int num = Integer.valueOf(str); // 返回Integer对象,自动拆箱为int

9.解释 String 的 intern() 方法的作用和使用场景。

intern()的作用

  • intern()`方法的作用是将字符串对象添加到字符串常量池(String Pool)中,并返回池中的引用

适合使用intern()的情况

  • 大量重复字符串处理:如处理CSV、XML等文本数据时

  • 作为Map的键:可以节省内存并提高比较速度

  • 长期存在的字符串:如配置项、常量等

  • 需要频繁比较的字符串:用==代替equals()提高性能

10.什么是不可变对象?为什么 String 要设计成不可变的?

  • 不可变对象是指一旦创建后其状态(属性值)就不能被修改的对象。任何修改操作都会创建一个新的对象,而不是改变原有对象。

  • 不可变对象的实现需要所有字段都是final的类本身是final的(防止子类修改行为)、没有修改内部状态的方法(setter)、对可变组件的防御性拷贝(如数组、集合等)

  • String 设计成不可变的,可以使线程安全,因为无需同步,字符串复用,减少对象的复用。

http://www.dtcms.com/a/311852.html

相关文章:

  • c++之基础B(进制转换)(第三课)
  • 详解Python标准库之并发执行
  • AI Agent开发学习系列 - LangGraph(3): 有多个输入的Graph
  • C#多数据库批量执行脚本工具
  • OneCode3.0 核心表达式技术深度剖析:从架构设计到动态扩展
  • 波士顿咨询校招面试轮次及应对策略解析
  • 双机并联无功环流抑制虚拟阻抗VSG控制【simulink仿真模型实现】
  • OneCodeServer 架构深度解析:从组件设计到运行时机制
  • 「iOS」————weak底层原理
  • Conda创建虚拟环境,解决不同项目的冲突!
  • Windows本地使用dify搭建知识库+ollama+deepseek
  • 从零打造大语言模型--处理文本数据
  • vue引入阿里巴巴矢量图库的方式
  • SpringBoot3.x入门到精通系列: 2.3 Web开发基础
  • sifu mod制作 相关经验
  • 11:java学习笔记:1D array(1维数组)
  • Windows下定位Mingw编译的Qt程序崩溃堆栈
  • Python科研数据可视化技术
  • 2025年常见网络安全问题及针对性预防措施
  • 小迪23年-22~27——php简单回顾(2)
  • pytorch的 Size[3] 和 Size[3,1] 区别
  • 动态规划Day7学习心得
  • 深入理解Linux线程:从概念到控制的最佳实践
  • jenkins从入门到精通-P1—九五小庞
  • Python编程基础与实践:Python函数编程入门
  • 基于Redis自动过期的流处理暂停机制
  • day38 力扣279.完全平方数 力扣322. 零钱兑换 力扣139.单词拆分
  • 位运算-371.两整数之和-力扣(LeetCode)
  • 2 安装 Docker 和 Jenkins:持续构建环境起步
  • Chisel芯片开发入门系列 -- 17. CPU芯片开发和解释7(5级流水线指令原理)