文章目录
(一)字符串String
1,string的创建方式
- 方式一
String str = "Java";
- 方式二
String str =new String("Java");
- 两种方式的区别: String 创建的字符串存储在公共池中,而 new 创建的字符串对象在堆上
- 示例:
String s1 = "Java"; // String 直接创建
String s2 = "Java"; // String 直接创建
String s3 = s1; // 相同引用
String s4 = new String("Java"); // String 对象创建
String s5 = new String("Java"); // String 对象创建
s1 == s2 ==s3 = true 比较的是内存地址
s3 == s4 == s5 = false 不同对象,地址不同(String对象的不可变性)
equals方法比较 都返回 true 因为String的equals方法的重写,比较的是堆中的值。
2,string的不可变性
1)不可变的原因
String是private final 初始化之后不可改变
public static void main(String[] args) {
String s = "ABCDEF";
System.out.println("s = " + s);
s = "123456";
System.out.println("s = " + s);
}
输出:
s = ABCDEF
s = 123456
-
解析:创建String对象的时候,s指向的是内存中的"ABDCEF",当执行语句s = “123456"后,其实又创建了一个新的对象"123456”,而s重新指向了这个新的对象,同时原来的"ABCDEF"并没有发生改变,仍保存在内存中。
-
有办法改变吗? 通过反射修改
public static void reflectString() throws Exception{
String s = "ABCDEF";
System.out.println("s = " + s);
Field valueField = s.getClass().getDeclaredField("value");
valueField.setAccessible(true);
char[] value = (char[]) valueField.get(s);
value[0] = 'a';
value[2] = 'c';
value[4] = 'e';
System.out.println("s = " + s);
}
输出:
s = ABCDEF
s = aBcDeF
3,String,StringBuffer与StringBuilder区别
- 1,String:字符串常量,字符串长度不可变
- 2,StringBuffer:字符串变量(Synchronized,即线程安全)
- 3,StringBuilder:字符串变量(非线程安全)
- 区别
(二)基本数据类型与封装类型
1,基本数据类型
2,自动装箱和拆箱
1,什么是装箱,拆箱
- 装箱就是 自动将基本数据类型转换为包装器类型;
- 拆箱就是 自动将包装器类型转换为基本数据类型
Integer i = 10; //装箱
int n = i; //拆箱
2,自动拆箱和装箱原理
- 装箱原理
基本数据类型–>封装类 (装箱)
Integer i = 10;
实际执行:
Integer i = Integer.valueOf(10);
分析Integer的valueOf源码:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high) // 没有设置的话,IngegerCache.high 默认是127
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
对于–128到127(默认是127)之间的值,Integer.valueOf(int i) 返回的是缓存的Integer对象(并不是新建对象),而其他值,执行Integer.valueOf(int i) 返回的是一个新建的 Integer对象。装箱的过程会创建对应的对象,这个会消耗内存,所以装箱的过程会增加内存的消耗,影响性能。
*** 拆箱原理**
封装类–>基本数据类型
Integer i = 10; //装箱
int t = i; //拆箱,实际上执行了 int t = i.intValue();
intValue()源码:
@Override
public int intValue() {
return value;
}
面试题:
int与Integer不同与比较?
-
不同
-
1、Integer是int的包装类,int则是java的一种基本数据类型
-
2、Integer变量必须实例化后才能使用,而int变量不需要
-
3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
-
4、Integer的默认值是null,int的默认值是0
-
比较
-
由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)。
-
、Integer变量和int变量比较时,只要两个变量的值是相等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较)
-
非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)
-
对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false。
-
原因:java对于-128到127之间的数,会直接从缓存中取,故相等。否则创建一个新的对象,故不等。
理解String为什么设计为不可变的?
- 在Java程序中String类型是使用最多的,这就牵扯到大量的增删改查,每次增删改差之前其实jvm需要检查一下这个String对象的安全性,就是通过hashcode,当设计成不可变对象时候,就保证了每次增删改查的hashcode的唯一性,也就可以放心的操作
- 字符串值是被保留在常量池中的,也就是说假若字符串对象允许改变,那么将会导致各种逻辑错误
- 网络连接地址URL,文件路径path通常情况下都是以String类型保存, 假若String不是固定不变的,将会引起各种安全隐患。
String,StringBuffer,StringBuilder区别?
上面有图表解析