面试题总结

本文是基于尚硅谷的面试总结,重点涵盖了Java面试中常见的单例模式、类与实例初始化、参数传递机制、SSM框架(Spring、SpringMVC、MyBatis)的面试题,还包括MySQL索引、Redis使用场景、购物车实现及消息队列在项目中的应用。详细解析了各种单例模式的实现方式,Spring Bean的作用域、数据库事务的传播属性和隔离级别,以及MyBatis中属性名与字段不一致的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于尚硅谷的面试总结

1. 单例模式

单例模式有【饿汉式】和【懒汉式】之分。饿汉式是在类加载的时候就进行对象的创建,而懒汉式是在需要使用的时候进行对象的创建

创建饿汉式的三种方式

饿汉式      1.直接创建 2.枚举  3. 静态代码块
		【 可以避免线程安全问题   】
 * 构造器私有化
 * 自行创建,并且用静态变量保存
 *
 * final 修饰类中的属性
 * 表示该属性一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对对象属性来说其引用不可再变。
 */
  //   1.
public class ESingleton {
    public static final ESingleton ENSTANCE = new ESingleton();
    private ESingleton(){}
}
// 2. 
// 枚举类的构造器都是私有的
public enum ESingletonEnum {
	INSTANCE
}
//3. 
public static final ESingletonStaticBlock INSTANCE;
	static{
		INSTANCE = new ESingletonStaticBlock();
	}
	private ESingletonStaticBlock (){}

注意: 对于饿汉式枚举方式最简单

创建懒汉式的三种方式

/* 懒汉式
 *    构造器私有化
 *     在类中使用静态变量保存唯一的使用
 * 懒汉式可能会发生【线程安全】的问题
 */
 //  1.
public class LazySingleton {
	//  这里使用private而不使用public因为不能通过调用这个属性而创建对象
	//   这样创建出来的对象为空 【null】
	private static LazySingleton LAZYSINGLETON ;
	private LazySingleton(){}
	public static LazySingleton getInstance(){
		if (LAZYSINGLETON == null) {
			LAZYSINGLETON =	new LazySingleton();
		}
		return LAZYSINGLETON;
	}
}
// 2.
public class LazySingletonBySuo {
	private static LazySingletonBySuo LAZYSINGLETON ;
	private LazySingletonBySuo(){}
	public static LazySingletonBySuo getInstance(){
		if (LAZYSINGLETON == null) {    //为了性能考虑
			synchronized (LazySingletonBySuo.class){  //为了安全考虑
				if (LAZYSINGLETON == null) {  
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					LAZYSINGLETON =	new LazySingletonBySuo();
				}
			}
		}
		return LAZYSINGLETON;
	}
}
//  测试
	//以下测试的是懒汉式
		// 先保证线程安全 加锁
		new Thread() {
			@Override
			public void run() {
				LazySingletonBySuo lazySingleton = LazySingletonBySuo.getInstance();
				System.out.println(Thread.currentThread().getName()+lazySingleton);
			}
		}.start();

		new Thread() {
			@Override
			public void run() {
				LazySingletonBySuo lazySingleton = LazySingletonBySuo.getInstance();
				System.out.println(Thread.currentThread().getName()+lazySingleton);
			}
		}.start();
// 运行结果
// Thread-0singleton.LazySingletonBySuo@2a75ae17
// Thread-1singleton.LazySingletonBySuo@2a75ae17

		//但是呢,如果在方法中调用了线程睡眠1秒,这个时候就会发生【不是单例的情况】
//Thread-1singleton.LazySingletonBySuo@5a2cdcfd
//Thread-0singleton.LazySingletonBySuo@3ca00ad1
		//出现这种的情况就是  第一个线程判断出了为空,然后阻塞
		//让出cpu使第二个线程使用
		//第二个线程进入这个方法,也判断出为空,阻塞
		//在往后继续执行的时候,都创建了对象、

		// 解决办法  加锁synchronized

		//  优化,在加锁之前判断是否为空,如果为空,就去创建,否则,返回
	}
// 3. 
//  内部类不会随着外部类的加载而创建,只有使用的时候,才会创建
public class LazySingletonYouHua {
	private LazySingletonYouHua(){}
	private static class Inner{
		private static LazySingletonYouHua LAZYSINGLETON = new LazySingletonYouHua();
	}
	public static LazySingletonYouHua getInstance(){
		return Inner.LAZYSINGLETON;
	}
} 

在懒汉式中,使用内部类最方便

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

2.类的初始化和实例的初始化

自己算算答案是什么
在这里插入图片描述
答案是:
在这里插入图片描述

解析

/*
想创建实例就要先加载类并进行初始化
 * main方法所对应的类先进行加载并初始化  (static修饰的在类加载的时候就执行了)
 *
 * 类加载并初始化:
 *      先父类后子类,加载【静态变量赋值代码】和【静态代码块】(这两个根据代码顺序执行)
 * 实例加载并初始化:
 *     1. super()  这里的执行也是 1,2,3的执行顺序
 *     2. 【非静态变量赋值代码】和【非静态代码块】 (这两个根据代码顺序执行) 3.构造方法
 *
 *  方法重写:
 *      由于多态,所以出现了父类上的执行结果是子类的执行结果
 *      什么不能出现方法重写呢?  【1】  final修饰   【2】 static修饰  【3】private子类不可见的
 */

3.方法的参数传递机制

  • 基本数据类型,传递的是值
  • 引用数据类型,传递的是地址
    例题:
    在这里插入图片描述
    注意: 全局变量引用在栈中,其值在堆中;方法的执行在栈中

4.全局变量和局部变量

