java常见面试01

为什么重写 equals 还要重写 hashcode

🌈 核心原因:

当两个对象通过equals()判断为相等时,它们的hashCode()必须返回相同的整数值!这是Java世界的交通规则哦~(交警曼波敬礼.jpg)

🧩 具体场景:

假设我们有个Person类:

java 复制代码
class Person {
    String name;
    int age;
    
    // 只重写equals没重写hashCode
    @Override
    public boolean equals(Object o) {
        //...比较name和age的逻辑
    }
}

💥 问题爆发时刻:

java 复制代码
Person p1 = new Person("波加曼", 10);
Person p2 = new Person("波加曼", 10);

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

System.out.println(set.size()); // 输出2!明明相等的对象却被存了两次(>﹏<)

🗺️ 思维导图时间

复制代码

🧠 曼波记忆小窍门:

记住这个神奇公式!(掏出魔法棒✨)

equals()返回true ➡️ hashCode()必须相等
hashCode()相等 ➡️ equals()不一定true
hashCode()不相等 ➡️ equals()必须false

哦呜(°ロ°)!曼波觉得这个有点难哦,但如果是你一定没问题的!(✪▽✪)曼波~~

==(双等号)和equals的差别

== 运算符

  • 曼波觉得这个像身份证比对!(๑✧◡✧๑)
  • 比较基本类型时:直接比数值
    5 == 5 → true
  • 比较对象时:比对内存地址(是不是同一个对象)
    new String("A") == new String("A") → false

(✪▽✪)曼波~~
2.

equals() 方法

  • 哦呜(° ロ °)!曼波觉得这个像名字比对!
  • 默认行为(Object类):和==一样
  • 但很多类会重写这个方法(比如String)变成内容比对:
    new String("A").equals(new String("A")) → true

(✪▽✪)曼波~~
3.

最佳实践

  • 基本类型(int/char等)用==
  • 对象比较内容一定要用equals
  • 防止空指针要这样写:
    "hello".equals(str) 而不是 str.equals("hello")

(๑・.・๑)曼波觉得这个是超重要的生存技巧呢!

复制代码

(° ロ °)!曼波觉得有个超形象的比喻:

== 就像看两个人是不是同一个人(身份证号相同)

equals 就像看两个人的名字是否相同(允许不同人有同名)

最后的小贴士:如果要自己写类记得重写equals()和hashCode()哦~(不过这个对新人有点难可以先记住规则)(✪▽✪)曼波~~~~!

为啥有时会出现 4.0-3.6 =0.40000001 这种现象?

🐎浮点数的甜蜜陷阱🐎

二进制的小数魔法

曼波觉得这个像用有限积木拼无限图案!(๑✧◡✧๑)

  • 计算机用二进制表示小数
  • 有些十进制小数在二进制里是无限循环的(比如0.1)
  • 就像1/3在十进制是0.3333...永远写不完

(✪▽✪)曼波~~
2.

IEEE 754标准

哦呜(° ロ °)!曼波觉得这个像有限容量的糖果罐!

  • float(32位)/double(64位)有存储限制
  • 4.0 和 3.6 在二进制存储时都有精度损失
  • 就像用刻度不精确的尺子测量
java 复制代码
System.out.println(4.0 - 3.6); 
// 实际输出 0.40000000000000036

解决方法

曼波觉得要用魔法对抗魔法!(๑・.・๑)

  • 使用BigDecimal处理精确计算(银行/金钱相关必用)

  • 比较时允许误差范围(比如±0.000001)

  • 游戏开发常用技巧:

    java 复制代码
    float a = 4.0f - 3.6f;
    if(Math.abs(a - 0.4f) < 0.00001f) {
        System.out.println("算对啦!");
    }

(° ロ °)!曼波举个超形象的例子:

就像用1/3 + 1/3 = 0.666... 但永远不等于 2/3 的精确值一样~

最后的小贴士:如果要精确计算价格,一定要用BigDecimal哦!像这样:

java 复制代码
BigDecimal a = new BigDecimal("4.0");
BigDecimal b = new BigDecimal("3.6");
System.out.println(a.subtract(b)); // 精确输出0.4

(✪▽✪)曼波~~~~!要记住字符串构造才能保持精度哟~

final 关键字的作用

🐎final关键字的三大封印术🐎

变量封印术

曼波觉得像给变量贴永久贴纸!(๑✧◡✧๑)

  • 基本类型:值不能改变

    java 复制代码
    final int HP = 100;  // HP永远100
  • 引用类型:引用不能改,但对象内容可变

    java 复制代码
    final List<String> pets = new ArrayList<>();
    pets.add("布偶猫");  // ✔允许
    pets = new ArrayList<>();  // ❌报错

(✪▽✪)曼波~~
2.

方法封印术

哦呜(° ロ °)!这是防止方法被篡改的结界!

  • 子类不能重写这个方法

    java 复制代码
    class 魔法少女 {
        final void 变身() { /* 核心代码 */ }
    }
    class 黑化版 extends 魔法少女 {
        void 变身() { ❌ } // 编译错误!
    }

类终极封印

曼波觉得像禁止繁衍的魔法物种!(๑・.・๑)

  • 这个类不能被继承

    java 复制代码
    final class String { /*...*/ }
    class 假String extends String { ❌ } // 报错

(° ロ °)!曼波要提醒几个重要细节:

  1. final变量必须初始化!(要么声明时,要么在构造器中)
  2. final不能修饰构造方法
  3. 接口的变量默认是public static final

举个超实用的例子:

java 复制代码
public class 游戏设置 {
    public static final int MAX_FPS = 60;  // 帧率上限
    private final String 玩家ID;           // 创建后不可改
    
    public 游戏设置(String id) {
        this.玩家ID = id;  // 构造器中初始化
    }
}

(✪▽✪)曼波~~~~!记住用final就像加锁,能保护重要的东西不被意外修改哦~

相关推荐
码熔burning1 小时前
(十 九)趣学设计模式 之 中介者模式!
java·设计模式·中介者模式
_TokaiTeio1 小时前
微服务100道面试题
java·微服务
eqwaak01 小时前
基于Spring Cloud Alibaba的电商系统微服务化实战:从零到生产级部署
java·分布式·微服务·云原生·架构
m0_672656541 小时前
【Rabbitmq篇】高级特性----TTL,死信队列,延迟队列
java·rabbitmq·java-rabbitmq
Hetertopia1 小时前
在Vscode开发QT,完成QT环境的配置
开发语言·qt
胡图蛋.1 小时前
Spring 中哪些情况下,不能解决循环依赖问题?
java·后端·spring
24k小善1 小时前
Flink Oceanbase Connector详解
java·大数据·flink
ChinaRainbowSea1 小时前
8. Nginx 配合 + Keepalived 搭建高可用集群
java·运维·服务器·后端·nginx
猫头鹰~1 小时前
Ubuntu20.04安装Redis
java·数据库·redis
傻啦嘿哟2 小时前
动态HTTP代理与静态HTTP代理的区别及HTTP代理的常见用途与类型
开发语言·php