边学边记——Java中的String类

目录

一.认识String类

二.常用方法

1.字符串构造

a.使用字符串的常量直接赋值

b.通过字符串常量的构造方法

c.通过字符串数组进行构造

d.调用字符串的valueOf方法

注意

2.两个字符串对象的比较

compareTo方法的比较规则:

三.字符串常用的操作

1.查找

(1).在字符串中查找指定的字符

(2).contains方法

2.字符串转化

(1).valueOf方法

(2).大小写转化

(3).字符串转为字符数组

(4).格式化字符串

3.字符串的替换

4.字符串拆分

5.字符串截取

6.其他方法

7.举个例子

判断字符是否是数字字符

四.关于字符串常量的理解

字符串中的intern方法

五.字符串的不可变性

1.定义

2.示例

3.字符串对象的内容无法修改

六.StringBuffer和StringBuilder

1.介绍

2.常用方法(以StringBuilder为例)

3.与String类的转换(以StringBuilder为例)

(1).String->StringBuilder

(2).StringBuilder->String

4.String,StringBuilder,StringBuffer的区别


一.认识String类

  • String是Java中的字符串,字符串是一个特殊的对象,属于引用类型。

        在Java中,String类对象创建后,字符串一旦初始化就不能更改,因为string类中所有字符串都是常量,数据是无法更改,由于string对象的不可变,所以可以共享。对String类的任何改变,都是返回一个新的String类对象。 

二.常用方法

1.字符串构造

关于字符串的对象创建方法,常用的有四种方式:

a.使用字符串的常量直接赋值

//使用常量串构造
String s1="hhh";
System.out.println(s1);

b.通过字符串常量的构造方法

//直接newString对象
String s2=new String("hhh");
System.out.println(s2);

c.通过字符串数组进行构造

//使用字符数组进行构造
char[] array={'h','h','h'};
String s3=new String(array);
System.out.println(s3);

d.调用字符串的valueOf方法

//调用字符串的valueOf方法
String s4=String.valueOf("hhh");
System.out.println(s4);

边学边记——Java中的String类_第1张图片

注意

  • Java中String是引用数据类型,保存的只是地址。
  • 在Java中""括起来的都是字符串常量,也是String类型对象。

2.两个字符串对象的比较

