七、 认识 String 类

🚀 一、String 类的常用方法

🌟 1.1 字符串构造

String 类提供的构造方法,常用的有以下三种:

// 使用常量串构造
String s1 = "hello";

// 直接 new 一个 String 对象
String s2 = new String("hello");

// 使用字符数组进行构造
char[] str = {'h','e','l','l','o'};
String s3 = new String(str);

❗ 注意 :

  1. String 是引用类型,内部存储的不是字符串本身,而是字符串在堆区中的地址。
String s1 = new String("hello");
String s2 = new String("world");
String s3 = s1;
// s1 和 s3 引用的是同一对象

在这里插入图片描述

  1. 在Java中“”引起来的也是String类型对象。
// 打印"hello"字符串(String对象)的长度
System.out.println("hello".length());

🌟 1.2 String 对象的比较

字符串的比较是是常见的操作。Java 中总共提供了 4 种方式:
1.== 比较是否引用同一个对象
注意:对于基本变量,‘ == ’比较的是变量的值;对于引用类型,比较的是引用中的地址是否相同。

int a = 10;
int b = 20;
int c = 10;
// 对于基本类型变量,==比较两个变量中存储的值是否相同
System.out.println(a == b); // false
System.out.println(a == c); // true


// 对于引用类型变量,==比较两个引用变量引用的是否为同一个对象
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = new String("world");
String s4 = s1;

System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // false
System.out.println(s1 == s4); // true
  1. equals(String str) 方法:按照字典序比较
    String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals方法后,按照如下规则进行比较,比如: s1.equals(s2).
public boolean equals(Object o1){
	// 1. 先检测 this 和 o1 是否是同一对象的比较,如果是,返回 true。
	if(this == o1){
		return true;
	}	

	// 2. 检测 o1 是否是 String 类的对象,如果是,继续比较。
	if(o1 instanceof String){
		// 将 o1 向下转型为 String 类
		String s1 = (String)o1;
		int n = this.value.length;

		// 3. 检测 this 和 s1 字符串长度是否相同,相同就继续比较
		if(n==s1.value.length){
			char[] v1 = this.value;
			char[] v2 = s1.value;
			
			// 4. 按照字典序,从前往后逐个字符比较
			int i = 0;
			while(n-- != 0){
				if(v1[i] != v2[i]){
					return false;
				}
				i++;
			}
			// 5. 检测完毕,两字符串值相同
			return true;
		}
	}
	return false;
}
public static void main(String[] args) {
	String s1 = new String("hello");
	String s2 = new String("hello");
	String s3 = new String("Hello");
	
	// s1、s2、s3引用的是三个不同对象,因此==比较结果全部为false
	System.out.println(s1 == s2); // false
	System.out.println(s1 == s3); // false
	
	// equals比较:String对象中的逐个字符
	// 虽然s1与s2引用的不是同一个对象,但是两个对象中放置的内容相同,因此输出true
	// s1与s3引用的不是同一个对象,而且两个对象中内容也不同,因此输出false
	System.out.println(s1.equals(s2)); // true
	System.out.println(s1.equals(s3)); // false
}
  1. compareTo(String str) 方法:按照字典序进行比较。
    与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。具体比较方式:
    1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
    2. 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值
public static void main(String[] args) {
	String s1 = new String("abc");
	String s2 = new String("ac");
	String s3 = new String("abc");
	String s4 = new String("abcdef");
	
	System.out.println(s1.compareTo(s2)); // 不同输出字符差值-1
	System.out.println(s1.compareTo(s3)); // 相同输出 0
	System.out.println(s1.compareTo(s4)); // 前k个字符完全相同,输出长度差值 -3
}

4.compareToIgnoreCase(String str) 方法:
与 compareTo 方式相同,但是忽略大小写比较。

🌟 1.3 字符串查找

在这里插入图片描述

🌟 1.4 转化

  1. 字符串转数值
public static void main(String[] args) {
	// 数组转字符串
	String s1 = String.valueOf(1234);
	String s2 = String.valueOf(12.34);
	String s3 = String.valueOf(true);

	System.out.println(s1);
	System.out.println(s2);
	System.out.println(s3);

	// 字符串转数字, Integer,Double 为包装类型
	int data1 = Integer.parseInt("1234");
    double data2 = Double.parseDouble("65.984");
	System.out.println(data1);
	System.out.println(data2);
}
  1. 大小写转换
