Java13基础(StringBuilder和StringBuffer 包装类)

发布于:2024-05-13 ⋅ 阅读:(138) ⋅ 点赞:(0)

目录

一. StringBuilder和StringBuffer

扩容机制:

链式操作:

一些方法:

区别:

小结:

二. 包装类

创建对象:

自动装箱:

自动拆箱:

缓存池:

进制转换:

 一些常量:

小结:


一. 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);// 研考想是还

细节:

由于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是可变对象,用来高效拼接字符串。
●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操作符创建Interger对象

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

●调用valueOf方法创建Interger对象

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

自动装箱:

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

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

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

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

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

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

自动拆箱:

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

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

// 自动拆箱: 基本数据类型<--引用数据类型
		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


网站公告

今日签到

点亮在社区的每一天
去签到