public class TestVariable{
	int i;
	int j;
{
	int i = 10;
	i++;
	j++;
}
public int test(int j){
	j++;
	i++;
	return j;
}

public static void main(String[] args) {
	TestVariable test1 = new TestVariable();
	TestVariable test2 = new TestVariable();
	test1.test(10);
	test1.test(20);
	test2.test(30);
	System.out.println(test1.i+","+test1.j);    //  2,1
	System.out.println(test2.i+","+test2.j);    //  1,1
}
}

5 ssm的面试题

1)Spring Bean的作用域有什么区别

在Spring中,可以在 元素的scope属性里设置bean的作用域,以决定这个bean是单实例还是多实例的。默认情况下是单实例。

类别说明
singleton在SpringIOC容器中仅存在一个Bean实例,当IOC容器一创建就会创建Bean的实例,Bean以单实例的方式存在
prototype每次调用getBean()时都会返回一个新的实例
request每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session同一个HTTP Session共享一个Bean,不同的HTTP使用不同的Bean。该作用域仅适合于WebApplicationContext环境

2)Spring支持的常用的数据库事务传播属性和设置事务的隔离级别

事务的属性:
1. propagation : 设置事务的传播行为
传播行为: 一个方法运行在了一个开启事务的方法中时,当前方法是使用原来的事务还是开启一个新的事务
- Propagation.REQUIRED: 默认值,使用原来的事务
- Propagation.REQUIRES_NEW : 将原来的事务挂起,开启一个新的事务

2.isolation : 设置事务的隔离级别
-Isolation.REPEATABLE_READ :可重复读,MySQL默认的隔离级别
-Isolation.READ_COMMITED: 读已提交,Oracle默认的隔离级别,开发时通常使用的隔离级别

事务的隔离级别讲的比较好的一篇文章:
https://developer.aliyun.com/article/743691

3)springMVC的工作流程

  • 这篇文章比较好: https://www.jianshu.com/p/4851dbedb63d
    需要注意的就是Handler和HandlerMapping和HandlerRequest的区别

4)mybatis当实体类中的属性名和表中的字段不一致时的解决办法

方法一: 写SQL语句时起别名

select create_time createTime from xxxxx;

方法二:开启驼峰命名规则
在mybatis配置文件中

<setting name=”mapUnderscoreToCamelCase” value=”true”/>

在springboot的yml文件中

mybatis.configuration.map-underscore-to-camel-case:=true

方法三:在mapper映射文件中使用resultMap自定义规则

 <resultMap type=”” id=””>
	<result column=”create_time”
		 property=”createTime”/>
</resultMap>

方法四: 编写Mybatis配置类

@Configuration
public class MyBatisConfig {
    @Bean
    public ConfigurationCustomizer configurationCustomizer(){
        return new ConfigurationCustomizer() {
            @Override
            public void customize(Configuration configuration) {
                configuration.setMapUnderscoreToCamelCase(true);
            }
        };
    }
}

6 mysql什么时候建立索引

索引是 【数据结构】,检索查询数据时快,排序快。但是做一些写操作比较慢了,并且占空间

以下情况需要建立索引

  • 主键自动建立唯一索引
  • 频繁作为查询条件的字段应该创建索引
  • 查询中与其他表关联的字段,外键关系建立索引
  • 单键/组合索引的选择问题,组合索引性价比更高
  • 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
  • 查询中统计或者分组字段

以下情况不需要建立索引

  • 表记录太少
  • 经常增删改的表或者字段
  • where条件里用不到的字段不创建索引
  • 过滤性不好的不适合建立索引

7.Redis在项目中的使用场景

数据类型使用场景
String什么时候封锁一个IP地址 使用 incrby命令
Hash存储用户信息【id,name,age】这种的不建议使用string类型来存储,因为它会将所有的都序列化
Lsit实现最新消息的【排行】,还可以利用List的push命令,将任务存在list集合中 Redis–list数据类型来模拟消息队列【电商中的秒杀就可以采用这种方法来完成一个秒杀活动】
Set可以自动排重 微博中将每个人的好友存在Set中
ZsetSortedSet 【以某个条件为权重进行排序】 例如:商品详情的时候,都会有一个排名,还可按照价格进行排名

8.购物车实现过程

购物车:
  1. 购物车和用户的关系
           1) **一对一**,一个用户对应一个购物车
           2) 单点登录一定在购物车之前
  2. 跟购物车有关的操作有哪些
           1)添加购物车
                 a)用户未登录状态下的添加
                 	  i:  添加到什么地方
                 	  ii: 未登录将数据保存到什么地方   Redis    Cookie(自己开发项目时)
                 b) 用户已登录状态下的添加
                     i: 添加到Redis缓存中,为了读取速度快。用Hash来存储hset(key,field,value)
                     ii:存在数据库中,保证数据的安全性
           2)展示购物车
           a)未登录状态
           				直接从cookie中取得数据展示数据即可
           b)登录转态
           				用户一旦登录:必须显示数据库【Redis】+cookie中的数据

9.消息队列在项目中的使用

背景: 在分布式系统中是如何处理高并发的
由于在高并发的环境下,来不及同步处理用户发送的请求,则会导致请求发生阻塞。
比如:大量的insert,update之类的请求同时到达MYSQL,直接导致无数的行锁表锁,甚至会导致请求堆积很多,从而触发 too many connections错误。
使用消息队列可以解决【异步通信】

同步/异步 阻塞/非阻塞的区别

  • 同步/异步 关注的是消息通知的机制

  • 阻塞/非阻塞 关注的是等待消息中的机制
    看图:
    在这里插入图片描述
    // ===== == 或者===============
    在这里插入图片描述
    并行

在这里插入图片描述
排队
在这里插入图片描述
消息队列在电商使用场景

在这里插入图片描述
消息队列的弊端: 发送消息的不确定性【延迟队列和轮询技术来解决】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值