Java面试复习总结02

1、为什么要有hashCode?

以“HashSet”如何检查重复为例进行说明为什么要有hashCode?

  • 向HashSet中添加对象时,会先计算该对象的hashCode值来判断对象加入的位置
  • 如果该位置没有其他对象,HashSet就认为该对象没有重复出现,直接加入即可
  • 如果发现该位置有其他对象,再调用对象的equals()方法,进行判断两个对象是否真的相同
    • 两者相同,则不让其加入;
    • 两者不同,再进行重新散列到其他位置,再进行上述判断。
  • 上述过程我们可以大大减少对于equals()方法的调用,大大提高执行速度!

从上述实例可以知道,hashCode()和equals()都是用来比较两个对象是否相等的,配合使用提高效率

2、为什么JDK要同时提供hashCode()和equals()这两个方法?

  • 有了hashCode()之后,在一些容器(比如HashMap、HashSet)中,判断元素是否在对应容器中效率会更高!hashCode()帮助我们大大缩小了查找成本,减少了equals()的使用,从而提高了效率!
  • 两个对象的hashCode()值相等时(存在碰撞),并不代表两个对象就相等,所以还得有equals()搭配使用!

3、为什么重写equals()时必须重写hashCode()方法?

  • 因为equals() 判断两个对象相等,则这两个对象的hashCode值必须是相等的。
  • 如果只是重写equals()方法,不重写hashCode(),会导致基于哈希的集合类(如“HashSet”, “HashMap”)无法正常工作(无法正确地存储、查找和删除对象)
  • 假设我们有一个简单的类 Person,并且只重写了 equals() 方法:
public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }

    // 注意:我们没有重写 hashCode() 方法
}
  • 我们在 main 方法中测试使用 HashSet 来存储和查找 Person 对象:
import java.util.HashSet;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        Person person1 = new Person("Alice", 25);
        Person person2 = new Person("Alice", 25);

        Set<Person> set = new HashSet<>();
        set.add(person1);

        System.out.println("Set contains person2: " + set.contains(person2));
    }
}

在这个示例中,我们创建了两个 Person 对象 person1 和 person2,它们具有相同的属性值,并且根据 equals() 方法,它们应该被认为是相等的。然而,由于我们没有重写 hashCode() 方法,person1 和 person2 的默认 hashCode() 值(基于对象的内存地址)是不同的

运行上述代码时,输出将是:

Set contains person2: false
  • 原因分析:
    这是因为 HashSet 在调用 contains() 方法时,首先使用对象的 hashCode() 来快速定位对象的存储位置。由于 person1 和 person2 的 hashCode() 值不同,HashSet 认为它们在不同的位置,因此没有找到 person2,即使它们在逻辑上是相等的。

  • 这种情况就会导致以下问题
    插入失败:相等的对象可能会被插入到集合的不同位置,导致集合中存在重复元素。
    查找失败:相等的对象无法被正确地查找到,导致 contains() 方法返回 false。
    删除失败:相等的对象无法被正确地删除,导致 remove() 方法无法正常工作。

  • 解决方案:我们应该同时重写 hashCode() 方法,使其与 equals() 方法一致

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

4、String、StringBuffer、StringBuilder的区别?

  • String是不可变的:
    • 保存字符串的数组被 final 修饰且为私有的,并且String 类没有提供/暴露修改这个字符串的方法。
    • String 类被 final 修饰导致其不能被继承,进而避免了子类破坏 String 不可变
  • StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的
  • StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的

5、Throwable类常用方法有哪些?

  • String getMessage(): 返回异常发生时的简要描述
  • String toString(): 返回异常发生时的详细信息
  • String getLocalizedMessage(): 返回异常对象的本地化信息。使用 Throwable 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 getMessage()返回的结果相同
  • void printStackTrace(): 在控制台上打印 Throwable 对象封装的异常信息

6、什么是泛型?有什么作用?

  • Java中,泛型(Generics)是一种语言特性,允许类、接口和方法操作任何类型(数据类型),而不需要在编写代码时指定具体的类型。通过使用泛型,代码可以变得更加通用、类型安全且可重用;
  • 应用场景:
    • 自定义接口通用返回结果 CommonResult<T> 通过参数 T 可根据具体的返回类型动态指定结果的数据类型
    • 定义 Excel 处理类 ExcelUtil<T> 用于动态指定 Excel 导出的数据类型
    • 构建集合工具类(参考 Collections 中的 sort, binarySearch 方法)

7、反射是什么?

反射被称为框架的灵魂,主要是因为它赋予了我们在运行时分析类以及执行类中方法的能力。通过反射你可以获取任意一个类的所有属性和方法,你还可以调用这些方法和属性。

8、反射的应用场景?

  • 轻松地使用各种框架。像 Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射机制。
  • 这些框架中也大量使用了动态代理,而动态代理的实现也依赖反射。
  • Java 中的一大利器 注解 的实现也用到了反射

是因为你可以基于反射分析类,然后获取到类/属性/方法/方法的参数上的注解。你获取到注解之后,就可以做进一步的处理。

9、什么是注解?

  • Annotation (注解) 是 Java5 开始引入的新特性,可以看作是一种特殊的注释,主要用于修饰类、方法或者变量,提供某些信息供程序在编译或者运行时使用
  • 注解本质是一个继承了Annotation 的特殊接口

10、注解的解析方法有哪几种?

注解只有被解析之后才会生效,常见的解析方法有两种:

  • 编译期直接扫描:编译器在编译 Java 代码的时候扫描对应的注解并处理,比如某个方法使用@Override 注解,编译器在编译的时候就会检测当前的方法是否重写了父类对应的方法。
  • 运行期通过反射处理:像框架中自带的注解(比如 Spring 框架的 @Value、@Component)都是通过反射来进行处理的。
  • 22
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值