《互联网大厂 Java 面试:核心知识、框架与中间件大考验》

71 阅读2分钟

互联网大厂 Java 面试:核心知识、框架与中间件大考验

王铁牛怀揣着对互联网大厂的向往,走进了面试的房间。严肃的面试官坐在对面,一场考验拉开了帷幕。

第一轮提问 面试官:首先问几个 Java 核心知识的问题。Java 中基本数据类型有哪些? 王铁牛:这个我知道,Java 基本数据类型有 byte、short、int、long、float、double、char、boolean。 面试官:回答得不错。那说说面向对象的四大特性是什么? 王铁牛:是封装、继承、多态和抽象。 面试官:很好。再问下,Java 中异常处理机制是怎样的? 王铁牛:Java 异常分为检查性异常和非检查性异常,通过 try、catch、finally 语句块来处理异常,还可以用 throw 和 throws 抛出异常。 面试官:非常棒,基础很扎实。

第二轮提问 面试官:接下来聊聊 JUC、JVM 和多线程相关的。JUC 包下有哪些常用的类和工具? 王铁牛:嗯……有 CountDownLatch、CyclicBarrier 这些吧。 面试官:对的。那 JVM 的内存模型是怎样的? 王铁牛:这个……好像有堆、栈、方法区啥的,具体我有点说不太清。 面试官:没关系,再问一个多线程的问题。创建线程有几种方式? 王铁牛:有继承 Thread 类、实现 Runnable 接口、实现 Callable 接口这几种。 面试官:回答得还行,不过 JVM 那块还需要加强。

第三轮提问 面试官:现在来谈谈一些框架和中间件。Spring 的核心特性有哪些? 王铁牛:有 IoC 和 AOP。 面试官:不错。那 Spring Boot 是如何简化 Spring 开发的? 王铁牛:就是有自动配置啥的,具体我也不是特别明白。 面试官:好吧。MyBatis 中 #{} 和 ${} 的区别是什么? 王铁牛:这个……我记得一个是预编译,一个不是,但具体不太能说清楚。 面试官:看来在框架这块的理解还不够深入。你先回家等通知吧,后续如果有消息会及时联系你。

