写点什么

懵了!本以为精通 String 类,想不到却被阿里面试官狠狠虐了一把

发布于: 2021 年 06 月 14 日
懵了!本以为精通String类,想不到却被阿里面试官狠狠虐了一把

今日分享开始啦,请大家多多指教~

一、创建字符串

创建字符串的方式有很多种,当是常见的一般就三种

1. 直接赋值(常用)

String str = "hello world !";

2. new String

String str = new String("hello world !");

3. 字符数组转 String

char[] array = {'a', 'b', 'c'};

String str = new String(array);

但以后一般都是用第一种创建方式

注意事项:

  • "hello" 这样的字符串字面值常量, 类型也是 String.

  • String 也属于引用类型. String str ="Hello"

4.String 类中两种对象实例化的区别

  • 直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。

  • 构造方法:会开辟两块堆内存空间,不会自动保存在对象池中,可以使用 intern()方法手工入池。

二、字符串比较相等

1.直接比较字符串

我们知道两个整形可以直接用 == 比较相等,那如果用 == 比较 String 类相等会发生什么呢?

代码:

运行结果:

我们知道 String 属于引用类型,所以 str 存的是地址。那么比较的就是地址。

只要 new 了就会在堆上开辟内存,所以不相等。直接说可能有点抽象,下面简单通过内存图来判断字符串是否相等。

2.字符串在内存中的存储

接上面的例子我们来看一下字符串在内存中的存储来判断相等

注意:

1.只要 new 了就会在堆上开辟内存,那么必定不会相等。

2.相同的字符串在字符串常量池里只会存一份。

3.字符串常量池

String 类的设计使用了共享设计模式

在 JVM 底层实际上会自动维护一个对象池(字符串常量池)

  • 如果现在采用了直接赋值的模式进行 String 类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中.

  • 如果下次继续使用直接赋值的模式声明 String 类对象,此时对象池之中如若有指定内容,将直接进行引用

  • 如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用

4.字符串比较 equals

Java 中要想比较字符串是否相等的话,就需要使用 String 提供的 equals 方法

equals 使用的注意事项:

现在需要比较 str 和 “Hello” 两个字符串是否相等, 我们该如何来写呢?

在上面的代码中, 哪种方式更好呢?

更推荐使用 “方式二”. 一旦 str 是 null, 方式一的代码会抛出异常, 而方式二不会。

注意事项: “Hello” 这样的字面值常量, 本质上也是一个 String 对象, 完全可以使用 equals 等 String 对象的方法。

5.理解字符串的不可变

字符串是一种不可变对象. 它的内容不可改变.

String 类的内部实现也是基于 char[] 来实现的, 但是 String 类并没有提供 set 方法之类的来修改内部的字符数组.

代码示例:

形如 += 这样的操作, 表面上好像是修改了字符串, 其实不是. 内存变化如下:

+= 之后 str 打印的结果却是变了, 但是不是 String 对象本身发生改变, 而是 str 引用到了其他的对象。

回顾引用:

引用相当于一个指针, 里面存的内容是一个地址. 我们要区分清楚当前修改到底是修改了地址对应内存的内容发生改变了, 还是引用中存的地址改变了。

6.手动入池 intern()

我们知道字符串常量是存在字符串常量池当中的,而 new 的是在堆上开辟内存。

而 String 的 intern()方法可以把 String 对象手动入到字符串常量池中。

如果 str2 没有

intern()方法的时候,它是指向堆上的 new 的 String 对象的,而使用了 intern()方法后,就会直接指向字符串常量池的

”hello“,如果调用 intern()方法的时候字符串常量池中没有 "hello"这个字符串,则会把它放入池中。

三、字符字节与字符串

1.字符转字符串

代码示例 :

注意:第一个参数是偏移量,偏移量是从 0 开始的,第二个是参数是往后从偏移量开始的位置走几步。且下标不能越界!

2.字符串转字符

指定获取字符串里的某一个字符:

字符串转字符数组代码示例:

运行结果

3.字节与字符串

用法和上面的类似

代码示例:

运行结果

4.编码方式

运行结果 :

常见的编码方式有 utf-8 和 GBK ,不过编码方式一般只对汉字有影响。

5.小结

