《互联网大厂 Java 面试:核心知识、JUC、JVM 等全方位考察》

37 阅读3分钟

互联网大厂 Java 面试:核心知识、JUC、JVM 等全方位考察

王铁牛怀揣着对互联网大厂的憧憬,坐在了面试房间里,对面是表情严肃的面试官,一场激烈的技术交锋即将开始。

第一轮提问 面试官:首先问几个 Java 核心知识的问题。Java 中基本数据类型有哪些? 王铁牛:这个我知道,有 byte、short、int、long、float、double、char、boolean。 面试官:回答正确,不错。那说说 Java 中面向对象的四大特性是什么? 王铁牛:是封装、继承、多态和抽象。 面试官:很好,基础很扎实。那在 Java 里,重载和重写的区别是什么? 王铁牛:重载是在一个类中,方法名相同但参数列表不同;重写是子类重写父类的方法,方法名、参数列表和返回值类型都一样。 面试官:非常棒,看来你对 Java 核心知识掌握得很牢固。

第二轮提问 面试官:接下来聊聊 JUC 和多线程相关的。什么是 JUC? 王铁牛:JUC 就是 java.util.concurrent 包,里面有很多处理并发的工具类。 面试官:回答得很准确。那创建线程有哪几种方式? 王铁牛:有继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池这几种方式。 面试官:不错。那说说线程的几种状态。 王铁牛:有新建、就绪、运行、阻塞和死亡这几种状态。 面试官:很好,对多线程这块了解得挺清楚。

第三轮提问 面试官:现在问一些关于框架和中间件的问题。Spring 的核心特性有哪些? 王铁牛:Spring 的核心特性有 IOC(控制反转)和 AOP(面向切面编程)。 面试官:回答正确。那 Spring Boot 和 Spring 有什么区别? 王铁牛:Spring Boot 是在 Spring 基础上简化配置的框架,它能快速搭建项目,自动配置很多东西。 面试官:不错。那 MyBatis 中 #{} 和 ${} 的区别是什么? 王铁牛:这个……嗯……好像一个是预编译,一个不是,但具体我有点说不清楚了。 面试官:这个是比较重要的点,希望你后续可以加强学习。还有 Dubbo 是做什么的? 王铁牛:Dubbo 好像是个分布式服务框架,但具体原理我不太了解。 面试官:看来你对框架的深入理解还需要加强。

面试接近尾声,面试官看着王铁牛说:“今天的面试就到这里了,你的基础知识掌握得还不错,对于一些简单的问题回答得很准确,这是值得肯定的。但是在一些复杂的知识点,比如 MyBatis 的细节和 Dubbo 的原理等方面,回答得不够清晰,还需要进一步提升。你先回家等通知吧,我们会综合评估后给你答复。”