问题答案

  1. Java 中基本数据类型有哪些? Java 的基本数据类型分为四类八种:
    • 整数类型:byte(1 字节)、short(2 字节)、int(4 字节)、long(8 字节)。
    • 浮点类型:float(4 字节)、double(8 字节)。
    • 字符类型:char(2 字节)。
    • 布尔类型:boolean(理论上 1 位,实际实现可能不同)。
  2. 面向对象的四大特性是什么?
    • 封装:将数据和操作数据的方法绑定在一起,隐藏对象的内部实现细节,只对外提供必要的接口,提高了代码的安全性和可维护性。
    • 继承:子类继承父类的属性和方法,使得子类可以复用父类的代码,同时可以添加自己的特性,实现代码的复用和扩展。
    • 多态:同一操作作用于不同的对象,可以有不同的表现形式。多态通过继承、接口实现和方法重写来实现,提高了代码的灵活性和可扩展性。
    • 抽象:抽象是将一类对象的共同特征总结出来,形成抽象类或接口。抽象类和接口不能实例化,需要具体的子类来实现,有助于提高代码的可维护性和可扩展性。
  3. Java 中异常处理机制是怎样的? Java 的异常处理机制主要通过 try、catch、finally、throw 和 throws 关键字来实现。
    • try 块:用于包含可能抛出异常的代码。
    • catch 块:用于捕获并处理 try 块中抛出的异常。可以有多个 catch 块,根据异常类型进行匹配。
    • finally 块:无论 try 块中是否抛出异常,finally 块中的代码都会执行,通常用于释放资源。
    • throw:用于手动抛出一个异常对象。
    • throws:用于在方法声明中声明该方法可能抛出的异常,调用该方法的代码需要处理这些异常。
  4. JUC 包下有哪些常用的类和工具?
    • CountDownLatch:一个同步辅助类,允许一个或多个线程等待其他线程完成操作。通过一个计数器来实现,计数器的初始值为线程的数量,当一个线程完成任务后,计数器减 1,当计数器为 0 时,等待的线程可以继续执行。
    • CyclicBarrier:一个同步辅助类,允许一组线程相互等待,直到所有线程都到达一个公共屏障点。可以重复使用,当所有线程都到达屏障点后,屏障会打开,线程可以继续执行,同时可以重置屏障。
    • Semaphore:一个计数信号量,用于控制同时访问某个资源的线程数量。通过一个许可集来实现,线程在访问资源前需要获取许可,访问完后释放许可。
    • ExecutorService:一个线程池接口,用于管理线程的创建、执行和销毁。常见的实现类有 ThreadPoolExecutor、ScheduledThreadPoolExecutor 等。
  5. JVM 的内存模型是怎样的? JVM 的内存模型主要分为以下几个区域:
    • 堆(Heap):是 JVM 中最大的一块内存区域,用于存储对象实例和数组。所有通过 new 创建的对象都存放在堆中,堆是线程共享的,垃圾回收主要针对堆进行。
    • 栈(Stack):分为虚拟机栈和本地方法栈。虚拟机栈用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每个线程都有自己独立的虚拟机栈。本地方法栈用于执行本地方法(使用 native 关键字修饰的方法)。
    • 方法区(Method Area):用于存储类的元数据信息,如类的结构、常量池、静态变量等。方法区也是线程共享的,在 JDK 1.8 及以后,方法区被元空间(Metaspace)取代。
    • 程序计数器(Program Counter Register):是一块较小的内存区域,用于记录当前线程执行的字节码指令的地址。每个线程都有自己独立的程序计数器。
  6. 创建线程有几种方式?
    • 继承 Thread 类:创建一个类继承自 Thread 类,重写 run 方法,在 run 方法中定义线程要执行的任务。然后创建该类的实例,调用 start 方法启动线程。
    • 实现 Runnable 接口:创建一个类实现 Runnable 接口,实现 run 方法。然后创建该类的实例,将其作为参数传递给 Thread 类的构造函数,再调用 Thread 实例的 start 方法启动线程。
    • 实现 Callable 接口:创建一个类实现 Callable 接口,实现 call 方法,call 方法可以有返回值。然后使用 FutureTask 类包装 Callable 实例,再将 FutureTask 实例作为参数传递给 Thread 类的构造函数,调用 start 方法启动线程,最后可以通过 FutureTask 的 get 方法获取线程的返回值。
  7. Spring 的核心特性有哪些?
    • IoC(Inversion of Control,控制反转):将对象的创建和依赖关系的管理交给 Spring 容器,而不是由对象自己来创建和管理。通过依赖注入(Dependency Injection,DI)的方式,将依赖对象注入到需要的对象中,降低了对象之间的耦合度。
    • AOP(Aspect-Oriented Programming,面向切面编程):允许开发者在不修改原有代码的情况下,对程序的某些功能进行增强。通过定义切面(Aspect)、切点(Pointcut)和通知(Advice),可以在程序的特定执行点插入额外的逻辑,如日志记录、事务管理等。
  8. Spring Boot 是如何简化 Spring 开发的?
    • 自动配置:Spring Boot 根据项目中引入的依赖,自动为应用程序进行配置,减少了开发者手动配置的工作量。例如,当引入 Spring Data JPA 依赖时,Spring Boot 会自动配置数据源、JPA 实体管理器等。
    • 起步依赖:Spring Boot 提供了一系列的起步依赖,这些依赖将常用的依赖组合在一起,开发者只需要引入相应的起步依赖,就可以快速搭建项目。例如,spring-boot-starter-web 依赖包含了 Spring MVC、Tomcat 等开发 Web 应用所需的依赖。
    • 嵌入式服务器:Spring Boot 内置了 Tomcat、Jetty 等嵌入式服务器,开发者可以直接将应用打包成可执行的 JAR 文件,通过 java -jar 命令启动应用,无需手动部署到服务器上。
    • 配置简单:Spring Boot 使用 application.properties 或 application.yml 文件进行配置,配置项简洁明了,避免了繁琐的 XML 配置。
  9. MyBatis 中 #{} 和 ${} 的区别是什么?
    • #{}:是预编译处理,MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为占位符?,然后使用 PreparedStatement 进行预编译,再将参数设置到占位符中。这样可以防止 SQL 注入攻击,提高了 SQL 的安全性。
    • :是字符串替换,MyBatis在处理{}:是字符串替换,MyBatis 在处理 {} 时,会直接将 替换为参数的值,相当于直接拼接SQL语句。因此,使用{} 替换为参数的值,相当于直接拼接 SQL 语句。因此,使用 {} 可能会导致 SQL 注入攻击,一般用于动态表名、动态列名等场景。