为了账号安全,请及时绑定邮箱和手机立即绑定

进百度公司10道Java面试题虐哭小李,面试直接泡汤(上集)

第六题,当在 HashMap 中放入一个已经存在的 key 时,会发生什么?

小李之所以没答对这道题,是因为他没有深入研究过 HashMap 的工作原理。

Hash,一般译作“散列”,也有直接音译为“哈希”的,这玩意什么意思呢?就是把任意长度的数据通过一种算法映射到固定长度的域上(散列值)。

再直观一点,就是对一串数据 wang 进行杂糅,输出另外一段固定长度的数据 er——作为数据 wang 的特征。我们通常用一串指纹来映射某一个人,别小瞧手指头那么大点的指纹,在你所处的范围内很难找出第二个和你相同的(人的散列算法也好厉害,有没有)。

对于任意两个不同的数据块,其散列值相同的可能性极小,也就是说,对于一个给定的数据块,找到和它散列值相同的数据块极为困难。再者,对于一个数据块,哪怕只改动它的一个比特位,其散列值的改动也会非常的大——这正是 Hash 存在的价值!

大家应该知道,HashMap 的底层数据结构是一个数组,通过 hash() 方法来确定下标。

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

当我们放入一个键值对的时候,会先调用 hash() 方法对 key 进行哈希算法,如果 key 是相同的,那么哈希后的结果也是相同的,意味着数组中的下标是相同的,新放入的值就会覆盖原来的值。

第七题,下面这段代码将会打印出什么?

public class Test {
    public static void main(String[] args) {
        char[] chars = new char[]{'\u0097'};
        String str = new String(chars);
        byte[] bytes = str.getBytes();
        System.out.println(Arrays.toString(bytes));
    }
}

小李之所以没答对这道题,是因为他没有深入研究过字符编码方面的一些知识。

在这段程序中,我们通过一个字符数组创建了一个字符串对象,然后调用 String 类的 getByte() 方法得到字节数组并将其打印到控制台。

这道面试题考察的核心并不是最终的打印结果(结果是不确定的),而是字符编码。通常情况下,我们在调用 getBytes() 方法时,要指定编码,比如说 str.getBytes(StandardCharsets.UTF_8)

当我们没有指定编码的时候,JDK 会调用平台默认的字符编码,而不同的操作系统,编码不尽相同的,bytes 的结果也就会不同。

当使用 UTF_8 时,结果为 -62, -105,当使用 GB2312 时,结果为 63

第八题,当方法在父类中抛出 NullPointerException 时,是否可以使用抛出 RuntimeException 的方法来重写它?

小李之所以没答对这道题,是因为他被重写(overriding)和重载(overloading)的概念搞混了。

方法重写和方法重载时,方法名可以完全相同,但根本的不同在于方法重写时发生在运行时,方法重载时发生在编译时。

另外,方法重写和方法重载时的规则也不尽相同。在 Java 中,不能重写 private、static 和 final 方法,但可以重载它们。

我们来重点看一下方法重写时的规则:

1)方法签名必须相同,包括返回类型、参数的数量、参数的类型和参数的顺序。

2)重写后的方法不能抛出比父类中更高级别的异常。举例来说,如果父类中的方法抛出的是 IOException,那么子类中重写的方法不能抛出 Exception,可以是 IOException 的子类或者不抛出任何异常。这条规则只适用于可检查的异常。

可检查(checked)异常必须在源代码中显式地进行捕获处理,不检查(unchecked)异常就是所谓的运行时异常,比如说 NullPointerException、ArrayIndexOutOfBoundsException 之类的,不会在编译器强制要求。

3)重写后的方法访问权限不能比父类中的方法低,比如说父类中的方法是 public,重写后的方法就不能是 protected。

public class ExceptionDemo {
    public static void main(String[] args) {
        Super s = new Child();
        s.write();
    }
}
class Super{
    public void write() throws NullPointerException { }
}

class Child extends Super {
    @Override
    public void write() throws RuntimeException { }
}

RuntimeException 和 NullPointerException 属于不检查异常,所以本题的答案是可以的。如果是可检查异常的话,IDE 就会发出警告。

https://img2.sycdn.imooc.com/5ffbaad50001db8610800294.jpg

第九题,下面这段代码使用了 compareTo() 方法,有问题吗?

class Employee implements Comparable {
    private int id;

    @Override
    public int compareTo(Object o) {
        Employee emp = (Employee) o;
        return this.id - emp.id;
    }
}

小李之所以没答对这道题,是因为他想当然地认为 id 的都是正整数。

当我们需要按照一定的规则进行排序的时候,通常要实现 Comparable 接口,并实现 compareTo 方法,规则如下:

1)如果当前对象小于另外一个对象,则 compareTo 方法必须返回负数;如果当前对象大于另外一个对象,则必须返回正数;如果两个对象相等,则返回零。

2)通常来说,compareTo 方法必须和 equals 方法一致,如果两个对象通过 equals 方法判断的结果为 true,那么 compareTo 必须返回零。

不过,JDK 中有一个反例,就是 BigDecimal。

BigDecimal bd1 = new BigDecimal("2.0");
BigDecimal bd2 = new BigDecimal("2.00");

System.out.println("equals: " + bd1.equals(bd2));
System.out.println("compareTo: " + bd1.compareTo(bd2));

输出结果如下所示:

equals: false
compareTo: 0

这是因为 JDK 认为 2.0 和 2.00 的精度不一样,所以不能 equals,但值确实是相等的。

3)不能使用减法来比较整数值,因为减法的结果可能溢出。应该使用 Integer.compareTo() 来进行比较。如果你想通过减法操作来提高性能,必须得确保两个操作数是正整数,或者确保两者相差的值小于 Integer.MAX_VALUE。

public class CompareDemo {
    public static void main(String[] args) {
        List<Employee> list = new ArrayList<>();
        list.add(new Employee(1));
        list.add(new Employee(Integer.MIN_VALUE));
        list.add(new Employee(Integer.MAX_VALUE));
        Collections.sort(list);
        System.out.println(list);
    }
}

class Employee implements Comparable {
    private int id;

    public Employee(int id) {
        this.id = id;
    }

    @Override
    public int compareTo(Object o) {
        Employee emp = (Employee) o;
        return this.id - emp.id;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                '}';
    }
}

程序的输出结果如下所示:

[Employee{id=1}, Employee{id=2147483647}, Employee{id=-2147483648}]

排序就乱了。因为 Integer.MIN_VALUE - 1 变成了正数 2147483647

第十题,StringBuffer 和 StringBuilder 之间有什么区别?

小李之所以没答对这道题,是因为他觉得这道题太简单了,结果说反了,大意了啊。

StringBuilder 是 JDK 1.5 之后引入的,它和 StringBuffer 最大的区别就在于它的一系列方法都是非同步的。

https://img1.sycdn.imooc.com/5ffbaad50001fb6410600532.jpg

总结:

好了,以上就是小李在百度面试遇到的 10 道虐心的面试题,本来最后一道是送分题,结果大意说反了,让小李更加懊恼。年后是跳槽的高峰期,有打算的小伙伴要提前准备了,希望大家都能够顺利面上心仪的岗位



点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消