答案详解

  1. Java 基本数据类型
    • byte:8 位,有符号,范围 -128 到 127。
    • short:16 位,有符号,范围 -32768 到 32767。
    • int:32 位,有符号,范围 -2147483648 到 2147483647。
    • long:64 位,有符号,范围 -9223372036854775808 到 9223372036854775807,定义时需在数字后面加 L。
    • float:32 位,单精度浮点数,定义时需在数字后面加 F。
    • double:64 位,双精度浮点数。
    • char:16 位,无符号,用于表示单个字符,用单引号括起来。
    • boolean:只有两个值 true 和 false。
  2. Java 面向对象的四大特性
    • 封装:将数据和操作数据的方法绑定在一起,隐藏对象的内部实现细节,只对外提供必要的接口。比如一个类中的私有属性,通过公共的 getter 和 setter 方法来访问和修改。
    • 继承:子类继承父类的属性和方法,并且可以扩展自己的属性和方法。通过 extends 关键字实现,提高了代码的复用性。
    • 多态:同一个行为具有多个不同表现形式或形态的能力。多态的实现方式有方法重载和方法重写,通过父类引用指向子类对象,在运行时根据实际对象类型调用相应的方法。
    • 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象类和接口是实现抽象的主要方式,抽象类中可以有抽象方法和非抽象方法,而接口中只能有抽象方法(Java 8 之后接口可以有默认方法和静态方法)。
  3. 重载和重写的区别
    • 重载:发生在同一个类中,方法名相同,但参数列表不同(参数的类型、个数、顺序不同),与返回值类型和访问修饰符无关。重载是编译时多态的体现,编译器根据调用方法时传递的参数来决定调用哪个重载方法。
    • 重写:发生在子类和父类之间,子类重写父类的方法,方法名、参数列表和返回值类型必须相同(返回值类型在 Java 5 之后可以是协变类型),访问修饰符不能比父类的更严格。重写是运行时多态的体现,在运行时根据实际对象的类型来调用相应的方法。
  4. JUC:java.util.concurrent 包是 Java 提供的用于处理并发编程的工具包,包含了很多用于多线程编程的类和接口,如线程池、锁机制、并发集合等,大大简化了 Java 并发编程的开发。
  5. 创建线程的方式
    • 继承 Thread 类:创建一个类继承 Thread 类,重写 run 方法,在 run 方法中定义线程要执行的任务,然后创建该类的对象并调用 start 方法启动线程。
    • 实现 Runnable 接口:创建一个类实现 Runnable 接口,实现 run 方法,然后将该类的对象作为参数传递给 Thread 类的构造函数,再调用 Thread 对象的 start 方法启动线程。
    • 实现 Callable 接口:创建一个类实现 Callable 接口,实现 call 方法,该方法有返回值。通过 FutureTask 类来包装 Callable 对象,然后将 FutureTask 对象作为参数传递给 Thread 类的构造函数,调用 start 方法启动线程,最后可以通过 FutureTask 的 get 方法获取线程执行的结果。
    • 使用线程池:通过 Executors 工具类创建不同类型的线程池,如 FixedThreadPool、CachedThreadPool 等,将实现了 Runnable 或 Callable 接口的任务提交给线程池执行。
  6. 线程的几种状态
    • 新建(New):线程对象被创建出来,但还没有调用 start 方法。
    • 就绪(Runnable):线程调用了 start 方法,进入可运行状态,等待获取 CPU 时间片。
    • 运行(Running):线程获取到 CPU 时间片,正在执行 run 方法中的代码。
    • 阻塞(Blocked):线程因为某些原因放弃 CPU 时间片,暂时停止执行。阻塞状态又可以分为等待阻塞(调用 wait 方法)、同步阻塞(获取同步锁失败)和其他阻塞(如调用 sleep、join 方法)。
    • 死亡(Terminated):线程执行完 run 方法中的代码,或者因为异常退出了 run 方法,线程生命周期结束。
  7. Spring 的核心特性
    • IOC(控制反转):也称为依赖注入(DI),是一种设计模式,将对象的创建和依赖关系的管理从代码中转移到 Spring 容器中。通过 Spring 容器来创建和管理对象,对象之间的依赖关系由容器来注入,降低了代码的耦合度。
    • AOP(面向切面编程):将与业务无关的通用功能(如日志记录、事务管理等)从业务逻辑中分离出来,形成独立的切面,在合适的时机将这些切面织入到业务逻辑中。AOP 可以提高代码的可维护性和复用性。
  8. Spring Boot 和 Spring 的区别
    • 配置方面:Spring 需要大量的 XML 配置文件或 Java 配置类来配置各种 Bean 和组件,配置过程繁琐。而 Spring Boot 采用了约定大于配置的原则,提供了自动配置功能,大部分情况下不需要手动进行复杂的配置,只需要引入相应的依赖,Spring Boot 就会自动完成配置。
    • 开发效率:Spring Boot 可以快速搭建项目,减少了开发人员的配置时间,提高了开发效率。它内置了嵌入式服务器(如 Tomcat、Jetty 等),可以直接运行项目,无需额外的服务器配置。
    • 微服务支持:Spring Boot 更适合用于构建微服务架构,它提供了一系列的 Starter 依赖,方便集成各种组件和中间件,如数据库、消息队列等。
  9. MyBatis 中 #{} 和 ${} 的区别
    • #{}:是预编译处理,MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为 ? 占位符,然后使用 PreparedStatement 进行预编译,再将参数值设置到占位符中。这样可以防止 SQL 注入攻击,提高安全性。
    • **:是字符串替换,MyBatis在处理{}**:是字符串替换,MyBatis 在处理 {} 时,会直接将 ${} 替换为参数的值。这种方式可能会导致 SQL 注入攻击,因为参数值会直接拼接到 SQL 语句中。通常用于动态表名、动态列名等情况。
  10. Dubbo:是阿里巴巴开源的分布式服务框架,用于解决分布式系统中服务之间的远程调用和服务治理问题。它提供了高性能的远程调用能力,支持多种协议(如 Dubbo 协议、HTTP 协议等)和负载均衡算法(如随机、轮询等),可以实现服务的注册与发现、服务监控、服务降级等功能,提高了分布式系统的可扩展性和可维护性。