(1).通过==比较。(比较的是两个字符串的地址,不看内容

(2).通过equals方法来比较两个字符串对象的内容是否相等(大小敏感)。(返回boolean

(3).通过equalsIgnoreCase比较两个字符串对象的内容是否相等(大小写不敏感)。(返回boolean

(4).通过compareTo方法来比较两个字符串对象的大小关系。(返回int)

compareTo方法的比较规则:

  • 首先按照两个字符串的字典序大小比较,若出现不相等的字符,直接返回两个字符的大小差值(字符编码差值)
  • 若前k个字符相等(k是两个字符长度的最小值),返回长度差。

三.字符串常用的操作

1.查找

常用方法总览:

方法 功能
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

(1).在字符串中查找指定的字符

char charAt(int index);

返回字符串中指定索引index位置的字符。

//字符串查找
String s1="hello";
//注意越界问题
char c=s1.charAt(2);
System.out.println(c);

边学边记——Java中的String类_第2张图片

注意:下标不要越界。 

(2).contains方法

boolean contains(String s);

判断字符串中是否有指定的字串,若有返回true,否则返回false。 

2.字符串转化

(1).valueOf方法

将其他类型转化为字符串对象,可以接收所有参数,当传入的是第三方对象时,默认调入toString方法。

String s1=String.valueOf(123);
String s2=String.valueOf(12.34);
String s3=String.valueOf(false);
//当传入的是第三方对象时,默认调入toString方法
String s4=String.valueOf(new Student("生菜虾",13));

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

边学边记——Java中的String类_第3张图片

(2).大小写转化

方法 功能
String toUpperCase() 字符串转大写
String toLowerCase() 字符串转小写
//大小写转换
String s1="aBcdE";
String s2="FghIj";
System.out.println(s1.toUpperCase());
System.out.println(s2.toLowerCase());

边学边记——Java中的String类_第4张图片

(3).字符串转为字符数组

a.转为字符数组

toCharArray();
//转为字符数组
String s1="hello";
char[] c=s1.toCharArray();
System.out.println(Arrays.toString(c));

边学边记——Java中的String类_第5张图片

b.转为字节数组getBytes(可以传入指定的字符编码)

getBytes(/*可以传入指定的字节编码*/);

(4).格式化字符串

//类似于C的printf,但是支持正则表达式
String.format();

//格式化输出
String str=String.format("%d-%d-%d",2022,10,2);
System.out.println(str);

边学边记——Java中的String类_第6张图片

3.字符串的替换

方法 功能
String replaceAll(String regex, String replacement) 替换所有的指定内容
String replaceFirst(String regex, String replacement) 替换收个内容

regex为替换前的内容,replacement为替换后的内容。 

//字符串替换
String str="hello world";
System.out.println(str.replaceAll("l","_"));
System.out.println(str.replaceFirst("l","_"));

边学边记——Java中的String类_第7张图片

4.字符串拆分

字符串的拆分,将一个字符串按照指定的格式拆分成数组。

注意:当碰到某些特殊字符无法正确拆分时,需要使用转义字符 \ 。

方法 功能
String[] split(String regex) 将字符串全部拆分
String[] split(String regex, int limit) 将字符串以指定的格式,拆分为limit组
//字符串拆分
String str="hello world hello Java";
String[] data1=str.split(" ");
String[] data2=str.split(" ",2);
System.out.println(Arrays.toString(data1));
System.out.println(Arrays.toString(data2));

边学边记——Java中的String类_第8张图片

5.字符串截取

方法 功能
String substring(int beginIndex) 从指定索引截取到结尾
String substring(int beginIndex, int endIndex) 截取部分内容

注意

  • 索引从0开始。
  • 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标。 
//字符串截取
String str="helloworld";
System.out.println(str.substring(5));
System.out.println(str.substring(5,9));

边学边记——Java中的String类_第9张图片

6.其他方法

方法 功能
String trim() 去掉字符串中的左右空格,保留中间空格
String toUpperCase() 字符串转大写
String toLowerCase() 字符串转小写

7.举个例子

判断用户输入的字符是否为纯数字字符,是则返回true,不是则返回false。

判断字符是否是数字字符

Character.isDigit(c);

char的包装类Character中,有一个静态方法,判断用户输入的字符串是否由纯数字组成,是则返回true,不是则返回false。 

public static boolean isDigit(String str){
        //边界条件,字符串为空null,或者内容为空
        if(str==null||str.length()==0){
            return false;
        }
        //将字符串拆分成一个一个字符来判断
        for(int i=0;i'9'){
//                return false;
//            }

        }
        //循环完成,没有退出,是纯数字字符
        return true;
    }

边学边记——Java中的String类_第10张图片

四.关于字符串常量的理解

采用直接赋值类似"String str=字符串字面量"的方式创建字符串对象,会使用字符串的常量池。

  • 若该对象是第一次使用,就在堆中开辟新空间,产生新对象,产生之后将该对象置入字符串的常量池。
  • 当下次再次使用该对象时(还是采用直接赋值的方式),若常量池中已有该内容的字符串,直接引用常量池中的对象,不再创建字符串。

只有直接赋值的方式会用到字符串的常量池。 

  • 池化思路:是程序设计中的常用思路,有字符串常量池,数据库常量池,线程池等等。
  • 看到池:节省内存,提高效率。字符串字面量经常会被重复利用,因此放入常量池,当再次使用该内容时,省去了创建对象,开辟内存的时间,直接复用已有对象。

eg: 

//常量池
String s="hello";
String s1="hello";
String s2=new String("hello");
String s3=new String("hello");
System.out.println(s==s1);//true
System.out.println(s==s2);//false
System.out.println(s==s3);//false

边学边记——Java中的String类_第11张图片

字符串中的intern方法

调用这个方法,若产生的字符串常量池中没有,则会将产生的字符串对象置入常量池,若常量池中已存在该对象,则返回常量池中的字符串对象引用。

注意:为了避免歧义,最好接收一下intern方法的返回值。 

//intern方法
String str="hello";
String str1="hello";
String str2=new String("hello");
String str3=str2.intern();
System.out.println(str==str1);//true
System.out.println(str==str2);//false
System.out.println(str==str3);//true

边学边记——Java中的String类_第12张图片

五.字符串的不可变性

1.定义

当一个字符串的对象产生后,他的内容就无法修改,这称之为字符串常对象的不可变性。

2.示例

我们来看如下程序的运行:

//字符串对象的不可变性
String str="hello";
str+="world";
str+="!!!";
//这里其实是字符串的引用在改变,实际字符串的对象并没有改变
System.out.println(str);

边学边记——Java中的String类_第13张图片

可以发现,这里的字符串对象好像 " 变了 " ,但是实际上,我们都知道字符串在Java中是引用数据类型,所以这里并不是字符串对象改变了,而是字符串的引用改变了!

画图理解: 

边学边记——Java中的String类_第14张图片

3.字符串对象的内容无法修改

问:如何理解字符串对象不可变,是如何做到内容无法修改的?

来看一下String的源码:

边学边记——Java中的String类_第15张图片

value字符数组就是用来保存字符串的内容的。

可以看到,字符数组被private和final关键字所修饰,这时很多人都会认为,是final关键字导致了字符数组不能再被修改,实则不然,final关键字的作用是为了保证字符串对象的线程安全问题,final修饰引用数据类型的变量,不能修改这个引用的指向,但是内容还是可变的!

final关键字的介绍及用法可查阅:final关键字的介绍及用法

示例

边学边记——Java中的String类_第16张图片

边学边记——Java中的String类_第17张图片

final char[] c={'a','b','c'};
//内容可以改变
c[0]='h';
System.out.println(Arrays.toString(c));
//引用无法改变
//char[] c1={'e','f','g'};
//c=c1;

那么是什么导致字符串对象的内容不可变呢?

根本就在于private关键字的修饰,当一个类中的某个被private修饰的属性或方法我们想要进行调用时,就需要调用该类提供的能够获取该属性的方法(getter和setter方法),否则外部无法对其进行操作。

在String类中,把value数据完全封装,对外没有提供任何获取或修改其内容的方法,因此字符串对象一旦产生,内容就无法修改!

这样做的目的是什么呢?

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

String类上一把刀,他的对象不可变

我们现在知道,String类的对象是无法修改的,那么当我们想要修改字符串对象时,在String类中,所有的修改都会创建新对象,效率非常低下。所以,要尽量避免直接对String类型对象进行修改。

那如果某个场景需要反复修改字符串内容,该如何操作呢?

推荐使用Java提供的StringBuffer或者StringBuilder。

六.StringBuffer和StringBuilder

1.介绍

  • StringBuffer:线程安全,效率低,适用于10%需要保证线程安全的场景。
  • StringBuilder:线程不安全,效率高,适用于90%的场景。

2.常用方法(以StringBuilder为例)

方法 说明
StringBuff append(String
str)
在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、
double、float、int、long、Object、String、StringBuff的变量
char charAt(int index) 获取index位置的字符
int length() 获取字符串的长度
int capacity() 获取底层保存字符串空间总的大小
void ensureCapacity(int
mininmumCapacity)
扩容
void setCharAt(int index,
char ch)
将index位置的字符设置为ch
int indexOf(String str) 返回str第一次出现的位置
int indexOf(String str, int
fromIndex)
从fromIndex位置开始查找str第一次出现的位置
int lastIndexOf(String str) 返回最后一次出现str的位置
int lastIndexOf(String str,
int fromIndex)
从fromIndex位置开始找str最后一次出现的位置
StringBuff insert(int
offset, String str)
在offset位置插入:八种基类类型 & String类型 & Object类型数据
StringBuffer
deleteCharAt(int index)
删除index位置字符
StringBuffer delete(int
start, int end)
删除[start, end)区间内的字符
StringBuffer replace(int
start, int end, String str)
将[start, end)位置的字符替换为str
String substring(int start) 从start开始一直到末尾的字符以String的方式返回
String substring(int
start,int end)
将[start, end)范围内的字符以String的方式返回
StringBuffer reverse() 反转字符串
String toString() 将所有字符按照String的方式返回

3.与String类的转换(以StringBuilder为例)

(1).String->StringBuilder

a.通过StringBuilder构造方法

b.通过StringBuilder的append方法

//String->StringBuilder
//a.通过StringBuilder构造方法
String str="hello";
StringBuilder s=new StringBuilder(str);
System.out.println(s);

//b.通过StringBuilder的append方法
StringBuilder s1=new StringBuilder();
s1.append(str);
System.out.println(s1);

边学边记——Java中的String类_第18张图片

(2).StringBuilder->String

调用toString方法

//StringBuilder->String
//调用toString方法
StringBuilder s2= new StringBuilder("abc");
String ret=s2.toString();
System.out.println(ret);

边学边记——Java中的String类_第19张图片​​​​​​​

4.String,StringBuilder,StringBuffer的区别

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

如有建议或想法,欢迎一起讨论交流~ 

你可能感兴趣的:(学习记录,java,jvm,开发语言,学习,经验分享)