public static void main(String[] args) {
	String s1 = "abcd";
	String s2 = s1.toUpperCase();
	String s3 = s2.toLowerCase();

	System.out.println(s2);
	System.out.println(s3);
	// ABCD
	// abcd
}
  1. 字符串转数组
public static void main(String[] args) {
        String s1 = "hello world!";

        // 字符串转字符数组
        char[] ch = s1.toCharArray();
        
        for(int i=0;i<ch.length;i++){
            System.out.print(ch[i]);
        }
        System.out.println();

        // 字符数组转字符串
        String s2 = new String(ch);
        
        System.out.println(s2);
}

// hello world!
// hello world!

🌟 1.5 字符串替换

使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:
在这里插入图片描述

public static void main(String[] args) {
        String s1 = "hello";
        System.out.println(s1.replaceAll("l","_"));
        System.out.println(s1.replaceFirst("l","_"));
}

// he__o	
// he_lo


注意事项: 由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串。所有String方法,如果返回值是 String 类型,一定产生了新对象。

🌟 1.6 字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。
在这里插入图片描述

str.split(',');
// // 以 ',' 完全分割。

str.split(',',3);
// 以 ',' 分割,总共分成 3 组。

拆分是特别常用的操作. 一定要重点掌握. 另外有些特殊字符作为分割符可能无法正确切分, 需要加上转义。

String str = "192.168.1.1" ;
String[] result = str.split("\\.") ;

for(String s: result) {
	System.out.println(s);
}

// 192
// 168
// 1
// 1

注意事项:

  1. 字符 ’ | ’ , ’ * ’ , ’ + ’ ,都要进行转义,前面加上 " \ "。
  2. 而如果是 " \ " ,那么就得写成 “\\\\”

🌟 1.7 字符串截取

在这里插入图片描述

String str = "helloworld" ;
System.out.println(str.substring(5));
System.out.println(str.substring(0, 5));

// world
// hello

注意:

1.索引从 0 开始。
2. 注意前闭后开的写法,substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标。

🚀 二、 字符串常量池

🌟 2.1 对于创建对象的思考

下面两种创建 String 对象的方式相同吗?

public static void main(String[] args) {
	String s1 = "hello";
	String s2 = "hello";
	String s3 = new String("hello");
	String s4 = new String("hello");
	
	System.out.println(s1 == s2); // true
	System.out.println(s1 == s3); // false
	System.out.println(s3 == s4); // false

	// s1 与 s2 是一个对象
	// s3 与 s4 不是同一个对象
	// 为什么呢?
}

在Java程序中,类似于:1, 2, 3,3.14,“hello”等字面类型的常量经常频繁使用,为了使程序的运行速度更快、更节省内存,Java为8种基本数据类型和 String 类都提供了常量池。

" 池 " 是编程中一种常见的、重要的提升效率的方式,我们以后会遇到各种 “ 内存池” ,“ 线程池 ”,“ 数据库连接池 ”。

为节省存储空间及提高程序运行效率,Java 中引入了:

  1. class 文件常量池:每个 .Java 源文件编译后生成 .Class 文件中会保存当前类中的字面常量以及符号信息。
  2. 运行时常量池:在 .Class 文件被加载时,.Class 文件中的常量池被加载到内存中称为运行时常量池,运行时常量池每个类都有一份。
  3. 字符串常量池:主要存放的是字符串常量,本质是一个哈希表,StringTable。

🌟 2.2 字符串常量池(StringTable)

字符串常量池在JVM中是StringTable类,实际是一个固定大小的HashTable。不同 JDK 版本下字符串常量池的位置以及默认大小是不同的。
在这里插入图片描述

🌟 2.3 再谈 String 对象的创建

基于Java8 HotSpot分析

  1. 直接使用字符串常量赋值。
String s1 = "hello";
String s2 = "hello";
s1==s2 ?
// true

在这里插入图片描述
2. 通过 new 创建 String 对象

