String类型详解

1. Java为何要创造String类

在C语言中,是没有String这个类型的,通常使用字符数组中存放一个个字符,再加上最后一个'\0'来表示/存放一个字符串.也可以使用一个字符指针指向字符串的首元素,直到遇到'\0'停止,再加上C语言头文件string.h中封装的函数,对于字符串的操作已经够用了.

Java为何要创建String类呢?因为Java是一种面向对象的语言,C语言的操作并不符合面向对象的思想,而是更注重底层的实现.因此,Java中创建了String类,将字符串作为了一个对象,符合"万物都是对象"的准则.

2. String是一种引用类型

何为引用,我们来举一个例子:

java 复制代码
String s = "hello world";

例如这么一条语句,我们实例化了一个String对象s,这个s内部并没有包含整个"hello world"字符串,而s中存储的是内存中存放"hello world"这个字符串的地址.这就是引用.

类比C语言中,这个s代表的含义是指向"hello world"中首元素'h'字符的char*类型字符指针.

3. 强大的String类型

String类型的引入减少了许多程序猿的工作量,String类内部封装了许多实用,功能强大的方法,对于String类型对象的操作也十分便捷.以下举几个例子,来体会一下:

3.1 字符串拼接

在Java中,Object类对于'+' 操作符进行了重载,当左右两个操作数有一个为字符串时,得到的结果就是一个两个量字面上拼接起来的字符串.这种操作的便捷是C程序猿可望而不可及的.

java 复制代码
//字符串+字符串
String s1 = "hello"+"world";// 等同于String s1 = "helloworld"
//字符串+整型
int a = 10;
String s2 = "123"+a;//等同于String s2 = "12310";

3.2 字符串查找

这里可以调用的方法比较多,直接列出常用方法,读者可以自己尝试:

java 复制代码
char charAt(int index) 返回index位置上字符,如果index为负数或者越界,抛出
IndexOutOfBoundsException异常

int indexOf(int ch) 返回ch第一次出现的位置,没有返回-1

int indexOf(int ch, int fromIndex) 从fromIndex位置开始找ch第一次出现的位置,没有返回-1

int indexOf(String str) 返回str第一次出现的位置,没有返回-1

int indexOf(String str, int fromIndex) 从fromIndex位置开始找str第一次出现的位置,没有返回-1

int lastIndexOf(int ch) 从后往前找,返回ch第一次出现的位置,没有返回-1

int lastIndexOf(int ch, int fromIndex)从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1

int lastIndexOf(String str) 从后往前找,返回str第一次出现的位置,没有返回-1

int lastIndexOf(String str, int fromIndex)从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返回-1

3.3 字符串替换

常用方法介绍:

java 复制代码
String replaceAll(String regex, String replacement) 替换所有的指定内容

String replaceFirst(String regex, String replacement) 替换收个内容

以下述代码为例:

java 复制代码
String str = "helloworld";
System.out.println(str.replaceAll("l", "_"));//"he__owor_d"
System.out.println(str.replaceFirst("l", "_"));//"he_loworld"

3.4 字符串分割

常用方法介绍:

java 复制代码
String[] split(String regex) 将字符串全部拆分

String[] split(String regex, int limit) 将字符串以指定的格式

以下述代码为例:

java 复制代码
String str = "hello world hello" ;
String[] result = str.split(" ") ; // 按照空格拆分
for(String s: result) {
    System.out.println(s);
}
//打印结果
hello
world
hello

3.5 字符串截取

java 复制代码
String substring(int beginIndex) 从指定索引截取到结尾
String substring(int beginIndex, int endIndex) 截取部分内容

这里使用时要注意,第二个方法使用时的参数取到的区间为左开右闭区间.

4. String类型的不可变性

String类型的不可变性是我们理解String类型特性的关键.

我们先来看一下String类型的源码(jdk8):

从这张图片中我们就可以看出,String类底层是使用一个char类型的value数组来维护字符串中的字符.该图还可以看出:

  1. String类被final修饰,表明该类不能被继承.
  2. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组(对应的关系不可以改变),但是其引用空间中的内容可以修改.

但是,即使如此,字符串仍然是不可变的,这也说明了上图中的两个final并非是字符串不可变的原因.

Java为了减少字符串对象的重复创建,在内存中开辟了一块空间----字符串常量池.

实际上,字符串设计成不可变就意味着,每当我们需要引用一个字符串时,会在字符串常量池中查找是否存在这个字符串常量.由于字符串不可变,因此要么这个字符串不存在,要么这个字符串只会在一个固定的地方,可以利用hashcode精准的定位.如果不存在,就在这个位置直接创建一个字符串常量然后引用,如果存在,直接引用即可.

字符串设计成不可变的好处(了解):

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

因此,我们应该尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下.

相关推荐
小安同学iter5 分钟前
Java进阶五 -IO流
java·开发语言·intellij-idea
尽兴-16 分钟前
Redis模拟延时队列 实现日程提醒
java·redis·java-rocketmq·mq
书埋不住我36 分钟前
java第三章
java·开发语言·servlet
boy快快长大38 分钟前
将大模型生成数据存入Excel,并用增量的方式存入Excel
java·数据库·excel
孟秋与你41 分钟前
【spring】spring单例模式与锁对象作用域的分析
java·spring·单例模式
菜菜-plus1 小时前
java 设计模式 模板方法模式
java·设计模式·模板方法模式
萨达大1 小时前
23种设计模式-模板方法(Template Method)设计模式
java·c++·设计模式·软考·模板方法模式·软件设计师·行为型设计模式
tian-ming1 小时前
(十八)JavaWeb后端开发案例——会话/yml/过滤器/拦截器
java·开发语言·前端
不能只会打代码1 小时前
大学课程项目中的记忆深刻 Bug —— 一次意外的数组越界
java·github·intellij-idea·话题博客
快意咖啡~1 小时前
java.nio.charset.MalformedInputException: Input length = 1
java·开发语言·nio