Java之字符串

1.String类介绍

Java中的String类是Java核心类库java.lang包中的一部分。String类代表了字符串,它是一个不可变类,这意味着一旦创建了一个字符串,就不能改变它
(注:JDK1.8以前String类内部数组定义的是字符数组,JDK1.9之后String类内部数组定义的是字节数组)

2.字符串常量

(1)定义方式
Java支持使用"符号进行字符串常量的定义,这种字符串常量的定义本质上是一个String类的匿名对象

(2)字符串常量的使用案例

String password = null;//假设密码由用户输入
if(password.equals("正确的密码内容")){
	System.out.println("登录成功");
}
/**
 *注:
 * 1.由于用户没有输入密码,password为null,null对象调用方法的结果会出现NullPointerException异常
 *   将代码改成"正确的密码内容".equals(password)则可避免这个问题
 * 2.equals()方法是String类中定义的方法,类中的普通方法只有实例化对象才可以调用,在下面的代码中,
 *   "正确的密码内容"调用了equals()方法,可见"正确的密码内容"是一个String类的匿名对象
 */

3.String类的实例化

(1)直接赋值实例化String类对象

String str = "直接赋值实例化String类对象";

JVM底层存在一个对象池(String只是对象池中保存的一种类型),代码中采用直接赋值的方式定义了一个String类对象时,会将此字符串对象所使用的匿名对象自动入池保存,如果后续其他String类对象也采用了直接赋值的方式,并且设置了同样的内容,那么将不会开辟新的堆内存空间,而是使用已有的对象进行引用分配,从而继续使用

(2)构造方法实例化String类对象

String str = new String("构造方法实例化String类对象");

因为每一个字符串都是一个String类的匿名对象,所以首先会在堆内存中开辟一块空间保存匿名对象的字符串内容,而后又使用关键字new,开辟另一块堆内存空间,而真正使用的是用关键字new开辟的堆内存,而之前定义的字符串常量开辟的堆内存空间将不会被任何的栈内存指向,称为垃圾空间,并等待GC回收
(注:使用构造方法实例化的String类对象可以使用intern()方法手动保存到对象池)

4.boolean equals(Object obj)和==的区别

(1)boolean equals(Object obj)
比较的是String类对象的字符串内容

(2)==
比较的是String类对象的堆内存地址

5.String类对象的字符串内容修改分析

String类对于数据的存储是基于数组实现的,数组本身属于定长的数据类型,表明String对象的内容一旦声明将不可直接改变,而所有的字符串对象内容的修改(即利用+符号拼接字符串)都是通过引用的变化来实现的,这样的修改会造成垃圾内存的产生

6.字符串常量池(对象池)

(1)字符串常量池介绍
Java中使用"符号可以进行字符串常量的定义,如果处理不当就有可能为多个内容相同的实例化对象重复开辟堆内存空间,这样必然造成内存的大量浪费。为了解决这一问题,在JVM中提供了一个字符串常量池(本质是一个动态对象数组),所有通过直接赋值实例化的String类对象都可以自动保存在此常量池中,以供下次重复使用

(2)字符串常量池的分类

  • 静态常量池:指class文件在加载的时候会自动将文件中保存的字符串,普通的常量,类和方法等信息,全部进行分配
String strA = "Java";
String strB = "J" + "a" + "va";
System.out.println(strA == strB);//判断结果为true
/**
*这段代码使用了两种方式定义了String类对象,由于在实例化strB对象时,所有参与连接的字符串都是常量,
*所以在程序编译时会将这些常量组合在一起定义,这样就与strA对象的内容相同,最终的结果就是继续使用字
*符串常量池中提供的内容为strB实例化,不会再开辟新的堆内存*空间
*/
  • 运行时常量池:指.class文件加载之后,有一些字符串内容是通过String对象的形式保存后再实现字符串连接处理
String temp = "a";
String strA = "Java";
String strB = "J" + temp + "va";
System.out.println(strA == strB);//判断结果为false
/**
*这段代码使用了一个temp变量定义了要连接的字符串内容,由于temp属于文件运行时才可以确定的内容,这样
*就使得文件编译时无法知道temp的具体内容,所以strB对象无法从字符串常量池中获取字符串引用
*/

7.StringBuffer类

(1)StringBuffer类介绍
JDK为了方便程序员修改字符串的内容提供了StringBuffer类,StringBuffer类并不像String类那样可以直接通过声明字符串常量的方式进行实例化,而是必须像普通类对象使用一样,首先通过构造方法进行对象实例化,而后才可以调用方法执行处理

(2)StringBuffer类常用方法

  • StringBuffer():创建一个空的StringBuffer对象
  • StringBuffer(String str):将接收到的String内容变为StringBuffer内容
  • StringBuffer append(数据类型 变量):内容连接,等价于String中的“+”操作
  • StringBuffer insert(int offset,数据类型 变量):在指定索引位置插入数据
  • StringBuffer delete(int start,int end):删除指定索引范围之内的数据
  • StringBuffer reverse():内容反转

(3)StringBuffer类和StringBuilder类的区别
StringBuffer类中的方法使用了synchronized关键字定义,是线程安全的,性能相对较低,而StringBuilder类中的方法没有使用synchronized关键字定义,是线程不安全的,性能相对较高
StringBuffer类的append()方法在拼接字符串时有内存开销。每次调用append()方法时,Java都会在内存中创建一个新的字符串对象,然后将两个字符串的文本内容复制到新的字符串对象中。StringBuilder类与StringBuffer类类似,但是没有公共的实例变量,因此可以更有效地使用内存。StringBuilder类的append()方法直接在现有的字符串对象上进行操作,而不需要创建新的对象,因此可以更高效地处理字符串拼接操作。

你可能感兴趣的:(Java语法,java,开发语言)