每天一道面试题@第四天(Java基础)
对于第二天面试题的回答
1. Java 中的几种基本数据类型是什么?对应的包装类型是什么?各自占用多少字节呢?
2 种浮点型:float、double
1 种字符类型:char
1 种布尔型:boolean。
占用字节 | ||
byte | Byte | 1 |
short | Short | 2 |
int | Integer | 4 |
long | Long | 8 |
float | Float | 4 |
double | Double | 8 |
char | Character | 2 |
boolean | Boolean | 未精确定义 |
2. String 、 StringBuffer 和 StringBuilder 的区别是什么? String 为什么是不可变的?
String 不可变类、若对其修改,实际上是创建了新的String对象
StringBuffer 可变类、synchronized 同步锁修饰、线程安全
StringBuider 可变类、线程不安全、性能较高
StringBuffer和StringBuilder都继承了AbstractStringBuilder,但是StringBuffer的方法都加了synchronized同步锁
适用场景:
String 适用 不频繁修改的场景
StringBuffer 适用 多线程 频繁修改的场景
StringBuilder 适用 单线程 频繁修改的场景
String不可变的原因:
安全性:可以保证多线程下数据安全
缓存哈希码:String重写了hashCode()方法,并在对象创建时就计算、缓存了哈希码,由于String不可变,所以哈希不会改变,故而String作为HashMap、HashSet等集合的键时更高效
常量池的使用:如果String可变,那么常量池无法工作
性能优化:不可变的String 可被编译器优化,如 在字符串拼接时,编译器可将多个字符串常量合并为一个
字符串常量池:一种字符串缓存机制
字符串常量池是JVM为提升性能、减少内存消耗,针对String类专门开辟的一块区域,目的是为了避免字符串的重复创建
// 在字符串常量池中创建字符串对象 ”ab“
// 将字符串对象 ”ab“ 的引用赋值给 aa
String aa = "ab";
// 直接返回字符串常量池中字符串对象 ”ab“,赋值给引用 bb
String bb = "ab";
System.out.println(aa==bb); // true
当使用双引号创建字符串时,Java 会先在字符串常量池中查找是否存在内容相同的字符串。若存在,就返回该字符串的引用;若不存在,才在常量池中创建新的字符串对象。
什么时候常量池的字符串会被回收?
内存不足、长时间不使用、显式移除(System.gc()建议JVM回收)
3. String s1 = new String("abc"); 这段代码创建了几个字符串对象?
创建1个 或者 2个字符串对象,具体取决于字符串常量池是否已经存在"abc"字符串
在执行 new String("abc")时,会先检查字符串常量池中是否存在"abc",如果不存在"abc",则会在字符串常量池中创建一个"abc"字符串对象
再使用new 关键字时会在堆内存中创建一个新的String对象,这个对象的值是"abc",它就会引用字符串常量池的"abc"对象
另外一种情况,字符串常量池中存在"abc",会直接 用 new 关键字创建一个String对象,引用常量池的"abc"
4. == 与 equals?hashCode 与 equals ?
== 用于比较基本类型的值,或比较引用类型的内存地址
equals() 在未被重写时,和 == 一样比较对象的内存地址;但被重写后,通常比较对象的内容
像 String
、Integer
等都对 equals()
方法进行了重写,重写后比较的是对象的内容:
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1.equals(str2)); // 输出: true
System.out.println(str1 == str2);// 输出: false
hashCode() 方法 会返回对象的哈希码值,是一个int 类型的整数。哈希码的主要用途是在哈希表(如 HashMap、HashSet 等)中快速查找对象。
hashCode() 和 equals() 的关系
在hashCode() 和 equals() 方法需要遵循以下几个规则:
如果两个对象相等(equals() 方法返回 true),那么它们的哈希码值必须相同。也就是说,如果 obj1.equals(obj2) 返回 true,那么 obj1.hashCode() 必须等于 obj2.hashCode()。
如果两个对象的哈希码值相同,它们不一定相等。即 obj1.hashCode() 等于 obj2.hashCode() 时,obj1.equals(obj2) 不一定返回 true。
【强制】所以重写equals(),一定要重写hashCode()