String s1 = "hello";
String s2 = "hello";
String s3 = new String("world");
String s4 = new String("world");

在这里插入图片描述
结论:
只要是 new 出来的对象,都是唯一的。使用常量串创建 String 类型对象的效率更高,更节省空间。

  1. intern() 方法
    intern 是一个 native 方法( Native方法指:底层使用C++实现的,看不到其实现的源代码 ),该方法的作用是手动将创建的String对象添加到常量池中。
public static void main(String[] args) {
	char[] ch = new char[]{'a', 'b', 'c'};
	String s1 = new String(ch); // s1对象并不在常量池中
	//s1.intern(); 				// s1.intern();调用之后,会将s1对象的引用放入到常量池中
	String s2 = "abc"; 			// "abc" 在常量池中存在了,s2创建时直接用常量池	中"abc"的引用
	System.out.println(s1 == s2);
} 

// 输出false
// 将上述方法打开之后,就会输出true

⛅⛅⛅

String 类中几种对象实例化的区别:

  1. String str = " hello "
    只会开辟一块堆内存空间,保存在字符串常量池中,然后 str 共享常量池中的 String 对象。

  2. String str = new String(" hello ")
    会开辟两块堆内存空间,字符串 " hello " 保存至字符串常量池,然后用常量池中的 String 对象给新开辟的 String 对象赋值。

  3. String str = new String(new char[]{‘h’, ‘e’, ‘l’, ‘l’, ‘o’})
    先在堆上创建一个 String 对象,然后利用 copyOf 重新开辟数组空间,将参数字符串数组中内容拷贝到 String 对象中。

🚀 三、字符串的不可变性

String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为:

  1. String类在设计时就是不可改变的,String类实现描述中已经说明了
    在这里插入图片描述
    🌕🌕
    String类中的字符实际保存在内部维护的value字符数组中,该图还可以看出:

    1. String 类被 final 修饰,表明该类不能被继承。
    2. value 被修饰符 final 修饰,表明 value 自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改。
  2. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,返回新对象。

为什么 String 类要设计为不可变的?有什么好处?

  1. 方便实现字符串常量池。如果 String 可变,那么对象池就要考虑拷贝的问题。
  2. 不可变对象是线程安全的。
  3. 不可变内存方便缓存 hashcode 对象,作为 key 时可以更高效保存到 HashMap中。

🚀 四 、StringBuffer 和 StringBuilder

🌟 4.1 StringBuilder 的介绍

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大部分功能是相同的,这里介绍 StringBuilder常用的一些方法。
在这里插入图片描述
在这里插入图片描述
从上述例子可以看出:String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder。

注意:String 和 StringBuilder 不能直接转换,但是可以调用下面的方法

  1. String 转换为 StringBuilder :利用 StringBuilder 的构造方法或者 append() 方法。
  2. StringBuilder 转换为 String :调用 toString() 方法。

🌟 4.2 常见问题

1. String 、StringBuffer、StringBuilder 的区别?

  • String 内容不可修改,StringBuffer 和 StringBuilder 内容可以修改。
  • StringBuffer 和 StringBuilder 大部分功能是相同的。
  • StringBuffer 采用同步处理,属于线程安全操作;StringBuilder 未采用同步处理,属于线程不安全操作

2.以下代码总共创建了几个对象?

String str = new String("ab");				// 创建多少对象?
String str = new String("a") + String("b");	// 创建多少对象?

// 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
string STL(标准模板库)是C++标准库中的一部分,用于处理字符串的模板。该提供了一系列接口,用于操作字符串。string的底层实际上是基于basic_string模板的别名,typedef basic_string<char, char_traits, allocator> stringstring可以通过多种方式进行构造,比如构造空字符串、拷贝字符串序列、复制字符等。另外,string还提供了查找子串的功能,可以截取给定字符串中从指定位置开始的指定长度的字符。总的来说,string STL是C++中处理字符串的一个重要工具。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【C++】-- STL之String详解](https://blog.csdn.net/gx714433461/article/details/124539134)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [STL与string认识及简单使用](https://blog.csdn.net/m0_54469145/article/details/130730972)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值