⭐ 1.hasCode和equals的关系
hashCode用于获取哈希码(散列值),equals用于比较两个对象是否相等。
(1)两个对象相等,则它们必须具有相同的哈希值;
(2)两个对象具有相同的哈希值,但它们不一定相等。
Set接口代表无序的、元素不可重复的集合,以HashSet为例,要将元素存入HashSet,需要判断集合中是否存在该元素,从而避免重复存储。通过遍历集合来判断元素是否存储,效率太低。实际上,可以通过计算该元素的哈希值,并调用equals方法来解决这个问题。
HashSet首先会调用对象的HashCode方法来获取其哈希值,并通过哈希值判断该元素在集合中的存储位置。假设该位置已经存在一个对象,则调用equals方法对两个对象进行比较。若相等则说明对象重复,此时不会保存新加的对象。若不相等,则说明两个对象不重复,只是存储位置发生了碰撞,此时HashSet会采用链式结构在同一个位置保存多个对象。若均不相等,则将其添加到最后一个对象之后。
⭐ 2.为什么要重写hashCode和equals方法?
Object类提供的equals方法默认使用==来进行比较,也就是两个对象是同一个对象时,才会返回相同的结果。但是在实际应用中,需求是不同对象具有相同的内容,也要认为其相等。因此,此时 Object类中的equals方法的默认实现没有实用价值,因此要进行重写。
而hashCode和equals之间具有联动关系,因此重写equals方法时,需要对hashCode方法进行重写,使得这两个方法始终满足相关的约定。
⭐ 3.==和equals的区别
(1)==
作用于基本数据类型时,用于比较两个数值是否相等;
作用于引用数据类型时,用于比较两个对象的内存地址是否相等,即判断它们是否是同一对象。
(2)equals
没有重写时,用于比较两个对象的内存地址是否相同;
重写之后,一般会按照两个对象的内容进行比较,若两个对象内容相同,则认为它们相等。
4.String和StringBuffer有什么区别?
String是final修饰的,是不能被继承的。String是不可变类,即一旦String对象被创建后,包含在这个对象中的字符串序列是不可改变的,直到这个对象被销毁。
StringBuffer代表一个字符串序列可变的对象,当一个StringBuffer被创建后,通过StringBuffer提供的append()、insert()等方法可以改变字符串序列,直到该字符串序列满足要求,再调用它的toString()方法将其转换为String对象。
5.StringBuffer和StringBuilder有什么区别?
StringBuffer和StringBuilder有共同的父类AbstractStringBuilder,它们都代表可变的字符串对象,有基本相同的构造方法和成员方法。但是StringBuffer是线程安全的,StringBuilder是非线程安全的。所以,StringBuilder的性能略高。一般情况下,创建一个字符串可变的对象,推荐采用StringBuilder。
6.使用字符串时,new和" "推荐哪一个?
以"hello"和new Sting("hello")为例,如下,
当Java程序直接使用"hello"的字符串直接量时,JVM会使用常量池来管理这个字符串;
当使用new Sting("hello")时,JVM会先使用常量池管理"hello"直接量,再调用String类的构造器来创建一个String对象,新创建的String对象被保存在堆内存中。
由此可知,采用new的方式会多创建一个对象,占用的内存更大,因此,一般采用直接量的方式创建方式。
7.说一说对字符串拼接的理解
字符串拼接有多种方式,其中最常用的有四种。下面列举了这4种方式各自适应的场景,
(1)+运算符:如果拼接的都是字符串直接量,则使用+运算符实现拼接;
(2)StringBuilder:如果拼接的字符串中包含变量,且不要求线程安全,则使用StringBuilder;
(3)StringBuffer:如果拼接的字符串中包含变量,且要求线程安全,则使用StringBuffer;
(4)String类的concat方法:如果只是对两个字符串进行拼接,且包含变量,则使用concat方法。
8.两个字符串相加的底层是如何实现的?
情况1:如果拼接的都是字符串直接量,则在编译时编译器会直接将其优化为一个完整的字符串;
情况2:如果拼接字符串中包含变量,则在编译时编译器会采用StringBuilder对其进行优化,将这些字符串拼接在一起。
9.String s = "abc",这个过程会创建什么?存放在哪里?
JVM会使用常量池来管理字符串直接量。在执行该语句前,JVM会先检查常量池中是否存在“abc”。若没有,则将“abc”存入常量池;反之,就复用常量池中的“abc”,将其赋值给变量s。
10.new String("abc")是去了哪里?仅是在堆里面吗?
在执行该语句时,JVM会使用常量池来管理字符串直接量,即将“abc”存入常量池;再创建一个新的String对象,该对象被保存在堆内存中,并且,堆中对象的数据会指向常量池中的直接量。
11.字符型常量和字符串常量的区别
(1)形式上
字符型常量仅使用单引号引起一个字符,字符串常量使用双引号引起多个字符;
(2)含义上
字符常量相当于一个整型值(ASIIC码),可以参与表达式运算,字符串常量代表一个地址;
(3)占内存大小上
字符型常用占用2个字节,字符串常量占用若干个字节。