java基础(jdk1.8)
**
**
字符串在Java基础中是比较重要的,这里我们对String及StringBuffer和StringBuilder进行研究
字符串的操作我们在String、StringBuffer、StringBuilder这里同时对这三个类进行分析
源码内容:
1、String是一个final的class
2、String实现了Serializable, Comparable, CharSequence三个接口
3、String储存字符串用的是一个final的char数组
4、String的构造方法传参可为空、字符数组(char [])、字节数组(byte [])和String字符串常量
根据源码,我们可以得出String的特点
1.String类不可被继承、且String字符串是一个常量
2.String类实现了compareTo方法、charAt、toString方法…
除此之外,我们要知道的还有
String str = new String("123abc");
String str1 = "123abc";
这两个到底创建了几个对象,它们分别储存在哪,区别又是什么?
这个容易牵扯到Java内存,这里可以戳戳看,但下面阅读不是太影响
我们知道的是new会将引用引用到堆空间,那么接下来就好办了
str = new String(“123abc”)
1.str引用必定指向堆空间的new String(“123abc”)
2.同时会从常量池(方法区的一部分)内寻找有无"123abc"这个字符串。方便理解起见,之后将常量池叫做String池
3.String池没有这个字符串则创建一个对象在池中,有则不创建
这里注意
因为字符串经常创建,使用。所以String池为了节省空间、提高效率,String池不可重复
str1 = “123abc”
1.str1没有使用new,那么str1自然直接引用到String池内
2.String池内同样找是否已经有了同样的字符串
这里我们基本对这两有何区别已经了解,我们看一段代码和一个关系图来在加深印象
public class StrTest {
public void strTest(){
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s3 == s4);
System.out.println(s1 == s3);
System.out.println(s1 == s3.intern());
}
public static void main(String[] args) {
StrTest strtest = new StrTest();
strtest.strTest();
}
}
结果
true
false
false
true
结果是此的原因也就出来了
上述我使用了s3.intern(),用它和s1比较,结果为true,这是intern将s3的引用从堆改到了String池。所以结果为true。
另外
我们使用==比较的是地址,有一个方法为equals
equals方法源码
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
这里,我们知道所有类都继承了Object类。
看类是否将Object类的equals是否重写,重写则比较值、无则比较地址。
而String将equals重写,所以equals方法是比较对象数值
这时我们将之前的==改为equals,那么结果将全部为true
先瞧:
这里我挑几个看看
length()
length()方法是字符串的长度。
String使用char数组,而length()源码调用的就是char数组的length方法
charAt(int index)
charAt()方法是传入下标,返回下标对应的字符。
isEmpty()
isEmpty()方法判断字符串是否为空
substring()
substring()方法是截取字符串
根据传参的下标,对截取你所需要的部分(左闭右开)
StringBuilder和StringBuffer都继承的是AbstractStringBuilder,实现Serializable, CharSequence
而且两者的构造方法及方法基本一致,区别则是StringBuffer类的方法加了一个synchronized关键字,这个关键字保证了线程安全性。
因此StringBuilder是线程非安全类、StringBuffer是线程安全类
与String的区别:
1、String的值不可改变,而StringBuilder 和 StringBuffer的值可改变。
2、StringBuffer及Builder只能使用new关键字进行初始化,初始化调用其append方法再到super.append,如果非空则调用到System.arraycopy方法
3、StringBuffer及Builder没有重写equals方法1
StringBuilder 和 StringBuffer的常用方法:增删改
insert(int,obj)
从int位置插入obj(string、byte、char…)
delete(int,int)
从int到int删除(左闭右开)
replace(int,int,String)
左闭右开替换
length()
charAt(int index)
isEmpty()
substring()
String a = "123";
//a在栈里,引用指向方法区里“123”这个对象(创建一个对象)
String b = "123";
//b指向方法区里“123”(未创建对象)
String c = new String("123");
//c 在堆创建一个对象并指向它,方法区有则不创建(创建一个对象)
String d = new String("456");
//d 在堆里和方法区分别创建一个(共创建两个对象)
String b = a+"12";
//这里并不是说b的值改变,而是将原来的b销毁,创建一个方法区的“12”对象,而这个a已经创建过了,最后将a+"12"共同创建一个新的对象(new堆上),和原来的b并不是同一个
subString方法
public String substring(int start, int end) {
if (start < 0)
throw new StringIndexOutOfBoundsException(start);
if (end > count)
throw new StringIndexOutOfBoundsException(end);
if (start > end)
throw new StringIndexOutOfBoundsException(end - start);
return new String(value, start, end - start);
}
返回的是一个new的对象
上一篇 》常用类
下一篇 》 异常处理