Java13基础(StringBuilder和StringBuffer 包装类)

目录

[一. StringBuilder和StringBuffer](#一. StringBuilder和StringBuffer)

扩容机制:

链式操作:

一些方法:

区别:

StringBuilder拼接:

小结:

[二. 包装类](#二. 包装类)

创建对象:

自动装箱:

自动拆箱:

缓存池:

进制转换:

一些常量:

小结:


一. StringBuilder和StringBuffer

String类的特点:任何的字符串常量都是String对象,而且String的常量一旦声明不可改变,如果改变对象内容,改变的是其引用的指 向而已。

Java标准库提供了StringBuilder,它是一个可变对象,可以预分配缓冲区,这样,往StringBuilder中新增字符时,不会创建新的临时对象:

●String不可变字符串
●StringBuilder可变字符串

java 复制代码
public static void main(String[] args) {
String不可变字符串
//StringBuilder可变字符串
//StringBuilder(); 无参构造创建,初始化数组char[]的容量为16,扩容<<1+2容量够,则直接返回newCapcity ,如果扩容后容量不够newCpacity = minCpacity
//StringBuilder(容量); 初始化容量为指定容量的char[]数组
//StringBuilder(str); super(str.length() + 16);
		StringBuilder sb = new StringBuilder("我爱学习");
		for (int i = 0; i < 100; i++) {
			// 追到到末尾
			sb.append(i).append(",");
		}
		// insert追加内容到指定位置
		sb.insert(0, "你好");

		String str = null;// StringBuilder可以追加null
		sb.append(str);
		System.out.println(sb);
	}

扩容机制:

见 StringBuilder与StringBUffer扩容机制

链式操作:

如果我们查看StringBuilder的源码,可以发现,进行链式操作的关键是,定义的append()方法会返回this,这样,就可以不断调用自身的其他方法。

一些方法:

●replace(start, end, str) 替换指定区间的字符串

java 复制代码
StringBuilder sb = new StringBuilder("还是想考研");
//  replace(start, end, str)  替换指定区间的字符串
		sb.replace(0, 1, "zkt");
		System.out.println(sb);// zkt是想考研

●reverse() 反转

java 复制代码
//	反转
		StringBuilder sb = new StringBuilder("还是想考研");
		sb.reverse();
		System.out.println(sb);// 研考想是还

●delete(起始,结束)::删除从start(包含)到end(不包含)位置的字符,start为0~length-1,end可以超出长度。

java 复制代码
sb.delete(4, 8);

●deleteCharAt(下标):删除某个索引位置上的字符,index不能越界

java 复制代码
sb.deleteCharAt(5);

细节:

由于StringBuilder和StringBuffer没有重写equals方法,所以还是使用的Object的equals方法。对比的是两个对象的地址是否相等。为了比较StringBuilder和StringBuffer字符串内容是否相等,需要先将其转换为string,String 由于重写了equals方法,所以使用equals函数是对比两个字符串内容是否相等。

java 复制代码
StringBuilder sb1 = new StringBuilder("abc");
		StringBuilder sb2 = new StringBuilder("abc");
		System.out.println("地址是否相等" + (sb1 == sb2));// 地址是否相等false
		// 没有重写equals,比较的仍旧是地址
		System.out.println("内容是否相等" + (sb1.equals(sb2)));// 内容是否相等false
		System.out.println(sb1.toString().equals(sb2.toString()));// true

区别:

●StringBuilder 类的继承和实现一样 1.5 线程不安全 性能好
●StringBuffer 类的继承和实现一样 JDK1.0 线程安全 效率相对差一点点

java 复制代码
            StringBuffer sbBuffer=new StringBuffer();
    		sbBuffer.append("a");
java 复制代码
String[] nameString = { "zkt1", "zkt2", "zkt3", "zkt4" };

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < nameString.length; i++) {
			sb.append(nameString[i]).append(",");
		}
		
		//sb.replace(sb.length()-1, sb.length(), "!");
		sb.deleteCharAt(sb.length()-1).append("还是想考研!");
		System.out.println(sb);//zkt1,zkt2,zkt3,zkt4还是想考研!

StringBuilder拼接:

单参构造方法:参数含义每个元素之间的拼接符

java 复制代码
//单参构造方法:参数含义每个元素之间的拼接符
		StringJoiner sj =new StringJoiner(",");

多参构造方法:

参数1:连接符
参数2:拼接结果的字符串的开始字符串
参数3:拼接结果的字符串的结束字符串

java 复制代码
//		 多参构造方法:
//		 参数1:连接符
//	         参数2:拼接结果的字符串的开始字符串
//	         参数3:拼接结果的字符串的结束字符串
		StringJoiner sj =new StringJoiner(",", "hello:", "!");

实例:

java 复制代码
String[] nameString = { "zkt1", "zkt2", "zkt3", "zkt4" };

//		单参构造方法:参数含义每个元素之间的拼接符
//		StringJoiner sj =new StringJoiner(",");
		
//		 多参构造方法:
//		 参数1:连接符
//	         参数2:拼接结果的字符串的开始字符串
//	         参数3:拼接结果的字符串的结束字符串
		StringJoiner sj =new StringJoiner(",", "hello:", "!");
		for (String str : nameString) {
			sj.add(str);
		}
		
		System.out.println(sj);//hello:zkt1,zkt2,zkt3,zkt4!
		
		//如果只对数组中元素进行拼接,开头结尾没元素,String.join方法简便
		String string = String.join(",", nameString);
		System.out.println(string);//zkt1,zkt2,zkt3,zkt4

小结:

●StringBuilder是可变对象,用来高效拼接字符串。
●StringBuilder可以支持链式操作,实现链式操作的关键是返回实例本身。
●StringBuffer线程安全(现在很少使用),性能较差;StringBuilder线程不安全,但性能较好。

二. 包装类

在Java中,数据类型被分两种:基本类型和引用类型。引用类型可以赋值为null,表示空,但基本类型不能赋值为null:
●基本类型:byte,short,int,long,boolean,float,double,char
●引用类型:所有class和interface类型、数组

java 复制代码
String s = null;
int n = null; // compile error!

Java核心库为每种基本类型都提供了对应的包装类型, 我们可以直接使用,并不需要自己去定义:

|---------|---------------------|
| 基本类型 | 对应的引用类型 |
| boolean | java.lang.Boolean |
| byte | java.lang.Byte |
| short | java.lang.Short |
| int | java.lang.Integer |
| long | java.lang.Long |
| float | java.lang.Float |
| double | java.lang.Double |
| char | java.lang.Character |

创建对象:

●new操作符创建Integer对象

java 复制代码
//new操作符创建Interger对象
		Integer n =new Integer("22");
		int i = 10;
		Integer n1 =new Integer(i);

●调用valueOf方法创建Integer对象(发生方法的重载)

java 复制代码
		//调用valueOf方法创建Interger对象
		Integer n2 = Integer.valueOf(20);
		Integer n3 = Integer.valueOf("99");

自动装箱:

因为int和Integer可以互相转换,所以,Java编译器可以帮助我们自动在int和Integer之间自动进行类型转换:

自动装箱: 基本数据类型-->引用数据类型

这种直接把int变为Integer的赋值写法,称为自动装箱(Auto Boxing)

编译器自动使用Integer.valueOf(int)

java 复制代码
// 自动装箱: 基本数据类型-->引用数据类型
		int i1 = 10;
		Integer n1 = i1; // Integer.valueOf(i1)自动装箱
		System.out.println(n1.toString());

自动拆箱:

自动拆箱: 基本数据类型<--引用数据类型

把Integer变为int的赋值写法,称为自动拆箱(Auto Unboxing)

编译器自动使用Integer.intValue()

java 复制代码
// 自动拆箱: 基本数据类型<--引用数据类型
		Integer n2 = new Integer(99);
		int i2 = n2; // n2.intValue();自动拆箱
		System.out.println(i2);

装箱和拆箱会影响代码的执行效率,因为编译后的class代码是严格区分基本类型和引用类型的。并且,自动拆箱执行时可能会报NullPointerException

java 复制代码
// 自动拆箱可能会有异常,不能为null,不然会出现NullPointerException
		Integer n3 = null;
		int i3 = n3;
		System.out.println(i3);

注意:自动装箱和自动拆箱只发生在编译阶段,目的是减少代码量

缓存池:

可以发现,==比较,较小的两个相同的Integer返回true,较大的两个相同的Integer返回false,这是因为Integer内部已经把-128~+127在缓存池中已经创建好了。所以,编译器把Integer x = 127;自动变为Integer x = Integer.valueOf(127);就可以直接使用缓存池中的127,从而节省内存。所以,基于缓存池的存在,Integer.valueOf()对于-128~+127之间的数字,始终返回相同的实例,因此,==比较"恰好"为true,但我们绝不能因为Java标准库的Integer内部有缓存优化就用==比较,必须用equals()方法比较两个Integer。

java 复制代码
//Integer.valueOf() 缓存池 -128-127之间
		Integer i1 = Integer.valueOf(127);
		Integer i2 = Integer.valueOf(127);
		System.out.println(i1 == i2);//true
		System.out.println(i1.equals(i2));//true
 
		Integer i3 = Integer.valueOf(128);
		Integer i4 = Integer.valueOf(128);
		System.out.println(i3 == i4);//false
		System.out.println(i3.equals(i4));//true
 
		//new开辟新空间
		Integer i5 = new Integer(100);
		Integer i6 = new Integer(100);
		System.out.println(i5 == i6);//false

进制转换:

进制转换 String<--->int:

●Integer.parseInt();对应进制的字符串转成10进制的整数

java 复制代码
// Integer.parseInt();对应进制的字符串转成10进制的整数
		int x1 = Integer.parseInt("10");// 10进制字符串10->10进制整数10
		System.out.println("10进制字符串->10进制整数" + x1);// 10
java 复制代码
int x2 = Integer.parseInt("10", 2);// 2进制字符串10->10进制整数2
		System.out.println("2进制字符串10->10进制整数" + x2);// 2

●Integer还可以把整数格式化为指定进制的字符串

java 复制代码
    // Integer.toString();10进制整数转成对应进制的字符串
		String s1 = Integer.toString(100);// 10进制整数100->10进制字符串
		System.out.println("10进制整数100->10进制字符串" + s1);// 100
 
		String s2 = Integer.toString(5, 2);// 10进制整数5->2进制字符串
		System.out.println("10进制整数5->2进制字符串" + s2);// 101
 
		// 将10进制的整数转成16,8,2进制的字符串
		// 10->16
		String hexString = Integer.toHexString(15);
		System.out.println(hexString);// f
 
		// 10->8
		String octString = Integer.toOctalString(8);
		System.out.println(octString);// 10
 
		// 10->2
		String binString = Integer.toBinaryString(5);
		System.out.println(binString);// 101

一些常量:

Java的包装类型还定义了一些有用的静态变量:

java 复制代码
        System.out.println(Integer.MAX_VALUE);//2147483647
		System.out.println(Integer.MIN_VALUE);//-2147483648

		System.out.println(Long.SIZE);//64
		System.out.println(Long.BYTES);//8
		System.out.println(Long.MAX_VALUE);//9223372036854775807
		System.out.println(Long.MIN_VALUE);//-9223372036854775808	

最后,所有的整数和浮点数的包装类型都继承自Number,因此,可以非常方便地直接通过包装类型获取各种基本类型:

java 复制代码
Integer i1 = new Integer(128);
		System.out.println(i1.byteValue());//-128
		System.out.println(i1.shortValue());//128
java 复制代码
// 向上转型为Number:
Number num = new Integer(999);

// 获取byte, int, long, float, double:
byte b = num.byteValue();
int n = num.intValue();
long ln = num.longValue();
float f = num.floatValue();
double d = num.doubleValue();

小结:

●Java核心库提供的包装类型可以把基本类型包装为class

●自动装箱和自动拆箱都是在编译期完成的(JDK>=1.5)

●装箱和拆箱会影响执行效率,且拆箱时可能发生NullPointerException

●包装类型的比较必须使用equals()

●整数和浮点数的包装类型都继承自Number

相关推荐
数据小爬虫@1 分钟前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python
ZJ_.3 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
Narutolxy9 分钟前
深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223
开发语言·golang·gin
XiaoLeisj14 分钟前
【递归,搜索与回溯算法 & 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)
数据结构·算法·leetcode·决策树·深度优先·剪枝
Hello.Reader16 分钟前
全面解析 Golang Gin 框架
开发语言·golang·gin
禁默27 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Cachel wood33 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Jasmine_llq34 分钟前
《 火星人 》
算法·青少年编程·c#
Code哈哈笑36 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习