Java筑基篇—String

提示:学习使用,仅供参考!


String类用于保存字符串,也即是一组字符序列,类图如下
在这里插入图片描述

一、特点

  • 无法被继承:String 类被 final 修饰
  • 采用Unicode编码:一个字符(不论是字母还是汉字)都占两个字节
  • 可串行化:实现了 Serializeble 接口,可进行网络传输
  • 可比大小:实现了 Comparable接口,可调用**compareTo()**进行字符串大小的比较
  • 线程安全:String 类是不可变类,而不可变类是线程安全的

有些彦祖可能会问:如果 String 类不可变,那下面代码为啥可行,这s1不是发生了变化吗?

String s1 = "hello";
s1 = "world";
System.out.println(s1);  // world

这么一看,确实发生了变化,不过此变非彼变

二、不可变

String 是引用类型,其值实际上保存的是具体内容的地址,而String 的创建一般有两种:通过 " " 直接赋值和通过构造器创建

  • 通过 " " 创建,字符串会直接存储到字符串常量池中,此时String对象指向的地址是存储在字符串常量池中的字符串的地址
  • 通过构造器创建,会先在堆上创建一个String对象, 里面维护一个字符数组属性 value[](存放字符串),value指向字符串常量池,此时String对象指向的是中的对象地址,而非常量池中的地址
String s1 = "a";
String s2 = new String("a")

在这里插入图片描述

问题1:s1 == s2 ?
s1保存的是字符串常量池中字符串的地址,而s2保存的是堆中对象的地址,显然不相等,返回 false

问题2:s1.equals(s2) ?
String类对Object类中的equals()方法进行了重写,比较的字符串的内容是否一致,而 s1 、s2 都为 “hello”,所以返回 true

上面说到,通过 " ",字符串会直接存储到字符串常量池中,再看彦祖提出的问题

String s1 = "hello";
s1 = "world";

第一行 s1 指向字符串常量池中 “hello” 地址,第二行 s1 又指向了字符串常量池 “world” 地址,如下图:
在这里插入图片描述
可以看出,s1 所谓的变化,实际是指向了另一个字符串常量,而非在原来的字符串常量上做修改

结论:被final修饰的引用类型不能再指向其他对象,而字符串内容实际存储在 String 类中的字符数组 value[]。value[]为引用类型,被 final 修饰,导致其不能指向其他字符数组对象,若只是被final修饰的话,其数组内容依旧可以修改,但坏就坏在 value[] 还被修饰符private修饰,加之 String 类本身没有提供修改 value [] 的方法,所以 String 不可变

所谓 String 发生变化实际指的不是在原来的基础上做修改,而是指向一个新的字符串地址

原因

1)String类被 final 修饰导致其不能被继承,进而避免了子类破坏 String不可变。
2)String 类有一个私有并被 final 修饰的字符数组 value[],字符串内容实际保存在数组中,而String并未提供可修改此数组的方法

拓展

被 finale修饰的变量是基本数据类型则值不能改变
被 finale修饰的变量是引用类型则不能再指向其他对象,但其内容可以发生变化

三、方法

1、intern()

返回字符串常量池中对应字符串的地址

String str1 = "abc";
String str2 = new String("abc");
str1 == str2; // false
str1 == str2.intern(); // true

2、split()

分割符,返回一个数组

String a = "a,b,v,d";
String[] str = a.split(","); // str = {a, b, v,d};

// 若有特殊字符,如 | 、 \\ 等, 需要加入转义符 \
String a = "a\\b\\v\\d";
String[] str = a.split("\\"); // 错误,需要转义
String[] str = a.split("\\\\");

3、equals() 与 equalsIgnoreCase()

eqauls():比较内容
equalsIgnoreCase():忽略大小写比较字符串内容

"hello".equals("Hellow"); // false
"hello".eqaulsIgonreCase("HELLOW"); // true

4、subString()

截取指定范围内容
str.subString(int i):从索引第 i 开始截取后面所有内容
str,subString(int i, int j ):从索引第 i 开始截取到索引为 ( j - 1)的内容

"hello,张三".subString(6); // 张三
"hello,张三".subString(0,5); // hello
"hello,张三".subString(3,5); // lo

5、indexOf() 与 lastIndexOf()

indexOf(String str):返回字符在字符串中第一次出现的索引位置,找不到返回-1
lastIndexOf(String str):返回字符在字符串最后一次出现的索引位置,**找不到返回-1

"abcdbcd".indexOf("b"); // 返回 2
"abcdbcd".lastindexOf("b"); // 返回 4

6、toUpperCase() 与 toLowerCase()

toUpperCase():转为大写
toLowerCase():转为小写

"abcd".toUpperCase();   // ABCD
"ABCD".toUpperCase();  // abcd

7、concat()

拼接字符串

"a".concat("b").concat("c"); // abc

8、compareTo()

比较字符串大小

1)长度相同,且内容相同:返回 0 (str1.length - str2.length)

"abcd".compareTo("abcd");  // 0

2)长度相同,内容不同:返回 str1 与 str2 第一个不同的字符进行相减的结果

"abcd".compareTo("abdd"); // 第一个不同的字符相减: c - d = -1

3)若长度不同,前面内容相同:返回 str1.length - str2.length 的结果

"abcd".compareTo("abcdabc"); // -3

9、replace()

替换,但不对原字符串做改变,返回的是一个新字符串

String s1 = "abbbccbc";
String s2 = s1.replace("b", "z"); // 将 "b" 全部替换成 "z"

// 此时 s1 还是"abbbccbc",而 s2 为"azzzcczc"

总结

步入筑基,金丹有望,若有错误,还望雅正

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值