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

53 阅读6分钟

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

王铁牛:嗯,面向对象的三大特性就是封装、继承和多态。封装就是把数据和操作数据的方法封装在一起;继承就是子类继承父类的属性和方法;多态就是同一个行为具有多个不同表现形式。

面试官:回答得不错。那在多线程中,如何确保线程安全?

王铁牛:可以用synchronized关键字,还有Lock接口。对共享资源进行加锁,这样同一时间就只有一个线程能访问啦。

面试官:很好。再问个关于JUC的问题,CountDownLatch的作用是什么?

王铁牛:这个嘛……它可以让一个线程等待其他多个线程完成任务后再执行。

第一轮结束。

面试官:说说JVM中类加载的过程。

王铁牛:类加载就是把类的字节码文件加载到内存,然后经过验证、准备、解析、初始化等步骤。

面试官:那在JVM中,内存区域是怎么划分的?

王铁牛:有堆、栈、方法区、程序计数器这些。堆里存对象,栈里存局部变量,方法区存类信息。

面试官:谈谈Spring中依赖注入的方式。

王铁牛:有构造器注入、setter方法注入,还有基于注解的注入。

第二轮结束。

面试官:讲讲MyBatis中#{}和${}的区别。

王铁牛:#{}是预编译处理,能防止SQL注入;${}是字符串替换,可能会有SQL注入风险。

面试官:Dubbo的集群容错策略有哪些?

王铁牛:这个……好像有几种,但是我一下子想不起来了。

面试官:说说RabbitMq中消息确认机制。

王铁牛:不太清楚,大概就是确认消息有没有被正确接收吧。

第三轮结束。

面试结束,面试官表示会让王铁牛回家等通知。整体来看,王铁牛对于一些基础简单的问题回答得还不错,展现了一定的知识储备。但对于较复杂的问题,回答得不是很清晰准确,对一些知识点的理解还不够深入全面。希望他回去能再好好巩固一下相关知识,提升自己的技术水平,以便更好地应对后续的面试。

答案:

  • 面向对象三大特性:
    • 封装:将数据和操作数据的方法封装在一起,对外提供统一的接口,隐藏内部实现细节,提高数据的安全性和程序的可维护性。例如一个类中的成员变量可以用private修饰,通过public的方法来访问和修改。
    • 继承:子类继承父类的属性和方法,实现代码复用。子类可以扩展父类的功能。比如一个父类定义了一些通用的方法,子类继承后可以根据自身需求重写或扩展这些方法。
    • 多态:同一个行为具有多个不同表现形式。分为编译时多态(方法重载)和运行时多态(方法重写)。运行时多态通过父类引用指向子类对象,调用方法时会根据实际对象类型来决定调用哪个类的重写方法。
  • 多线程确保线程安全:
    • synchronized关键字:可以修饰代码块或方法,保证同一时刻只有一个线程能访问被修饰的代码或方法。例如修饰一个方法,当一个线程进入该方法时,会自动获取对象的锁,其他线程需要等待该锁释放才能进入。
    • Lock接口:提供了比synchronized更灵活的锁控制。如ReentrantLock,它可以实现公平锁,可中断锁等特性。通过lock()方法获取锁,unlock()方法释放锁。
  • CountDownLatch作用:用于让一个线程等待其他多个线程完成任务后再执行。比如有一个主线程需要等待多个子线程都完成数据处理后,再进行汇总操作。可以创建一个CountDownLatch对象,在子线程完成任务时调用countDown()方法,主线程调用await()方法等待,直到计数器变为0。
  • JVM类加载过程:
    • 加载:将类的字节码文件从硬盘读取到内存中,创建一个Class对象。
    • 验证:检查字节码文件的格式、语义等是否正确,确保不会危害虚拟机安全。
    • 准备:为类的静态变量分配内存,并设置默认初始值。
    • 解析:将常量池中的符号引用替换为直接引用。
    • 初始化:执行类的静态代码块,为静态变量赋予正确的初始值。
  • JVM内存区域划分:
    • 堆:是Java程序运行时最大的内存区域,用于存储对象实例。所有对象都在堆中分配内存。
    • 栈:每个线程都有自己的栈,用于存储局部变量、方法调用等。栈中的数据随着方法的执行和结束而进出。
    • 方法区:存储类信息、常量、静态变量等。被所有线程共享。
    • 程序计数器:记录当前线程执行的字节码指令地址,是线程私有的。
  • Spring依赖注入方式:
    • 构造器注入:通过构造函数传入依赖对象,在创建对象时就完成依赖注入。优点是注入的依赖不可为空,缺点是当依赖较多时,构造函数参数列表会很长。
    • setter方法注入:通过setter方法设置依赖对象。优点是可以在对象创建后再注入依赖,缺点是可能导致对象在注入前处于部分初始化状态。
    • 基于注解的注入:如@Autowired注解,可以自动根据类型进行依赖注入。使用方便,但需要配置扫描注解的包。
  • MyBatis中#{}和${}的区别:
    • #{}:是预编译处理,会将传入的值作为参数处理,能防止SQL注入。例如在SQL语句中使用#{},MyBatis会将其替换为?,然后通过PreparedStatement设置参数值。
    • ${}:是字符串替换,直接将传入的值拼接到SQL语句中。如果传入的值包含恶意SQL语句,可能会导致SQL注入。一般用于表名、列名等不涉及用户输入的部分。
  • Dubbo集群容错策略:
    • Failover Cluster:失败自动切换,当调用失败时,自动切换到其他服务器重试。
    • Failfast Cluster:快速失败,只调用一次,失败立即报错。
    • Failsafe Cluster:失败安全,调用失败时,直接忽略,不抛出异常。
    • Failback Cluster:失败自动恢复,失败后会在后台定时重试。
    • Forking Cluster:并行调用多个服务器,只要一个成功就返回。
  • RabbitMq消息确认机制:
    • 生产者确认机制:确保生产者发送的消息被正确发送到RabbitMq服务器。分为事务模式和Confirm模式。事务模式通过txSelect()开启事务,txCommit()提交事务,txRollback()回滚事务。Confirm模式通过调用channel的confirmSelect()方法开启,消息发送后通过confirmListener监听发送结果。
    • 消费者确认机制:消费者接收消息后,向RabbitMq发送确认消息,告知服务器该消息已被正确处理。有自动确认和手动确认两种方式。自动确认是消费者接收到消息后,RabbitMq自动认为消息已被处理。手动确认需要消费者在处理完消息后,调用channel的basicAck方法进行确认。