《互联网大厂面试:Java核心、JUC、JVM等技术深度大考验》

42 阅读7分钟

互联网大厂面试:Java核心、JUC、JVM等技术深度大考验

严肃的面试官坐在办公桌后,面前放着王铁牛的简历。王铁牛紧张地坐在对面,双手不自觉地攥着衣角。

第一轮面试开始 面试官:“首先问你几个关于Java核心知识的问题。Java中基本数据类型有哪些?” 王铁牛:“这个我知道,有byte、short、int、long、float、double、char、boolean。” 面试官:“回答得不错。那Java的访问修饰符有几种,分别有什么作用?” 王铁牛:“有四种,public可以被所有类访问;protected可以被同一个包内的类以及不同包的子类访问;默认(不写修饰符)只能被同一个包内的类访问;private只能在本类中访问。” 面试官:“很好,看来基础掌握得挺扎实。那在Java里,方法重载和方法重写的区别是什么?” 王铁牛:“方法重载是在同一个类中,方法名相同但参数列表不同;方法重写是在子类中重写父类的方法,方法名、参数列表和返回值类型都要相同。” 面试官:“非常棒,这几个基础问题回答得很准确。”

第二轮面试开始 面试官:“接下来我们聊聊JUC和多线程。什么是线程安全?” 王铁牛:“线程安全就是在多线程环境下,对共享资源的访问不会出现数据不一致等问题。” 面试官:“那JUC里的ReentrantLock和synchronized有什么区别?” 王铁牛:“嗯……好像ReentrantLock更灵活,但是具体的我有点说不清楚了。” 面试官:“那在多线程环境下,如何保证数据的原子性?” 王铁牛:“我记得可以用原子类,但是具体怎么用不太清楚。” 面试官:“你前面那个线程安全回答得还行,但是后面两个问题回答得不太清晰,需要加强这方面的学习。”

第三轮面试开始 面试官:“现在来谈谈Spring和Spring Boot。Spring的核心特性有哪些?” 王铁牛:“有依赖注入和面向切面编程。” 面试官:“那Spring Boot的自动配置原理是什么?” 王铁牛:“这个……我好像听说过,但是不太能说清楚。” 面试官:“MyBatis的动态SQL有什么作用,常用的动态SQL标签有哪些?” 王铁牛:“动态SQL应该是可以根据不同条件生成不同的SQL语句,标签的话我就只记得if标签了。” 面试官:“整体来看,你对一些基础概念有一定了解,但是对于一些深入的知识点掌握得不够扎实。像JUC、Spring Boot这些内容,还需要进一步学习。回去之后可以多看看相关的资料,提升自己的技术水平。你先回家等通知吧,后续如果有消息我们会及时联系你。”

答案详解

  1. Java基本数据类型
    • byte:8位,有符号,用于表示较小的整数,取值范围是 -128 到 127。
    • short:16位,有符号,取值范围是 -32768 到 32767。
    • int:32位,有符号,是最常用的整数类型,取值范围是 -2147483648 到 2147483647。
    • long:64位,有符号,用于表示较大的整数,取值范围非常大。定义时需要在数字后面加“L”。
    • float:32位,单精度浮点数,用于表示小数,定义时需要在数字后面加“F”。
    • double:64位,双精度浮点数,比float精度更高,是默认的浮点类型。
    • char:16位,无符号,用于表示单个字符,使用单引号括起来。
    • boolean:只有两个值,true和false,用于逻辑判断。
  2. Java访问修饰符
    • public:被public修饰的类、方法、变量可以被任何类访问,没有访问权限限制。
    • protected:同一个包内的类可以直接访问,不同包的子类也可以访问。
    • 默认(不写修饰符):只能被同一个包内的类访问,不同包的类无法访问。
    • private:只能在定义它的类内部访问,其他类无法直接访问。
  3. 方法重载和方法重写
    • 方法重载:在同一个类中,方法名相同但参数列表不同(参数的个数、类型或顺序不同)。方法的返回值类型和访问修饰符可以不同。编译器根据调用方法时传入的参数来决定调用哪个重载方法。
    • 方法重写:发生在子类和父类之间,子类重写父类的方法。方法名、参数列表和返回值类型必须相同(Java 5 及以后版本中,返回值类型可以是父类方法返回值类型的子类,称为协变返回类型)。重写的方法不能降低父类方法的访问权限,抛出的异常范围不能比父类方法更广。
  4. 线程安全:在多线程环境下,当多个线程同时访问共享资源时,如果不采取任何同步措施,可能会导致数据不一致、脏读等问题。线程安全的代码能够保证在多线程环境下对共享资源的访问是正确的,不会出现上述问题。例如,一个计数器类,如果多个线程同时对其进行自增操作,没有同步机制就会出现计数错误,而线程安全的计数器会通过加锁等方式保证操作的正确性。
  5. ReentrantLock和synchronized的区别
    • 语法层面:synchronized是Java的关键字,是内置的语言特性,使用起来比较简单,通过修饰方法或代码块来实现同步。ReentrantLock是一个类,需要手动创建对象并调用lock()和unlock()方法来加锁和解锁。
    • 锁的获取和释放:synchronized在代码执行完或出现异常时会自动释放锁。ReentrantLock需要在finally块中手动调用unlock()方法释放锁,否则可能会导致死锁。
    • 锁的特性:ReentrantLock更加灵活,支持可重入、公平锁、可中断锁等特性。synchronized只支持可重入,默认是非公平锁。
  6. 多线程环境下保证数据原子性
    • 使用原子类:Java的java.util.concurrent.atomic包提供了一系列原子类,如AtomicInteger、AtomicLong等。这些类使用了CAS(Compare-And-Swap)算法,通过硬件层面的支持来保证操作的原子性。例如,AtomicInteger的incrementAndGet()方法可以原子地将值加1。
    • 使用锁:可以使用synchronized或ReentrantLock来保证在同一时间只有一个线程可以访问共享资源,从而保证操作的原子性。
  7. Spring的核心特性
    • 依赖注入(DI):将对象之间的依赖关系通过外部容器来管理,而不是在对象内部直接创建依赖对象。这样可以降低代码的耦合度,提高代码的可维护性和可测试性。例如,一个Service类依赖一个Dao类,通过Spring容器将Dao对象注入到Service类中。
    • 面向切面编程(AOP):允许在不修改原有业务逻辑的基础上,对程序进行增强。例如,在方法执行前后添加日志记录、事务管理等功能。AOP通过代理模式实现,将切面逻辑(如日志记录)织入到目标对象的方法中。
  8. Spring Boot的自动配置原理:Spring Boot的自动配置是基于条件注解实现的。当项目中引入了某个依赖时,Spring Boot会根据类路径下的类和配置文件,自动配置相关的Bean。Spring Boot有一个自动配置类库,这些自动配置类上使用了@Conditional注解,根据不同的条件判断是否进行配置。例如,如果类路径下存在DataSource类,就会自动配置数据源相关的Bean。
  9. MyBatis的动态SQL
    • 作用:动态SQL可以根据不同的条件生成不同的SQL语句,提高SQL语句的灵活性和复用性。例如,在查询用户信息时,根据用户输入的不同条件(如用户名、年龄等)生成不同的查询语句。
    • 常用标签
      • if:用于条件判断,根据条件是否成立来决定是否包含某段SQL语句。
      • where:可以自动处理SQL语句中的WHERE关键字,并且会去除多余的AND或OR。
      • set:用于更新语句,自动处理SET关键字和逗号。
      • foreach:用于遍历集合或数组,常用于批量插入或查询。