Java笔试题记录

前言

笔者最近面试时碰到了一道面试题,个人觉得出得挺好的,特此记录以供大家一起学习。

public class Demo {

    public static void main(String args[]) {

    System.out.println(new Simpson("Bart").equals(new Simpson("Bart")));
    Simpson overriddenHomer = new Simpson("Homer") {
      public int hashCode() {
          return (43 + 777) + 1;
      }
    };

    System.out.println(new Simpson("Homer").equals(overriddenHomer));

    Set set = new HashSet(Set.of(new Simpson("Homer"), new Simpson("Marge")));
    set.add(new Simpson("Homer"));
    set.add(overriddenHomer);

    System.out.println(set.size());

    }

    static class Simpson {
        String name;

        Simpson(String name) {
            this.name = name;
        }

        @Override
        public boolean equals(Object object) {
            Simpson otherSimpson = (Simpson) object;
            return this.name.equals(otherSimpson.name) && this.hashCode() == otherSimpson.hashCode();
        }

        @Override
        public int hashCode() {
            return (43 + 777);
        }

    }

}

问题:上述代码运行结果是()

A)true true 4

B)true false 3

C)true false 2

D)false true 3

我的解题过程:

  • 第一个输出结果

    System.out.println(new Simpson("Bart").equals(new Simpson("Bart")));
    

    内部类 Simpson 定义了新的构造函数,重写了 equals 和 hashCode 方法。在这两个对象 equals 时要根据重写后的方法来判断返回值。重写后的 equals 方法的判断条件有两个:1. 内部 String 变量 name 的字符串比较。2. 重写后的 hashCode 方法返回值比较。

    这里两个 Simpson 对象的内部变量 name 都是在创建对象时通过构造函数赋的值,且构造函数传参都是 “Bart”,所以两个对象的 name 值都是 “Bart” ,String 类型的原生 equals 方法实现原理是将 String 转成 char 数组并按下标逐一对比是否相等,由此可知条件一是满足的。

    又因为重写后的 hashCode 方法返回值是固定的 (43 + 777),遂两个对象的 hashCode 方法返回值肯定也是相同的,至此第二个条件也满足。可以得出第一项输出值为 true。

    
    	public boolean equals(Object object) {
    	    Simpson otherSimpson = (Simpson) object;
    	    return this.name.equals(otherSimpson.name) && this.hashCode() == otherSimpson.hashCode();
    	}
    	
    
    	public int hashCode() {
    	    return (43 + 777);
    	}
    
  • 第二个输出

    System.out.println(new Simpson("Homer").equals(overriddenHomer));
    

    题中在创建 overriddenHomer 对象时很调皮的再次重写了 hashCode 方法,所以该对象 hashCode 方法的返回值是重写后的值,也就是 (43 + 777) + 1,与对象原方法返回值不同。“&&” 是逻辑与,"&&" 两边条件同时满足时才会返回 true, 由此可知第二项输出值为 false。

  • 第三个输出

    System.out.println(set.size());
    

    Set.of() 函数是 jdk1.9 才开始有的新特性,该方法主要是为了像题中一样快速往 HashSet 中添加元素。

    题中在创建 set 对象时就添加了 “Homer”、“Marge” 两个元素。由于 HashSet 自带去重机制,去重原理就是在 add 函数被调用时会调用对象的 HashCode 函数,并比对返回结果,如果结果不相同则直接添加,但如果结果相同的话则会调用元素对象的 equals 方法再次比对,如果equals 方法返回 false 则添加,否则不允许添加。会覆盖已有的元素。总结,HashSet 添加元素时如果元素的 hashCode 值相同并且 equals 返回 true 时,元素不会被正常添加。(重点)

    由此可知,第一个 “Homer” 与 “Marge” 虽然 hashCode 返回值相同,但重写的 equals 方法因为两者 name 值不同返回为 false,所以两者都正常添加。第二个出现的 “Homer” hashCode 与 name 值都相同,在添加时由于 hashCode 返回值相同且equals 方法返回 true 没有被正常添加。最后 overriddenHomer 对象虽然 name 值与 “Homer” 相同,但由于该对象再次重写了 HashCode 方法,HashCode 返回值与 name 为 “Homer” 的对象 HashCode 返回值不同,可以正常添加。至此可知 set 对象中只有三个元素被成功添加,第三项输出值应该是 3。

运行结果验证

大家可以自行在该网址运行题中代码查看结果

https://tool.lu/coderunner/

在这里插入图片描述

感谢热爱钻研的你看到这儿~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值