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

37 阅读4分钟

面试官:请简要介绍一下Java核心知识中的面向对象三大特性。

王铁牛:这个我知道,封装、继承、多态嘛。

面试官:不错,回答正确。那在多线程场景下,如何确保线程安全?

王铁牛:可以用synchronized关键字,或者用Lock接口。

面试官:嗯,基本思路是对的。再问一个,说说JVM的内存结构。

王铁牛:有堆、栈、方法区这些。

第一轮结束。

面试官:接下来问几个关于JUC的问题。CountDownLatch的作用是什么?

王铁牛:它可以让一个线程等待其他线程完成操作。

面试官:那CyclicBarrier呢?

王铁牛:这个……好像是让一组线程互相等待,直到都到达某个点。

面试官:最后一个,Semaphore有什么用?

王铁牛:不太清楚,感觉像是信号量之类的吧。

第二轮结束。

面试官:说说HashMap的底层实现原理。

王铁牛:它是数组加链表,后来又有了红黑树。

面试官:那ArrayList的扩容机制呢?

王铁牛:好像是每次扩容1.5倍。

面试官:Spring框架中,依赖注入有几种方式?

王铁牛:接口注入、构造器注入、setter方法注入。

第三轮结束。

面试结束,面试官表示会让王铁牛回家等通知。

答案:

  • 面向对象三大特性:
    • 封装:将数据和操作数据的方法封装在一起,对外提供统一的接口,隐藏内部实现细节,提高数据的安全性和程序的可维护性。
    • 继承:子类继承父类的属性和方法,实现代码复用,提高开发效率。
    • 多态:同一个行为具有多个不同表现形式或形态的能力。包括编译时多态(方法重载)和运行时多态(方法重写)。
  • 多线程确保线程安全:
    • synchronized关键字:可以修饰方法或代码块,保证同一时刻只能有一个线程访问被修饰的部分,从而实现线程同步。
    • Lock接口:提供了比synchronized更灵活的锁控制,如可中断锁、定时锁等。通过Lock对象的lock()和unlock()方法来控制锁的获取和释放。
  • JVM内存结构:
    • 堆:是Java对象实例存储的地方,也是垃圾回收主要进行的区域。
    • 栈:存储局部变量、方法调用等信息。
    • 方法区:存储类信息、常量、静态变量等。
  • CountDownLatch作用:
    • 用于某个线程等待其他一组线程完成各自的工作之后再执行。通过构造函数传入需要等待的线程数量,调用countDown()方法来减少计数,当计数为0时,等待的线程被唤醒继续执行。
  • CyclicBarrier作用:
    • 让一组线程互相等待,直到所有线程都到达某个屏障点。它可以循环使用,当所有线程到达屏障点后,会执行预先设定的任务,然后屏障被重置,线程可以再次等待。
  • Semaphore作用:
    • 信号量,用于控制对共享资源的访问数量。通过构造函数指定许可数量,线程调用acquire()方法获取许可,调用release()方法释放许可。
  • HashMap底层实现原理:
    • 初始是一个数组,当有新元素插入时,通过计算key的哈希值,找到对应的数组下标位置。
    • 如果该位置为空,则直接插入新元素。
    • 如果不为空,则会形成链表或红黑树结构(当链表长度达到一定阈值时会转换为红黑树),新元素会插入到链表或红黑树的尾部。
  • ArrayList扩容机制:
    • 当向ArrayList中添加元素时,如果当前容量不足,会进行扩容。
    • 扩容时,新容量是原容量的1.5倍(如果原容量小于10,则新容量为10)。
    • 然后会创建一个新的更大的数组,将原数组中的元素复制到新数组中,再将新元素添加到新数组。
  • Spring框架依赖注入方式:
    • 接口注入:通过实现特定接口来进行依赖注入,不太常用。
    • 构造器注入:在类的构造函数中通过参数传入依赖对象,确保对象在创建时就完成依赖注入,保证对象的完整性。
    • setter方法注入:通过类的setter方法来设置依赖对象,灵活性较高,可以在对象创建后再进行依赖注入。