目录
一、八大基本类型
八大基本类型分别为:double、float、long、int、short、byte、boolean、char;
其对应基本封装类为:Double、Float、Long、Integer、Short、Byte、Boolean、Character。
其实现为封装类中封装一个基本类型,做的所有改动都基于基本类型,比较也是基于基本类型比较。一些额外的成员属性和方法包含但不限于取值范围、特殊取值、转换为其他进制以及常用操作。
- byte:8位,1字节,最大存储数据量是255,存放的数据范围是-128~127之间。
- short:16位,2字节,最大数据存储量是65536,数据范围是-32768~32767之间。
- int:32位,4字节,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。
- long:64位,8字节,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。
- float:32位,4字节,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。
- double:64位,8字节,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。
- boolean:只有true和false两个取值。
- char:16位,2字节,存储Unicode码,用单引号赋值。
二、String及其封装类
其内部封装了一个char[]数组,做的所有操作都是基于char[]数组,且本身不能够被继承,每次操作都会产生一个新的String对象。
1.String“+”拼接原理
字符串拼接原理:运行时, 两个字符串str1, str2的拼接首先会调用 String.valueOf(obj),这个Obj为str1,而String.valueOf(Obj)中的实现是return obj == null ? “null” : obj.toString(), 然后产生StringBuilder, 调用的StringBuilder(str1)构造方法, 把StringBuilder初始化,长度为str1.length()+16,并且调用append(str1)。接下来调用StringBuilder.append(str2), 把第二个字符串拼接进去, 然后调用StringBuilder.toString返回结果!
以下为测试:
String s=null;
s=s+"abc";
System.out.println(s);
/*
打印结果为:nullabc
*/
String拼接,有字符串变量参与时,中间会产生StringBuilder对象(JDK1.5之前为StringBuffer)
拼接时,如果String为null,则会调用appendNull,在末尾增加"null",因此后续再append(abc),结果为nullabc。
由此产生疑问,既然String+拼接时编译器默认调用StringBuilder提升效率,循环拼接时为什么要使用StringBuilder的append来进行拼接扩展,而不是使用+拼接?
答:StringBuilder封装的char[]数组是可变的,每次操作都是基于char[]类型的value。但String封装的char[]类型value是final,每次变动都会创建新的。循环拼接时StringBuilder操作的一直是原来的value,但String虽然在+拼接的过程中使用了StringBuilder,但最终在这一句里面还是会转成String,相当于每次循环都会产生新的String对象,以前的String封装的对象则没有引用,GC会被激活很多次,造成资源浪费。因此及时+拼接时虽然会自动转换,但多次循环拼接时还是得用StringBuilder。
2.StringBuilder
默认构造函数产生char[]数组长度为16,StringBuilder(String)长度为String.length+16,每次扩展长度为value.length*2 + 2。每次删除、增加、插入等操作都在char[]数组上,因此相对String对象而言开销更小。
3.StringBuffer
特性和StringBuilder基本一致,不同在于每个方法都有synchronized关键字修饰,保证线程安全。toString时会使用toStringCashe数组对象作为中间层过渡用以提高toString调用效率。若短时间内多个线程同时调用了toString,则直接把toStringCache引用指向新的String对象,而不用像StringBuilder重新copy对象中的value数组到新的String对象,同时也可以保证短时间内toString返回的为同一个对象String。