API:String、integer

字符串

java.lang.String :字符串类,并且该类加final修饰;
底层就是char数组 private final char value [];
所以字符串有很多的特性就是数组的特性

# 1.字符串一旦创建不能更改;

2.为了提升字符串的访问效率,java中提出了字符串常量池,相当于一个缓存区;
引用类型对象应该保存在堆内存,但字符串不同,保存在字符串常量池中;
3.在程序的执行过程中,如果程序要用到某个字符串;虚拟机会先前常量池中搜索,是否存在这个字符串;
如果有就直接指向改字符串,如果没有就新建一个字符串对象,并指向这个字符串常量池的地址;
因为String一旦创建不可更改,所以不要频繁拼接字符串
因为效率比较低,还浪费空间,并且垃圾回收也会有一定问题
java.lang.StringBuffer java.lang.StringBuilder

1:StringBuffer和StringBuilder是什么?

	一个可变的字符串缓冲区

2:原理?
预先在内存中申请一块空间,可以容纳字符序列(字符数组)
如果 预留空间不够,会进行自动扩容
底层都是char[] ,并且默认初始化容量是16个字符

3:String,StringBuffer,StringBuilder最大的区别?

	①String不可变字符序列,而StringBuilder和StringBuffer是可变字符序列
	②StringBuffer是线程安全,在多线程环境下,不会出现问题,所以效率低,一般常用于类中
	③StringBuilder是非线程安全,在多线程环境下可能出现问题,效率高,一般用于方法中

4 :如何选择StringBuilder和StringBuffer

	多线程环境下,是否有可能出现多个线程同时操作同一个数据的可能(增,删,改);

String 不可以任意拼接的字符串
String s2 = “a” + “b”; 这种写法,在编译阶段,就会把+ 去掉;变成ab;
“a” +“b” a和b都是字面量,需要在编译阶段说明临时空间,所以需要通过值确定类型
编译时看到是两个字符串相加,就直接把+省略,保存ab
s1 == s2 是同一个内存地址 所以相等 true

	String s3 = a + b;
	a和b是变量,编译阶段是不确定变量的值的
	在运行的时候,由于是两个字符串变量相加,新建了一个对象,在堆内存用来存它的值;
	自动创建一个StringBuffer对象,然后把两个变量拼接到一起,最终转换为String类型
	而是以    return new String(value, 0, count);   所以 s3是指向堆内存的

包装类 : 封装了基本类型的操作,更方便我们使用

	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
	boolean -- java.lang.Boolean

既然有了基本类型,为什么还要使用包装类呢?
方便;为了理论上的完整(面向对象);

想要创建一个方法,该方法可以接收任何类型?
Object ,因为Object是所有类的祖类.
由于多态的原因,可以接收任何对象.
基本类型并不是Object的子类,怎么接收?
包装类 , 可以把基本类型转换为对应的包装类类型,
而包装类也是个类,也是Object的子类.

java1.5新特性

自动装箱:把 基本数据类型 自动转换为 对应的包装类
自动拆箱:把 包装类 自动转换为 基本数据类型
都是在编译时完成的;

深入理解自动装箱和自动拆箱

1.都是编译时的概念,和运行时无关
2.装箱的时候,会在编译时 自动把赋值 操作 变成 Integer.valueOf(222)
3.String , Integer,Double 等 八种包装类 和String 都覆写了toString(),equals() , hashCode() 方法
4. Integer.valueOf(xxx) : 方法实现
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

5.valueOf : 把基本类型转换为Integer类型

理解:一个大箱子,放的下就直接放进来用,有就直接拿走;
			放不下东西了就放个信息,告诉去哪里拿它;

(箱子的大小)
里面初始化了一个整型常量池,值的范围是在 -128~127之间
就是一个Integer[] 数组 有 256个对象,对象中的int值 分别为 -128,-127…126,127 下标 是 0~ 255
(源码)
在 private static class IntegerCache 类中 是 Integer中的一个静态内部类
三个变量
static final int low = -128;
static final int high;
static final Integer cache[];
并且在 static 代码块中 对这个数组进行了初始化操作

	如果 值 在 -128~127之间 就直接去这个缓存数组中找对应的对象即可,不用再重新创建Integer对象
		   return IntegerCache.cache[i + (-IntegerCache.low)];  
				// IntegerCache.low 是 -128   
				// (-IntegerCache.low) : 就是 128  负负得正
				// 加上 我们要添加的数据,就能得到 对应的值所在缓存数组中的下标索引
				// 把该对象返回

	那么这样的话,如果是通过自动装箱或者是通过valueOf方法赋值的两个值都符合该范围,那么 这两个变量保存的内存地址是一致的,则使用 == 也是true
		如  Integer i1 = 123;  Integer i2 = 123;  或者 Integer i3 = Integer.valueOf(123);  他们的内存地址是相等的,找到的是同一个对象

(箱子不够大的时候)
反之 , 就等于new Integer(xxx)
return new Integer(i); 既然是new 那么 堆内存会重新创建新的对象,那么尽管初始化的int值一样,但是内存地址也不同
所以 使用 == 也是false,此时 应该使用equals 来比较是否相等
如 Integer i4 = Integer.valueOf(128); Integer i5 = Integer.valueOf(128); 或者是 Integer i6 = new Integer(1)

猜你喜欢

转载自blog.csdn.net/MIRACLE_Ying/article/details/112914005
今日推荐