《互联网大厂Java求职者面试:核心知识大考验》

36 阅读5分钟

面试官:第一轮面试开始,先问你几个Java核心知识的问题。在Java中,什么是多态?它有什么作用?

王铁牛:多态就是同一个行为具有多个不同表现形式或形态。作用嘛,能提高程序的可扩展性和可维护性,比如不同的子类对象可以统一用父类类型来引用和操作。

面试官:回答得不错。那再问你,String类为什么是不可变的?

王铁牛:因为String类内部用final修饰了字符数组,一旦初始化就不能再修改。

面试官:很好。最后一个问题,简述一下Java中的异常处理机制。

王铁牛:就是try、catch、finally那一套,try块放可能出现异常的代码,catch捕获异常,finally不管怎样都会执行。

面试官:第一轮表现不错,接下来第二轮,关于JUC和多线程的。在JUC中,CountDownLatch的作用是什么?

王铁牛:它可以让一个或多个线程等待其他线程完成一组操作后再继续执行。

面试官:那如何使用线程池来实现定时任务?

王铁牛:可以用ScheduledThreadPoolExecutor,设置好初始线程数、最大线程数和定时任务的执行周期啥的。

面试官:线程池有哪几种拒绝策略?

王铁牛:哎呀,这个嘛,好像有什么AbortPolicy、CallerRunsPolicy之类的,具体不太清楚。

面试官:第二轮就到这里,现在进入第三轮,关于JVM、HashMap、ArrayList这些。JVM的内存模型分为哪几个区域?

王铁牛:有堆、栈、方法区、程序计数器、本地方法栈。

面试官:HashMap的底层数据结构是什么?

王铁牛:是数组加链表,后来链表长度超过8还会转成红黑树。

面试官:ArrayList是如何实现动态扩容的?

王铁牛:不太清楚,感觉就是自动增加容量吧。

面试官:今天的面试就到这里,回去等通知吧。

答案:

  1. 多态:同一个行为具有多个不同表现形式或形态。作用是提高程序的可扩展性和可维护性,不同的子类对象可以统一用父类类型来引用和操作。比如定义一个父类Animal,子类Dog和Cat都继承自Animal,在操作时可以用Animal类型来引用Dog和Cat对象,调用它们各自重写的方法。
  2. String类不可变:因为String类内部用final修饰了字符数组,一旦初始化就不能再修改。当对String对象进行修改操作时,实际上是创建了一个新的String对象,原对象不会改变。例如 String s = "abc"; s = s + "d"; 这里s原来指向的"abc"对象不会变,而是创建了一个新的"abcd"对象,s指向了新对象。
  3. Java异常处理机制:try块放可能出现异常的代码,catch捕获异常,finally不管怎样都会执行。try块中的代码如果出现异常,就会跳转到对应的catch块中处理,如果没有匹配的catch块,异常会继续向上抛。finally块通常用于资源清理等操作,无论try块是否有异常都会执行。比如在操作文件时,在try块中打开文件,catch块中处理文件操作异常,finally块中关闭文件。
  4. CountDownLatch作用:可以让一个或多个线程等待其他线程完成一组操作后再继续执行。例如有一个主线程需要等待多个子线程完成各自的任务后再进行汇总操作,就可以使用CountDownLatch。子线程完成任务后调用CountDownLatch的countDown方法,主线程调用await方法等待,直到CountDownLatch的值为0,主线程才继续执行。
  5. 使用线程池实现定时任务:可以用ScheduledThreadPoolExecutor。示例代码:ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2); executor.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("定时任务执行"); } }, 0, 1, TimeUnit.MINUTES); 这里设置了初始线程数为2,每1分钟执行一次定时任务。
  6. 线程池拒绝策略
    • AbortPolicy:默认策略,当线程池无法执行新任务时,抛出RejectedExecutionException异常。
    • CallerRunsPolicy:当线程池无法执行新任务时,由调用线程(即提交任务的线程)直接执行该任务。
    • DiscardPolicy:当线程池无法执行新任务时,直接丢弃该任务,不抛出异常。
    • DiscardOldestPolicy:当线程池无法执行新任务时,丢弃队列中最老的任务,然后尝试重新执行新任务。
  7. JVM内存模型区域
    • :存放对象实例,是垃圾回收的主要区域。
    • :存储局部变量、方法调用等信息。
    • 方法区:存储类信息、常量、静态变量等。
    • 程序计数器:记录当前线程执行的字节码指令地址。
    • 本地方法栈:为本地方法服务。
  8. HashMap底层数据结构:是数组加链表,后来链表长度超过8还会转成红黑树。当向HashMap中put元素时,首先根据key的hash值计算出在数组中的位置,如果该位置为空,则直接插入新节点;如果不为空,则判断key是否相同,相同则覆盖value,不同则将新节点插入链表尾部,当链表长度超过8时,链表会转成红黑树以提高查询效率。
  9. ArrayList动态扩容:ArrayList内部维护了一个数组,当添加元素导致数组容量不足时,会创建一个新的更大的数组,将原数组的元素复制到新数组中,然后再添加新元素。每次扩容时,新数组的容量是原数组容量的1.5倍。例如初始容量为10的ArrayList,当添加到第11个元素时,会创建一个容量为15的新数组,将原来的10个元素复制过去,再添加新元素。