学习别人的博客后自己写的笔记,感觉看了她其他博客还是挺有收获的,这是原博客传送门
文章目录
1.String类,StringBuffer类以及StringBuilder类
首先String类是不可变类,即一旦产生一个String类的对象,便不再允许改变;但是StringBuffer和StringBuilder类是可变类。
StringBuffer和StringBuilder类的原理和操作基本相同,区别在于StringBuffer支持并发操作,线性安全的,适合多线程中使用。StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用,但StringBuilder在单线程中的性能比StringBuffer高。在单线程中应该用StringBuilder代替StringBuffer。
原博客传送门
2.字符串拼接
两个字符串的拼接可以直接用“+”来连接
String string1 = "Hello";
String string2 = "World";
String string3 = string1 + string2;
但是使用"+"来进行字符串的拼接效率低下,每次连接字符串都会构建一个新的String对象,既耗时又浪费空间;使用StringBuffer和StringBuilder可以避免这个问题。
StringBuilder stringBuilder = new StringBuilder();
每次需要在末尾添加内容时就调用append方法
stringBuilder.append("Hello");//stringBuilder结果为:Hello
String string = " World";
stringBuilder.append(string);//stringBuilder结果为:Hello World
在需要String对象时,可以使用toString方法得到一个String对象:
String newString = stringBuilder.toString();
StringBuffer用法和StringBuilder类似,不再赘述。
3.StringBuilder的部分API
- int length()
返回构建器或缓冲器中的代码单元数量 - StringBuilder append(String str)
追加一个字符串并返回this(即返回当前的StringBuilder对象) - StringBuilder append(char c)
追加一个代码单元并返回this(即返回当前的StringBuilder对象) - StringBui 1 der appendCodePoint(int cp)
追加一个代码点,并将其转换为一个或两个代码单元并返回 this。 - void setCharAt(int i ,char c)
将第 i 个代码单元设置为 c。 - StringBui 1 der insert(int offset,String str)
在 offset 位置插入一个字符串并返回 this。 - StringBuilder insert(int offset,Char c)
在 offset 位置插入一个代码单元并返回 this。 - StringBui 1 der delete(1 nt startindex,int endlndex)
删除偏移量从 startindex 到 -endlndex-1 的代码单元并返回 this。
4.字符串相等
String类型并不是Java中的基本类型,变量名指向的是对象在内存中的地址,所以不能使用常量的==来比较两个字符串是否相等,它仅仅是比较两个变量指向的地址是否相同。在不同的地址完全可能存在两个String值相同的对象,故而要调用equals方法进行比较。
String string1 = "a";
String string2 = "b";
String string3 = new String("a");
String string4 = "ab";
String string5 = new String("ab");
String string6 = string1 + string2;
String string7 = "a";
System.out.println(string1 == string3);//false
System.out.println(string4 == string5);//false
System.out.println(string5 == string6);//false
System.out.println(string4 == string6);//false
System.out.println(string1 == string7);//true
string6 = "a";
System.out.println(string1 == string6);//true
原因分析:
java中有字符串常量池,在采用直接赋值的方式(即String string1 = “a”;)创建一个字符串对象的时候,他会先在字符串常量池中查找是否有这个字符串,如果有,则将新创建的String变量指向该对象地址,如果没有,则在常量池新创建一个字符串,并让String变量指向它,所以直接赋相同值的两个String变量用是“相等的”,这里的相等是指他们指向的对象相同。
但是使用new操作将直接创建一个新的对象,而不管常量池,所以每一个new出来的对象都是不同的,他们的地址自然也不同,所以用“==”比较两个指向new出来的String对象的变量,其结果是false。
equals方法才是用来比较两个字符串字面量是否相等的方法
//equals方法比较字符串字面量是否相等
System.out.println(string4.equals(string5));//true
5.Java基本数据类型
基本数据类型与封装好的类的区别:
- 基本类型在传递参数是是按值传递,而封装类型是按引用传递的,即传递的是对象的地址
- 默认值不同,int是基本类型,默认值是0,而Integer是对象,对象的默认值为null
- 基本类型在内存中是存储在栈中,引用类型的引用(值的地址)存储在栈中,而实际的对象(值)是存在堆中。
Integer与int的区别:
- int是一种基本数据类型,而Integer是一种类,是int的包装类
- Integer类型的数据必须实例化后才能使用,int不必
- 他们的默认值不同
- int存储的是值,Integer变量存储的是对象的地址
6.Java的自动拆箱和装箱
讲道理int变量和Integer变量的比较是没有意义的,他们一个是基本数据类型,一个是类的实例;但是又应该可以比较,因为他们实际上都是为了表示一个值;实际上,java是支持这种比较的,在这里面java自动进行了装箱和拆箱的操作
Integer a = 1;//实际上java编译器自动进行了装箱的操作,
//等价于Integer a = Integer.valueOf(1);
上面编译器在编译期间自动进行的操作就叫做装箱
Integer a = 1;
int b = a;//这里编译器在编译期间进行拆箱
//等价于int b = a.intValue();
这就是java编译器的自动拆箱
由于编译器的自动拆箱与装箱,所以Integer和int类型的变量参与运算是等价的
7.Integer和int的比较
- 就像上面说的,new出来的Integer变量实际上是对Integer对象的引用,两个new出来的Integer对象地址不同,所以指向他们的变量是不可能相等的
Integer b = new Integer(1);
Integer c = new Integer(1);
System.out.println(b == c);//false
- 一个Integer类型的变量和int类型的变量进行比较时,由于Java的自动拆箱,只要他们表示的值相等就是相等的,等价于两个int类型的变量进行比较
int a = 1;
Integer d = 1;
System.out.println(a == d);//true
- 一个new出来的Integer变量与直接赋值产生的变量永远不相等,因为直接赋值的变量指向常量池里面的对象,在栈中,new出来的对象在堆中,他们的比较是对象地址的比较
Integer b = new Integer(1);
Integer d = 1;
System.out.println(b == d);//false
- 对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
Integer d = 1;
Integer e = 1;
System.out.println(d == e);//true
Integer f = 128;
Integer g = 128;
System.out.println(f == g);//false
这是因为Integer d = 1;在编译时装箱为Integer d = Integer.valueOf(1);
Integer.valueOf方法的源码如下:
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
其中IntegerCache.low = -128,IntegerCache.high = 127;
当-128 <= i <= 127时,返回常量池中已有的Integer对象的引用,所以实际上并没有创建新的对象,只不过是把已有对象的地址赋值给变量,所以这时两个变量指向同一个对象,变量值相等。
当i的值不在这个范围内时,返回new的一个对象的地址,这时情况就变成上述1的情况,两个new出来的对象的地址显然不同,故不相等