目录
为什么两个对象有相同的hashCode值,它们也不一定是相等的?
String,StringBuffer,StringBuilder的区别?
String#equals和Object#equals的区别?
String s1 = new String("abc");这句话创建了几个字符串对象?
Java常见类
Object
hashCode()有什么用?
hashCode()
方法用于获取对象的哈希码(Hash Code),也成为散列码,它的主要作用是用于在哈希表等数据结构中进行快速查找、插入和删除操作。
为什么要有hashCode?
hashCode()和equals()都是用于比较两个对象是否相等 。
在使用哈希集合(如 HashSet
、HashMap
、Hashtable
等)存储对象时,通过哈希码来确定对象的存储位置。这样可以在查找对象时快速定位到对象所在的位置,提高了查找效率。
那为什么不止提供hashCode()方法?
这是因为两个对象的hashCode值相等并不代表两个对象就相等。
为什么两个对象有相同的hashCode值,它们也不一定是相等的?
因为hashCode()所使用的哈希算法也许刚好会让多个对象返回相同的hash值。越糟糕的哈希算法越容易碰撞。
总结:
如果两个对象的hashCode值相等,这两个对象不一定相等(哈希碰撞)
如果两个对象的hashCode值相等并且equals方法也返回true,我们才认为这两个对象相等
如果两个对象hashCode值不相等,我们直接认为这两个对象不相等。
为什么重写equals时必须重写hashCode()方法?
因为两个相等的对象的hashCode值必须想相等。 通过equals判断两个对象是否相等之前会先通过两个对象的hashCode值进行判断。如果两个对象的hashCode值不相等,直接认为两个对象不相等。
String
String,StringBuffer,StringBuilder的区别?
-
String(字符串常量):
String
类是不可变的,即一旦创建了字符串对象,就无法修改它的内容。每次对字符串进行修改(如拼接、替换等),都会创建一个新的字符串对象。- 字符串常量池中的字符串对象是唯一的,如果创建了一个内容相同的字符串常量,它们会共享同一个对象。
- 因为字符串不可变性的特点,适用于字符串不经常变化的情况,例如表示常量、配置信息、数据库连接等。
-
StringBuffer(线程安全的可变字符串):
StringBuffer
类是可变的,可以通过方法对字符串进行修改,而不会创建新的对象。StringBuffer
是线程安全的,它的方法都是同步的,适用于多线程环境下的字符串操作。- 由于线程安全的特点,
StringBuffer
的性能比较低,不适合在单线程环境下大量字符串操作。
-
StringBuilder(非线程安全的可变字符串):
StringBuilder
类与StringBuffer
类功能相似,也是可变的字符串对象,可以通过方法对字符串进行修改,而不会创建新的对象。StringBuilder
不是线程安全的,因此它的性能比StringBuffer
更高。- 由于不需要考虑线程安全问题,
StringBuilder
适用于单线程环境下的大量字符串操作。
因此,根据需要选择合适的字符串类:
- 如果字符串内容不经常变化,或者在多线程环境下,应该使用
String
类。 - 如果在单线程环境下进行大量字符串操作,应该使用
StringBuilder
类。 - 如果在多线程环境下进行字符串操作,应该使用
StringBuffer
类。
String为什么是不可变的?
- 保存字符串的数组被final修饰且为私有,并且String类没有提供/暴露修改这个字符串的方法
- String类被final修饰导致其不能被继承,进而避免了子类破坏String不可变。
- 在Java9之后,String,StringBuilder,StringBuffer的实现改用byte数组存储字符串。
String#equals和Object#equals的区别?
String中的euqals方法是被重写过的,比较的是String字符串的值是否相等。Object的equals方法比较的是对象的内存地址
字符串常量池的作用了解吗?
字符串常量池是JVM为了提升性能和减少内存消耗针对字符串专门开辟的一块区域,主要目的是为了避免字符串的重复创建。
String s1 = new String("abc");这句话创建了几个字符串对象?
会创建1或2个字符串对象。
-
一种情况是创建一个字符串对象: 如果字符串常量池中已经存在内容为
"abc"
的字符串对象,则这个代码只会创建一个字符串对象,因为new String("abc")
不会在常量池中创建新的字符串对象,而是在堆中创建一个新的对象。 -
另一种情况是创建两个字符串对象: 如果字符串常量池中不存在内容为
"abc"
的字符串对象,则这个代码会创建两个字符串对象:一个是在常量池中创建的"abc"
字面值字符串对象,另一个是在堆中创建的new String("abc")
对象。