目录:
1 String 概述
2 String不可变的好处
3 String,StringBuffer和 StringBuilder的区别
4 字符串常量池(String Pool)
5 new String(String类中两种对象实例化的区别)
6 String 常用方法(字符串构造、String对象的比较 、字符串查找、转化、字符串替换、字符串拆分、字符串截取、其他操作方法)
1 String 概述
String 被声明为 final,因此它不可被继承。
在 Java 8 中, String 内部使用 char 数组 存储数据。
在 Java 9 之后, String 类的实现改用 byte 数组存储字符串,同时使用coder来标识使用了哪种编 码。
value 数组被声明为 final,这意味着 value 数组初始化之后就不能再引用其它数组。并且 String 内 部没有改变 value数组的方法,因此可以保证 String 不可变。
2 String不可变的好处
所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象。
可以缓存 hash 值
因为 String 的 hash 值经常被使用,例如 String 用做 HashMap 的 key。不可变的特性可以使得hash 值也不可变,因此只需要进行一次计算 。
String Pool 的需要
如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用 。只有 String 是不可变的,才可能使用 String Pool(确实也是,如果改变的话,那么多个引用指向内存中字符串地址,那么就不对应了)。
安全性
String 经常作为参数, String 不可变性可以保证参数不可变 。例如在作为网络连接参数的情况下如果 String 是可变的,那么在网络连接过程中 ,String 被改变,改变 String 对象的那一方以为现在连接的是其它主机,而实际情况却不一定是。
线程安全
String 不可变性天生具备线程安全 ,可以在多个线程中安全地使用。
3 String,StringBuffer和 StringBuilder的区别
String
的内容无法修改,而
StringBuilder
的内容可
以修改。频繁修改字符串的情况考虑使用StringBuilder。
可变性
String的内容不可修改
StringBuffffer与StringBuilder的内容可以修改
StringBuffffer与StringBuilder大部分功能是相似的
线程安全
String 不可变,因此是线程安全的
StringBuilder 不是线程安全的
StringBuffer 是线程安全的,内部使用 synchronized 进行同步
4 字符串常量池(String Pool)
字符串常量池(String Pool)保存着所有字符串字面量 (literal strings),这些字面量在编译时期就确定 。不仅如此,还可以使用 String 的 intern() 方法在运行过程中将字符串添加到 String Pool 中。 当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在一个字符串和该字符串值相等( 使 用 equals() 方法进行确定 ),那么就会返回String Pool中字符串的引用 ;否则,就会在 String Pool 中添加一个新的字符串,并返回这个新字符串的引用。
下面示例中, s1 和 s2 采用 new String() 的方式新建了两个不同字符串,而 s3 和 s4 是通过 s1.intern() 方法取得一个字符串引用。 intern() 首先把 s1 引用的字符串放到 String Pool 中,然后返回这个字符串引用。因此 s3 和 s4 引用的是同一个字符串。
如果是采用”bbb” 这种字面量的形式创建字符串,会自动地将字符串放入 String Pool 中。
5 new String
使用这种方式一共会创建两个字符串对象(前提是 String Pool 中还没有 “abc” 字符串对象)。
● “abc” 属于字符串字面量,因此编译时期会在String Pool中创建一个字符串对象 ,指向这个 “abc” 字符串字面量;
● 而使用 new 的方式会在堆中创建一个字符串对象。
创建一个测试类,其main 方法中使用这种方式来创建字符串对象。
如果是直接赋值的,String s = “abc”。那么就会先去字符串常量池看看,如果有,就直接赋值
没有就在字符串常量池中创建一个再赋值。但是 new出来的是不会入池的,想要入池还要用到
intern方法。(intern 是一个native方法(Native方法指:底层使用C++实现的,看不到其实现的源代码),该方法的作用是手动将创建的String对象添加到常量池中)
以下是 String 构造函数的源码,可以看到, 在将一个字符串对象作为另一个字符串对象的构造函数参数时,并不会完全复制 value 数组内容,而是都会指向同一个 value 数组 。
String str = “hello”
String str = new String(“hello”)
String str = new String(new char[]{‘h’, ‘e’, ‘l’, ‘l’, ‘o’})
6 String 常用方法
是引用类型,内部并不存储字符串本身
public static void main(String[] args) {
// 使用常量串构造
String s1 = "hello bit";
System.out.println(s1);
// 直接newString对象
String s2 = new String("hello bit");
System.out.println(s1);
// 使用字符数组进行构造
char[] array = {'h','e','l','l','o','b','i','t'};
String s3 = new String(array);
System.out.println(s1);
}
String对象的比较
==
比较是否引用同一个对象
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 10;
// 对于基本类型变量,==比较两个变量中存储的值是否相同
System.out.println(a == b); // false
System.out.println(a == c); // true
// 对于引用类型变量,==比较两个引用变量引用的是否为同一个对象
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = new String("world");
String s4 = s1;
System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // false
System.out.println(s1 == s4); // true
}
boolean equals(Object anObject)
方法:按照字典序比较
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) 方法: 按照字典序进行比较
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
}
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.compareToIgnoreCase(s2)); // 不同输出字符差值-1
System.out.println(s1.compareToIgnoreCase(s3)); // 相同输出 0
System.out.println(s1.compareToIgnoreCase(s4)); // 前k个字符完全相同,输出长度差值 -3
}
字符串查找
方法
|
功能
|
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
|
转化
数值和字符串转化
// 数字转字符串String s1 = String.valueOf(1234);// 字符串转数字int data1 = Integer.parseInt(“1234”);double data2 = Double.parseDouble(“12.34”);
2. 大小写转换
// 小写转大写s1.toUpperCase();// 大写转小写s2.toLowerCase();
3.字符串转数组
// 字符串转数组char[] ch = s.toCharArray();// 数组转字符串String s2 = new String(ch);
4. 格式化
public static void main(String[] args) {String s = String.format(“%d-%d-%d”, 2019, 9,14);System.out.println(s);}
字符串替换
方法
|
功能
|
String replaceAll(String regex, String replacement)
|
替换所有的指定内容
|
String replaceFirst(String regex, String replacement)
|
替换首个内容
|
注意事项: 由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串.
字符串拆分
方法 | 功能 |
String[] split(String regex)
|
将字符串全部拆分
|
String[] split(String regex, int limit)
|
将字符串以指定的格式,拆分为limit组
|
示例: 多次拆分
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]);}
方法 | 功能 |
String substring(int beginIndex)
|
从指定索引截取到结尾
|
String substring(int beginIndex, int endIndex)
|
截取部分内容
|
其他操作方法
方法 | 功能 |
String trim()
|
去掉字符串中的左右空格,保留中间空格
|
String toUpperCase()
|
字符串转大写
|
String toLowerCase()
|
字符串转小写
|
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/94629.html