黑马程序员-Java String类
首先,我们先看两个问题:
String a = "hello world"; String b = "hello world";
String a = new String("hello world"); String b = "hello world";
a=b? a和b是否相等?为什么?
分析:
1. 首先String不属于8种基本数据类型,String是一个对象。因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其他对象没有的一些特性。
2. new String()和new String("")都是声明一个新的空字符串,是空串不是null;
3. String str = "kvill";和String str = new String("kvill")的区别。
在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。常量池(constant pool)指的是在编译期被确定,并保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。
String s0 = "kvill"; String s1 = "kvill"; String s2 = "kv" + "ill"; System.out.println(s0 == s1); System.out.println(s0 == s2);
结果为:
true
true
首先,我们要知道java会确保一个字符串常量只有一个拷贝。
因为例子中的s0和s1中的“kvill”都是字符串常量,它们在编译期就被确定了,所以s0 == s1 为true;而“kv”和“ill”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中“kvill”的一个引用。所以我们得出s0 == s1 == s2。
用new String()创建的字符串不是常量,不能再编译期就确定,所以new String()创建的字符串不放入常量池中,它们有自己的地址空间。
String s0 = "kvill"; String s1 = new String("kvill"); String s2 = "kv" + new String("ill"); System.out.println(s0 == s1); System.out.println(s0 == s2); System.out.println(s1 == s2);
结果为:
false
false
false
分析:
s0还是常量池中“kvill”的引用,s1和s2的后部分无法再编译期确定,所以是运行时创建的新对象“kvill”的引用。
4. String.intern();
补充一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用。
String s0 = "kvill"; String s1 = new String("kvill"); String s2 = new String("kvill"); System.out.println(s0 == s1); System.out.println("*************"); s1.intern(); s2 = s2.intern(); System.out.println(s0 == s1); System.out.println(s0 == s1.intern()); System.out.println(s0 == s2);
结果为:
false
*************
false//虽然执行了s1.intern(),但它的返回值没有赋给s1
true//说明s1.intern()返回的是常量池中“kvill”的引用
true
5. 关于equals()和==
这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。
6. 关于String是不可变的
大家都知道String的实例一旦生成就不会再改变了,比如:
String str = "kv" + "ill" + " " + "ans";
就是有4个字符串常量,首先“kv”和“ill”生成了“kvill”存在内存中,然后“kvill”又和“ ”生成“kvill ”存在内存中,...可以看到String的不可变产生了很多临时变量,这也就是为什么建议使用StringBuffer的原因呢,因为StringBuffer是可以改变的。
String类适用于描述字符串事物,那么它就提供了多个方法对字符串进行操作。
常见的操作有哪些?
1.获取
1.1 字符串中包含的字符数,也就是字符串的长度
int length()
1.2 根据位置获取位置上某个字符。
char charAt(int index)
1.3 根据字符获取该字符在字符串中位置。
int indexOf(int ch) //返回该字符在字符串中第一次出现的位置
int indexOf(int ch, int fromIndex) //从fromIndex指定位置开始,获取ch在字符串中的位置
int indexOf(String str) //返回str在字符串中第一次出现的位置
int indexOf(String str, int fromIndex) //从fromIndex指定位置开始,获取str在字符串中的位置
int lastIndexOd(int ch)
2.判断
2.1 字符串中是否包含某一个子串。
boolean contains(str);
特殊之处:indexOf(str):
2.2 字符串中是否有内容
boolean isEmppty();
2.3 字符串是否以指定内容开头
boolean startWith(str);
2.4字符串是否以指定内容结尾
boolen endWith(str);
2.5判断字符串内容是否相同
boolean equals(str);
2.6判断字符串内容是否相同并忽略大小写
boolean equalsIgnoreCase();
3.转换
3.1 将字符数组转成字符串
构造函数: Strnig(char[])
String(char[], offset, count); 将字符数组中的一部分转成字符串
静态方法: static String copyValueof(char[]);
static String copyValueof(char[], offset, count);
static String valueOf(char());
3.2 将字符串转成字符数组
char[] toCharArray();
3.3 将字节数组转成字符串
Strnig(byte[])
String(byte[], offset, count); 将字节数组中的一部分转成字符串
3.4将字符串转成字节数组
byte[] getBytes();
3.5将基本数据类型转成字符串
static String valueOf(int)
static String valueOf(double)
特殊:字符串和字节数组在转换过程中,是可以指定编码表的。
4. 替换
String replace(oldchar, newchar);
5. 切割
String[] split(regex);
6. 子串
String substring(begin);
String substring(begin, end);
7. 转换
7.1 将字符串转成大写或小写
String toUpperCase();
String toLowerCase();
7.2 将字符串两端的多个空格去除
String trim();
7.3 将两个字符串进行自然顺序的比较
int compareTo(string);