1. String 和 StringBuffer、StringBuilder 的区别是什么?
可变性
String
是不可变的(后面会详细分析原因)。
StringBuilder
与StringBuffer
都继承自AbstractStringBuilder
类,在AbstractStringBuilder
中也是使用字符数组保存字符串,不过没有使用final
和private
关键字修饰,最关键的是这个AbstractStringBuilder
类还提供了很多修改字符串的方法比如append
方法。abstract class AbstractStringBuilder implements Appendable, CharSequence { char[] value; public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; } //... }线程安全性
String
中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder
是StringBuilder
与StringBuffer
的公共父类,定义了一些字符串的基本操作,如expandCapacity
、append
、insert
、indexOf
等公共方法。StringBuffer
对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder
并没有对方法进行加同步锁,所以是非线程安全的。性能
每次对
String
类型进行改变的时候,都会生成一个新的String
对象,然后将指针指向新的String
对象。StringBuffer
每次都会对StringBuffer
对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StringBuilder
相比使用StringBuffer
仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。对于三者使用的总结:
操作少量的数据: 适用
String
单线程操作字符串缓冲区下操作大量数据: 适用
StringBuilder
多线程操作字符串缓冲区下操作大量数据: 适用
StringBuffer
String 真正不可变有下面几点原因:
保存字符串的数组被
final
修饰且为私有的,并且String
类没有提供/暴露修改这个字符串的方法。
String
类被final
修饰导致其不能被继承,进而避免了子类破坏String
不可变。public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[]; //... }
著作权归所有 原文链接:Java基础常见面试题总结(中) | JavaGuide(Java面试 + 学习指南)
2. MySQL 中的索引是怎么实现的?B+ 树是什么,B 树和 B+ 树的区别,为什么 MySQL 要用 B+ 树?
MySQL 中的索引是通过 B+ 树实现的。B+ 树是一种多叉树,它可以将数据按照一定的顺序组织起来,从而提高查询效率。
B+ 树与 B 树的区别在于,B+ 树的所有数据都存储在叶子节点上,而非叶子节点只存储索引,这样可以提高数据查询效率。B+ 树的叶子节点之间使用指针相连,这样可以实现区间查找,也就是说,可以快速定位某个区间内的数据。
MySQL 之所以采用 B+ 树作为索引的实现方式,主要是因为 B+ 树具有以下优点:
能够支持高效的范围查找和排序。
叶子节点之间使用指针相连,能够支持高效的区间查询。
B+ 树具有较高的数据密度,可以减少磁盘 I/O 次数,提高查询效率。
B+ 树对于插入和删除操作也比较高效。
在 MySQL 中,B+ 树的实现主要是通过 InnoDB 存储引擎来实现的。InnoDB 存储引擎中的索引主要有聚簇索引和辅助索引两种类型,聚簇索引是根据主键创建的索引,而辅助索引是根据非主键列创建的索引。对于辅助索引,MySQL 中会同时创建一个对应的聚簇索引,这样可以提高查询效率。
MySQL中的B+树
3. Spring 框架中都用到了哪些设计模式?
建议:不用记所有的设计模式,重点把单例、代理、工厂、责任链理解了即可
Spring 框架中使用了许多设计模式,以下列举一些比较重要的:
单例模式:Spring 的 Bean 默认是单例模式,通过 Spring 容器管理 Bean 的生命周期,保证每个 Bean 只被创建一次,并在整个应用程序中重用。
工厂模式:Spring 使用工厂模式通过 BeanFactory 和 ApplicationContext 创建并管理 Bean 对象。
代理模式:Spring AOP 基于动态代理技术,使用代理模式实现切面编程,提供了对 AOP 编程的支持。
观察者模式:Spring 中的事件机制基于观察者模式,通过 ApplicationEventPublisher 发布事件,由 ApplicationListener 监听事件,实现了对象间的松耦合。
模板方法模式:Spring 中的 JdbcTemplate 使用了模板方法模式,将一些固定的流程封装在父类中,子类只需实现一些抽象方法即可。
策略模式:Spring 中的 HandlerInterceptor 和 HandlerExecutionChain 使用了策略模式,允许开发者自定义处理器拦截器,按照一定顺序执行。
责任链模式:Spring 中的过滤器和拦截器使用了责任链模式,多个过滤器和拦截器按照一定顺序执行,每个过滤器和拦截器可以拦截请求或者响应并做出相应的处理。
总之,Spring 框架中充分利用了许多设计模式,提供了良好的扩展性和灵活性,降低了代码的耦合度,提高了代码的可维护性。