Java基础13(StringBuilder和StringBuffer 包装类)

目录

一. StringBuilder和StringBuffer

扩容机制:

链式操作:

一些方法:

区别:

StringBuilder拼接:

小结:

二. 包装类

创建对象:

自动装箱:

自动拆箱:

缓存池:

进制转换:

 一些常量:

小结:


一. StringBuilder和StringBuffer

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

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

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

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)  替换指定区间的字符串

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

●reverse() 反转

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

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

sb.delete(4, 8);

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

sb.deleteCharAt(5);

细节:

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

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   线程安全  效率相对差一点点

            StringBuffer sbBuffer=new StringBuffer();
    		sbBuffer.append("a");
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拼接:

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

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

多参构造方法:
         参数1:连接符
         参数2:拼接结果的字符串的开始字符串
         参数3:拼接结果的字符串的结束字符串

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

实例:

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类型、数组

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对象

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

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

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

自动装箱:

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

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

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

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

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

自动拆箱:

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

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

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

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

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

// 自动拆箱可能会有异常,不能为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。      

//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进制的整数

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

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

    // 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的包装类型还定义了一些有用的静态变量:

        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,因此,可以非常方便地直接通过包装类型获取各种基本类型:

Integer i1 = new Integer(128);
		System.out.println(i1.byteValue());//-128
		System.out.println(i1.shortValue());//128
// 向上转型为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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冯诺依曼转世

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值