裸泳的猪

沾沾自喜其实最可悲

0%

Java基础提升_String类

String(字符串常量)概述

在API中是这样描述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。
字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。
String str = "abc";

相当于:
char data[] = {'a', 'b', 'c'};
String str = new String(data);

以下是一些有关如何使用字符串的更多示例:
System.out.println("abc");
String cde = "cde";
System.out.println("abc" + cde);
String c = "abc".substring(2,3);
String d = cde.substring(1, 2);

类String包括用于检查序列中的单个字符、比较字符串、搜索字符串、提取子字符串以及创建所有字符都转换为大写或小写的字符串副本的方法。 大小写映射基于Character类指定的 Unicode 标准版本。
...
*/
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
...
}

需要注意的是:String是一个不可变对象,可以认为是特殊的常量,因此存在方法区的运行时常量池中,可以被共享使用(享元模式),而不是创建一个新对象,但是这样的做法仅仅适合于通过=符号进行的初始化

由此引申出许多判断各种情况下,string对象是否相等的判断

常见的String == 比较

首先,我们在比较两个string对象之前,需要了解:

  1. 通过构造方法创建(new创建)的String对象,存放在java虚拟机的堆内存,堆内存里存放的是字符串常量的地址,字符串常量存放在方法区的常量池中;
  2. 直接赋值:通过直接赋值所创建的对象直接是方法区中的常量池中的字符串常量。

下面列举一些常见的比较例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
   String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hel" + "lo";
String s4 = "Hel" + new String("lo");
String s5 = new String("Hello");
String s6 = s5.intern();
String s7 = "H";
String s8 = "ello";
String s9 = s7 + s8;

System.out.println(s1 == s2); // true 都是方法区常量池
System.out.println(s1.equals(s2)); //true 值都相同
System.out.println(s1.equals(s5)); //true 值都相同
System.out.println(s1 == s3); // true 做+号的时候,会进行优化,自动生成Hello赋值给s3都是方法区常量池
System.out.println(s1 == s4); // false s4最后生成的是一个在堆中的string对象
System.out.println(s1 == s9); // false 用的是动态调用,所以s9返回的是一个新的String对象
System.out.println(s4 == s5); // false s4,s5不同的对象
System.out.println(s1 == s6); // true

分析:

  1. s1 = = s2 很容易可以判断出来。s1 和 s2 都指向了方法区常量池中的Hello。
  2. s1 = = s3 这里要注意一下,因为做+号的时候,会进行优化,自动生成Hello赋值给s3,所以也是true
  3. s1 = = s4 s4是分别用了常量池中的字符串和存放对象的堆中的字符串,做+的时候会进行动态调用,最后生成的仍然是一个String对象存放在堆中。
  4. s1 = = s9 在JAVA9中,因为用的是动态调用,所以返回的是一个新的String对象。所以s9和s4,s5这三者都不是指向同一块内存
  5. s1 = = s6 为啥s1 和 s6地址相等呢? 归功于intern方法,这个方法首先在常量池中查找是否存在一份equal相等的字符串如果有的话就返回该字符串的引用,没有的话就将它加入到字符串常量池中,所以存在于class中的常量池并非固定不变的,可以用intern方法加入新的

String、StringBuffer、StringBuilder。

  • String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象;
  • 而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
  • StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer线程安全的,而 StringBuilder非线程安全的;
  • 但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

如何将字符串反转

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

1
2
3
4
// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("abcdefg");
System.out.println(stringBuffer.reverse()); // gfedcba

String 类的常用方法都有那些?

  • indexOf():返回指定字符的索引。
  • charAt():返回指定索引处的字符。
  • replace():字符串替换。
  • trim():去除字符串两端空白。
  • split():分割字符串,返回一个分割后的字符串数组。
  • getBytes():返回字符串的 byte 类型数组。
  • length():返回字符串长度。
  • toLowerCase():将字符串转成小写字母。
  • toUpperCase():将字符串转成大写字符。
  • substring():截取字符串。
  • equals():字符串比较。
-------------本文结束感谢您的阅读-------------