那么何时使用 byte[], 何时使用 char[] 呢?

  • byte[] 是把 String 按照一个字节一个字节的方式处理, 这种适合在网络传输, 数据存储这样的场景下使用. 更适合 针对二进制数据来操作。

  • char[] 是吧 String 按照一个字符一个字符的方式处理, 更适合针对文本数据来操作, 尤其是包含中文的时候。

回忆概念: 文本数据 vs 二进制数据

一个简单粗暴的区分方式就是用记事本打开能不能看懂里面的内容。

如果看得懂, 就是文本数据(例如 .java 文件), 如果看不懂, 就是二进制数据(例如 .class 文件)。

四、字符串常见操作

1.字符串比较

上面使用过 String 类提供的 equals()方法,该方法本身是可以进行区分大小写的相等判断。除了这个方法之外,String 类还提供有如下的比较操作:

代码示例:

**compareTo()**方法前面博客有详细介绍,这里就不多说了。可以看看—>compareTo 方法

在 String 类中 compareTo()方法是一个非常重要的方法,该方法返回一个整型,该数据会根据大小关系返回三类内

容:

  • 相等:返回 0

  • 小于:返回内容小于 0

  • 大于:返回内容大于 0

2.字符串查找

从一个完整的字符串之中可以判断指定内容是否存在,对于查找方法有如下定义:

代码示例 :

用法都是通过 String 类点出方法名,注意就收放回值就好了。

3.字符串替换

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

代码示例:

运行结果

注意如果替换的是特殊字符,则需要使用转义字符。

代码示例:

运行结果

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

4.字符串拆分

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

代码示例:

运行结果

注意:下面的的这段代码是不能被拆分的

运行结果:

因为 \ 后面跟两到三个数字会被转义成一个八进制数字。

注意事项:

  • 字符"|","*","+“都得加上转义字符,前面加上”"。

  • 而如果是"",那么就得写成"\"。

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

多次拆分代码示例:

运行结果:

5.字符串截取

从一个完整的字符串之中截取出部分内容。

代码示例:

注意事项:

  • 索引从 0 开始

  • 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标

6.其他操作方法

这些都比较简单,用的时候查就好了。

五、StringBuffer 和 StringBuilder

首先来回顾下 String 类的特点:

任何的字符串常量都是 String 对象,而且 String 的常量一旦声明不可改变,如果改变对象内容,改变的是其引用的指向而已。

通常来讲 String 的操作比较简单,但是由于 String 的不可更改特性,为了方便字符串的修改,提供 StringBuffer 和 StringBuilder 类。

StringBuffer 和 StringBuilder 大部分功能是相同的,只有较小的区别。

1.append()方法

在 String 中使用"+"来进行字符串连接,但是这个操作在 StringBuffer 类中需要更改为 append()方法:

public synchronized StringBuffer append(各种数据类型 b)

代码示例:

运行结果:

StringBuffer 和 StringBuilder 大部分功能是相同的,它们的 append()方法的方法可以拼接各种数据类型。

注意:

  • String 和 StringBuffer 最大的区别在于:String 的内容无法修改,而 StringBuffer 的内容可以修改。频繁修改字符串的情况考虑使用 StingBuffer。

  • 因为 String 通过+拼接会产生临时对象,而 StringBuffer 和 StringBuilder 只会在当前对象上进行拼接。

2.字符串反转 reverse( )

代码示例:

运行结果:

3.删除指定范围的数据 delete( )

代码示例:

运行结果:

4.插入数据 insert( )

代码示例:

运行结果:

5.StringBuffer 和 StringBuilder 的区别

来看一下 StringBuffer 和 StringBuilder 的 append 方法

1.String 的拼接会产生临时对象,但是后两者每次都只是返回当前对象的引用

2.String 的加号拼接,会被底层优化为一个 StringBuilder

3.StringBuilder 和 String,一般如果不涉及到多线程的情况下才会使用

4.StringBuffer(创建锁、销毁锁、都是耗费资源的)

总结

1.如果以后涉及到字符串的拼接,一定要注意使用 StringBuffer 和 StringBuilder 的 append()方法;

2.注意 String 类中两种对象实例化的区别;

3.相同的字符串在字符串常量池中只会存一份;

今日份分享已结束,请大家多多包涵和指点!

用户头像

还未添加个人签名 2021.04.20 加入

Java工具与相关资料获取等WX: pfx950924(备注来源)

评论

发布
暂无评论
懵了!本以为精通String类,想不到却被阿里面试官狠狠虐了一把