String类

简介: String类

一.String类中的常用方法

0872b1c32d0c40d2b4698952336c2079.png

02b43123012c4debbf021aad33293e38.png

85515e650e6f42f396b7b7feb9b23ee0.png

5a72f840c2d947da932e7bde77588162.png

public boolean equals ( Object anObject ) {

// 1. 先检测 this 和 anObject 是否为同一个对象比较,如果是返回 true

if ( this == anObject ) {

return true ;

}

// 2. 检测 anObject 是否为 String 类型的对象,如果是继续比较,否则返回 false

if ( anObject instanceof String ) {

// 将 anObject 向下转型为 String 类型对象

String anotherString = ( String ) anObject ;

int n = value . length ;

// 3. this 和 anObject 两个字符串的长度是否相同,是继续比较,否则返回 false

if ( n == anotherString . value . length ) {

char v1 [] = value ;

char v2 [] = anotherString . value ;

int i = 0 ;

// 4. 按照字典序,从前往后逐个字符进行比较

while ( n -- != 0 ) {

if ( v1 [ i ] != v2 [ i ])

return false ;

i ++ ;

}

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

}

3. int compareTo(String s) 方法 : 按照 字典序进行比较

与 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. int compareToIgnoreCase(String str) 方法:与 compareTo 方式相同,但是忽略大小写比较


2.3 字符串查找

public static void main ( String [] args ) {

String s = "aaabbbcccaaabbbccc" ;

System . out . println ( s . charAt ( 3 )); // 'b'

System . out . println ( s . indexOf ( 'c' )); // 6

System . out . println ( s . indexOf ( 'c' , 10 )); // 15

System . out . println ( s . indexOf ( "bbb" )); // 3

System . out . println ( s . indexOf ( "bbb" , 10 )); // 12

System . out . println ( s . lastIndexOf ( 'c' )); // 17

System . out . println ( s . lastIndexOf ( 'c' , 10 )); // 8

System . out . println ( s . lastIndexOf ( "bbb" )); // 12

System . out . println ( s . lastIndexOf ( "bbb" , 10 )); // 3

2.4 转化

1. 数值和字符串转化

public static void main ( String [] args ) {

// 数字转字符串

String s1 = String . valueOf ( 1234 );

String s2 = String . valueOf ( 12.34 );

String s3 = String . valueOf ( true );

String s4 = String . valueOf ( new Student ( "Hanmeimei" , 18 ));

System . out . println ( s1 );

System . out . println ( s2 );

System . out . println ( s3 );

System . out . println ( s4 );

System . out . println ( "=================================" );

// 字符串转数字

// 注意: Integer 、 Double 等是 Java 中的包装类型,这个后面会讲到

int data1 = Integer . parseInt ( "1234" );

double data2 = Double . parseDouble ( "12.34" );

System . out . println ( data1 );

System . out . println ( data2 );

2. 大小写转换

3. 字符串转数组

4. 格式化

2.5 字符串替换

使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:

System . out . println ( s1 );

System . out . println ( s2 );

System . out . println ( s3 );

System . out . println ( s4 );

System . out . println ( "=================================" );

// 字符串转数字

// 注意: Integer 、 Double 等是 Java 中的包装类型,这个后面会讲到

int data1 = Integer . parseInt ( "1234" );

double data2 = Double . parseDouble ( "12.34" );

System . out . println ( data1 );

System . out . println ( data2 );

}

public static void main ( String [] args ) {

String s1 = "hello" ;

String s2 = "HELLO" ;

// 小写转大写

System . out . println ( s1 . toUpperCase ());

// 大写转小写

System . out . println ( s2 . toLowerCase ());

}

public static void main ( String [] args ) {

String s = "hello" ;

// 字符串转数组

char [] ch = s . 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 );

}

4.格式化

public static void main ( String [] args ) {

String s = String . format ( "%d-%d-%d" , 2019 , 9 , 14 );

System . out . println ( s );

}

2.5 字符串替换

使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:


代码示例 : 字符串的替换处理

String str = "helloworld" ;

System . out . println ( str . replaceAll ( "l" , "_" ));

System . out . println ( str . replaceFirst ( "l" , "_" ));

注意事项 : 由于字符串是不可变对象 , 替换不修改当前字符串 , 而是产生一个新的字符串

2.6 字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。

如果limit大于最多拆分的数组数,则能拆分几组就拆分几组

String str = "hello world hello bit" ;

String [] result = str . split ( " " ) ; // 按照空格拆分

for ( String s : result ) {(注意:字符串本身不能改变,是将拆分的字符串放入新的字符串数组)

System . out . println ( s );

}

代码示例 : 字符串的部分拆分

String str = "hello world hello bit" ;

String [] result = str . split ( " " , 2 ) ;

for ( String s : result ) {

System . out . println ( s );

}

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

代码示例 : 拆分 IP 地址

String str = "192.168.1.1" ;

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

for ( String s : result ) {

System . out . println ( s );

}

注意事项 :

1. 字符 "|","*","+" 都得加上转义字符,前面加上 "\\" .

2. 而 如果是 "\" ,那么就得写成 "\\\\" .

3. 如果一个字符串中有多个分隔符, 可以用 "|" 作为连字符 .

代码示例 : 多次拆分

String str = "name=zhangsan&age=18" ;

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

for ( int i = 0 ; i < result . length ; i ++ ) {

String [] temp = result [ i ]. split ( "=" ) ;

System . out . println ( temp [ 0 ] + " = " + temp [ 1 ]);

}

2.7 字符串截取

b44a6153e1414427af4f553d6cd95c2e.png

2.8 其他操作方法

其他方法需要用到时,大家参考 Java 在线文档: Java Platform SE 8

在 Java 程序中, 为了使程序的运行速度更快、

更节省内存 , Java 为 8 种基本数据类型和 String 类都提供了常量池。

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

1.Class文件常量池:每个.Java源文件编译后生成.Class文件中会保存当前类中的字面常量以及符号信息

2.运行时常量池:在.Class文件被加载时,.Class文件中的常量池被加载到内存中称为运行时常量池,运行时常

量池每个类都有一份。

3. 字符串常量池

7fee8bd90f784fec8d9c3a97f80ec9cd.png

50653dfaf07e4a169f9f1764da197f26.png

5bff9e0a83904706a31a7dd078bb999d.png

2.9.2 字符串常量池 (StringTable)

字符串常量池在 JVM 中是 StringTable 类,实际 是一个固定大小的 HashTable ( 一种高效用来进行查找的数据结构,

后序给大家详细介绍 ) ,不同 JDK 版本下字符串常量池的位置以及默认大小是不同的

2.9.3再谈String对象创建

由于不同JDK版本对字符串常量池的处理方式不同,此处在Java8 HotSpot上分

1. 直接使用字符串常量进行赋值

public static void main ( String [] args ) {

String s1 = "hello" ;

String s2 = "hello" ;

System . out . println ( s1 == s2 ); // true

}

3. intern 方法

intern 是一个 native 方法 (Native 方法指:底层使用 C++ 实现的,看不到其实现的源代码 ) , 该方法的作用是手

动将创建的 String 对象添加到常量池中 。

c030e126d5874bb6bbee8a17e78cc5b0.png

caea6f9284334c0cb33680ce3ddabce4.png

27e10227e9514dee864c04583ccb5a3c.png

34de775ec6264f1d84e43ac14c38619d.png


234d5f11b75547a3a7903ace541516ca.png

2.10字符串的不可变性

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

1.String类在设计时就是不可改变的,String类实现描述中已经说明了


16501c1877e548ebb23e429ccb98e38f.png

String 类中的字符实际保存在内部维护的 value 字符数组中 ,该图还可以看出:

1. String 类被 fifinal 修饰,表明 该类不能被继承

2. value 被修饰 被 final 修饰,表明 value 自身的值不能改变,即不能引用其它字符数组,但是其引用空间中

的内容可以修改。

2. 所有涉及到可能 修改字符串内容的操作都是创建一个新对象,改变的是新对象

比如 replace 方法:

【 纠正 】网上有些人说: 字符串不可变是因为其内部保存字符的数组被 final 修饰了,因此不能改变。

这种说法是错误的,不是因为 String 类自身,或者其内部 value 被 fifinal 修饰而不能被修改。

fifinal 修饰类表明该类不想被继承, final 修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内

容是可以修改的 。 真正原因:设计时规定String类是不能进行修改的。

为什么 String 要设计成不可变的 ? ( 不可变对象的好处是什么 ?) ( 选学 )

1. 方便实现字符串对象池. 如果 String 可变 , 那么对象池就需要考虑写时拷贝的问题了.

2. 不可变对象是线程安全的 .

3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中

2.11 字符串修改

注意:尽量避免直接对 String 类型对象进行修改,因为 String 类是不能修改的,所有的修改都会创建新对象,效率

非常低下。

10c903d26107499c9a6bdb08a070aef9.png

c60af92135c947fca96b0c37f42ce080.png

6505623554404cafacea14b4bb05bd8f.png

可以看待在对 String 类进行修改时,效率是非常慢的,因此:尽量避免对 String 的直接需要,如果要修改建议尽量

使用 StringBuffffer 或者 StringBuilder 。(我们可以理解的是,用StringBuffer和StringBuilder进行字符串修改时,其内部可以进行字符串的修改,直接用其修改,可以避免String和这两类之间的转化,同时避免转化后建立新的对象,有利于提高效率)

二.StringBuffer和Stringbuilder

3.1 StringBuilder的介绍

由于 String 的不可更改特性,为了方便字符串的修改, Java 中又提供 StringBuilder 和 StringBuffffer 类。这两个类大

部分功能是相同的,这里介绍 StringBuilder 常用的一些方法,其它需要用到了大家可参阅 StringBuilder 在线文档( Java Platform SE 8 )

4851f06e8f2b41019e79de5c63ded1e2.png

从上述例子可以看出: String 和 StringBuilder 最大的区别在于 String 的内容无法修改,而 StringBuilder 的内容可

以修改 。频繁修改字符串的情况考虑使用 StringBuilder 。

注意: String 和 StringBuilder 类不能直接转换。如果要想互相转换,可以采用如下原则:

String 变为 StringBuilder: 利用 StringBuilder 的构造方法或 append() 方法

StringBuilder 变为 String: 调用toString方法

1. String 、 StringBuffer 、 StringBuilder 的区别

String 的内容不可修改, StringBuffer 与 StringBuilder 的内容可以修改 .

StringBuffer 与 StringBuilder 大部分功能是相似的

StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作

a34f129ffb4c47d3b67c90e25635f569.png

1a94d3ec2ff544c7bab6757b58007613.png

8ea99aeef3c045f09d32f690020d5297.png


相关文章
|
2月前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
39 0
java基础(13)String类
|
3月前
|
API 索引
String类下常用API
String类下常用API
44 1
|
1月前
|
Java
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
本文深入探讨了Java中方法参数的传递机制,包括值传递和引用传递的区别,以及String类对象的不可变性。通过详细讲解和示例代码,帮助读者理解参数传递的内部原理,并掌握在实际编程中正确处理参数传递的方法。关键词:Java, 方法参数传递, 值传递, 引用传递, String不可变性。
55 1
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
|
30天前
|
安全 Java 测试技术
Java零基础-StringBuffer 类详解
【10月更文挑战第9天】Java零基础教学篇,手把手实践教学!
24 2
|
1月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
21 1
|
2月前
|
安全 Java
String类-知识回顾①
这篇文章回顾了Java中String类的相关知识点,包括`==`操作符和`equals()`方法的区别、String类对象的不可变性及其好处、String常量池的概念,以及String对象的加法操作。文章通过代码示例详细解释了这些概念,并探讨了使用String常量池时的一些行为。
String类-知识回顾①
|
1月前
|
数据可视化 Java
让星星月亮告诉你,通过反射创建类的实例对象,并通过Unsafe theUnsafe来修改实例对象的私有的String类型的成员属性的值
本文介绍了如何使用 Unsafe 类通过反射机制修改对象的私有属性值。主要包括: 1. 获取 Unsafe 的 theUnsafe 属性:通过反射获取 Unsafe类的私有静态属性theUnsafe,并放开其访问权限,以便后续操作 2. 利用反射创建 User 类的实例对象:通过反射创建User类的实例对象,并定义预期值 3. 利用反射获取实例对象的name属性并修改:通过反射获取 User类实例对象的私有属性name,使用 Unsafe`的compareAndSwapObject方法直接在内存地址上修改属性值 核心代码展示了详细的步骤和逻辑,确保了对私有属性的修改不受 JVM 访问权限的限制
51 4
|
1月前
|
存储 安全 Java
【一步一步了解Java系列】:认识String类
【一步一步了解Java系列】:认识String类
25 2
|
1月前
|
安全 C语言 C++
【C++篇】探寻C++ STL之美:从string类的基础到高级操作的全面解析
【C++篇】探寻C++ STL之美:从string类的基础到高级操作的全面解析
34 4
|
1月前
|
存储 编译器 程序员
【C++篇】手撕 C++ string 类:从零实现到深入剖析的模拟之路
【C++篇】手撕 C++ string 类:从零实现到深入剖析的模拟之路
63 2