尚硅谷面试题集(第一季)
1、自增变量
//代码如下
public class Main {
public static void main(String[] args) {
int i = 1;
int j = i++;
int k = i+++i*i++;
// System.out.prinln(i+" "+j+" "+k);//i=4,j=1;k=11;
}
}
字节码如下:
0 iconst_1
1 istore_1
2 iload_1
3 iinc 1 by 1
6 istore_2
7 iload_1
8 iinc 1 by 1
11 iload_1
12 iload_1
13 iinc 1 by 1
16 imul
17 iadd
18 istore_3
19 return
图解如下:
2、单例模式
要点
一是某个类只能有一个实例;
构造器私有化
二是它必须自行创建这个实例;
含有一个该类的静态变量来保存这个唯一的实例
三是它必须自行向整个系统提供这个实例;
对外提供获取该实例对象的方式:
(1)直接暴露(2)用静态变量的get方法获取
(1)饿汉式
饿汉式:直接创建对象,不存在线程安全问题
直接实例化饿汉式(简洁直观)
枚举式(最简洁)
静态代码块饿汉式(适合复杂实例化)
代码如下:
//饿汉式单例:直接创建对象,不存在线程安全问题:不管是否需要都会创建
//1、直接实例化饿汉式(简单直观)
public class Singleton1 {
//1、构造器私有化
private Singleton1(){
}
//2、自行创建,并且用静态变量保存,为了强调这是个单例可用final修饰,使用final便不能 更改,public向外提供实例
public final static Singleton1 INSTANCE = new Singleton1();
}
//饿汉式单例:直接创建对象,不存在线程安全问题:不管是否需要都会创建
//2、枚举:表示该类型的对象是有限的几个,我们可用限定一个便成立单例(最简洁)
//枚举的构造器全都是私有化,该模式等同于饿汉式直接实例
public enum Singleton2 {
INSTACE
}
//饿汉式单例:直接创建对象,不存在线程安全问题:不管是否需要都会创建
//3、静态代码块 饿汉式(适合复杂实例化)
public class Singleton3 {
//1、构造器私有化
private Singleton3(){
}
//2、自行创建,并且用静态变量保存,为了强调这是个单例可用final修饰,使用final便不能 更改,public向外提供实例
public static final Singleton3 INSTANCE;
static {
INSTANCE = new Singleton3();//有参数时最适合这种模式
}
}
(2)懒汉式
懒汉式:延迟创建对象
线程不安全(适用于单线程)
线程安全(适用于多线程)
静态内部类形式(适用于多线程)
代码如下:
//懒汉式单例:延迟创建对象\
//1、线程不安全(适用于单线程)
public class Singleton4 {
//1、构造器私有化
private Singleton4(){
}
//2、用静态变量保存
private static Singleton4 INSTANCE;
//3、提供一个静态方法,获取这个实例对象
public static Singleton4 getInstance(){
if(INSTANCE==null){
try {
Thread.sleep(100);//阻塞线程后如果两个线程进入,可能会造创建两个线程,
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Singleton4();
}
return INSTANCE;
}
}
//懒汉式单例:延迟创建对象\
//2、线程安全(适用于多线程)
public class Singleton5 {
//1、构造器私有化
private Singleton5(){
}
//2、用静态变量保存
private static Singleton5 INSTANCE;
//3、提供一个静态方法,获取这个实例对象
public static Singleton5 getInstance(){
if(INSTANCE==null){//优化线程
synchronized (Singleton5.class){//添加同步块即可锁定该线程
if(INSTANCE==null){
try {
Thread.sleep(100);//阻塞线程后如果两个线程进入,可能会造创建两个线程,
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Singleton5();
}
}
}
return INSTANCE;
}
}
//懒汉式单例:延迟创建对象\
//3、静态内部类形式(适用于多线程)代码简洁:在内部类被加载和初始化时才被创建INSTANCE实例对象
//静态内部类不会自动随着外部类的加载和初始化而被初始化,它是要单独去加载和初始化
//因为是在内部类加载和初始化时,创建的,因此线程安全
public class Singleton6 {
//1、构造器私有化
private Singleton6(){
}
//2、将静态变量存入内部类
private static class Inner{
//2.1、用静态变量保存
private static final Singleton6 INSTANCE = new Singleton6();
}
// 3、暴露接口
public static Singleton6 getInstance(){
return Inner.INSTANCE;
}
}
小节:
如果是饿汉式,枚举形式最简单
如果是懒汉式,静态内部类形式最简单
3、类的初始化和实例初始化
考点:
类初始化过程
实例初始化过程
方法的重写
类初始化过程 :
4、方法的参数传递机制
考点?
方法的传递机制
String、包装类的等对象的不可变性
5、递归与迭代
编程题:有n步台阶,一次只能上1步或2步,共有多少种走法
1、递归
2、循环迭代
6、成员变量与局部变量
考点:
就近原则
变量的分类
成员变量:类变量、实例变量
局部变量
非静态代码块的执行:每次创建实例对象都会执行
方法的调用规则:调用一次,执行一次
7、Spring Bean的作用域之间的区别
<!-- ★bean的作用域
可以通过scope属性来指定bean的作用域
-singleton:默认值。当IOC容器一创建就会创建bean的实例,而且是单例的,每次得到的都是同一个
-prototype:原型的。当IOC容器一创建不再实例化该bean,每次调用getBean方法时再实例化该bean,而且每调用一次创建一个对象
-request:每次请求实例化一个bean
-session:在一次会话中共享一个bean
-->
<bean id="book" class="com.atguigu.spring.beans.Book" scope="prototype">
<property name="id" value="8"></property>
<property name="title" value="红高粱"></property>
<property name="author" value="莫言"></property>
<property name="price" value="10.00"></property>
<property name="sales" value="800"></property>
</bean>
8、Spring支持的常用数据库事务传播属性和…
当开启事务,@Transactional时,没有指定属性,则默认开启required,因为required特性,即如果事
务中进行两次操作,余额有100,买第一件要60,第二件要50,买完第一件则买第二件时失败,因为
要保持原子性,买第二件失败后回滚事务,第一件也回滚事务,则没有买成功。
如果改成propagation=Propagation.REQUIRED_NEW,则可以买成功第一件。
原因是因为当propagation=Propagation.REQUIRED时,开启买第一件和第二件的事务是同一个
,因为原子性,要么都成功,要么都失败,而当propagation=Propagation.REQUIRED_NEW时
,每次启动开启事务的方法时,其开启的是两个不同的事物,则第一件成功是一个事物,
第二件失败又是另一种事物,两种之间不影响。
代码如下
脏读:当前这个事务读到了其他事务更新但是还没提交的值就是脏读。
第一个级别,脏读,不可重复读,幻读都不能避免
第二个级别,不可重复读,幻读不能避免
第三级别:幻读不能避免
第四级别:都可以避免
但是效率从高到低。所以要合适使用,开发时一般用读已提交
9、SpringMVC中如何解决POST请求中文乱码,GET又如何处理
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/testPOJO" method="post">
<!-- 表单项中的name属性值要与POJO类中的属性名保持一致 -->
工号:<input type="text" name="id"><br>
姓名:<input type="text" name="lastName"><br>
邮箱:<input type="text" name="email"><br>
部门编号:<input type="text" name="dept.id"><br>
部门名称:<input type="text" name="dept.name"><br>
<input type="submit">
</form>
</body>
</html>
package com.atguigu.springmvc.handler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.atguigu.springmvc.entities.Employee;
@Controller
public class SpringMVCHandler {
public static final String SUCCESS="success";
//1.SpringMVC中如何解决POST请求中文乱码问题,GET的又如何处理呢
/*
* ★测试入参为POJO
* Spring MVC会按请求参数名和 POJO属性名进行自动匹配,
* 自动为该对象填充属性值。支持级联属性
*/
@RequestMapping("/testPOJO")
public String testPOJO(Employee employee) {
System.out.println("员工的信息是:"+employee);
return SUCCESS;
}
}
测试:
得出结果(中文乱码)
可以使用SpringMVC中的过滤器CharacterEncodingFilter
需要在web.xml中设置过滤器
之后需要设置拦截目标,常设置成拦截所有
如果改成get?
那么还是会乱码
解决:
1、在服务器中的server.xml中第一个Connector中添加属性URLEncoding=“UTF-8”,重启服务器
10、简单谈一下SpringMVC的工作原理
@Controller
public class SpringMVCHandler {
public static final String SUCCESS="success";
//1.简单的谈一下SpringMVC的工作流程
//处理模型数据方式一:将方法的返回值设置为ModelAndView
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
//1.创建ModelAndView对象
ModelAndView mav = new ModelAndView();
//2.设置模型数据,最终会放到request域中
mav.addObject("user", "admin");
//3.设置视图
mav.setViewName("success");
return mav;
}
/*
* ★处理模型数据方式二:方法的返回值仍是String类型,在方法的入参中传入Map、Model或者ModelMap
* 不管将处理器方法的返回值设置为ModelAndView还是在方法的入参中传入Map、Model或者ModelMap,
* SpringMVC都会转换为一个ModelAndView对象
*/
@RequestMapping("/testMap")
public String testMap(Map<String , Object> map) {
//向Map中添加模型数据,最终会自动放到request域中
map.put("user", new Employee(1, "韩总", "hybing@atguigu.com", new Department(101, "教学部")));
return SUCCESS;
}
}
/*①客户端的所有请求都交给前端控制器DispatcherServlet来处理,它会负责调用系统的其他模块来真正处理用户的请求。
②DispatcherServlet收到请求后,将根据请求的信息(URL、http协议方法、请求头、请求参数、cookie等)以及HandlerMapping的配置找到处理该请求的Handler(任何一个对象都可以作为请求的Handler)。
③在这个地方spring会通过HandlerAdapter对该处理器进行封装。
④HandlerAdapter是一个适配器,它用统一的接口对各种Handler中的方法进行调用。
⑤Handler完成对用户请求的处理后,会返回一个ModelAndView对象给DispatcherServlet,顾名思义,ModelAndView包含了数据模型以及相应的视图信息。
⑥ModelAndView的视图是逻辑视图,DisptcherServlet还要借助视图解析器ViewResolver完成从逻辑视图到真正视图的解析工作。
⑦当得到真正的视图对象后,DispatcherServlet会利用视图对象对模型数据进行渲染。
⑧客户端得到响应,可能是一个普通的html页面,也可以是json或xml数据,还可以是一张图片或pdf文件。
源码解析如下
1、发送请求
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="${pageContext.request.contextPath }/testModelAndView">Test ModelAndView</a><br>
<a href="${pageContext.request.contextPath }/testMap">Test Map</a><br>
</body>
</html>
点击Test Map,发送请求进入testMap
/**
* Process the actual dispatching to the handler.处理实际分派给处理程序。
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
处理程序将通过按顺序应用servlet的handler映射获得。
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
HandlerAdapter将通过查询servlet已安装的HandlerAdapter获得
* to find the first that supports the handler class.
找到第一个支持handler类的。
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
所有的HTTP方法都由这个方法处理。这取决于手持适配器或处理程序
* themselves to decide which methods are acceptable.
自己决定哪些方法是可以接受的。
* @param request current HTTP request 当前HTTP请求
* @param response current HTTP response 当前HTTP响应
* @throws Exception in case of any kind of processing failure
如果出现任何处理故障
*/
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
//确定当前请求的处理程序。
//其中mappedHandler就是HandlerExecutionChain对象,里边包含了所有的处理器和拦截器
mappedHandler = getHandler(processedRequest);//getHandler源码如下
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
//确定当前请求的处理程序适配器。
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//调用拦截器的方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//重点
// Actually invoke the handler.实际调用处理程序。
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
//处理结果,源码如下方processDispatchResult
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
/**
* Return the HandlerExecutionChain for this request.
为此请求返回HandlerExecutionChain。
* <p>Tries all handler mappings in order.按顺序尝试所有处理程序映射。
* @param request current HTTP request 当前HTTP请求
* @return the HandlerExecutionChain, or {@code null} if no handler could be found
*/
@Nullable//如果可以传入NULL值,则标记为@Nullable,如果不可以,则标注为@Nonnull。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);//此处得到HandlerExecutionChain对象
if (handler != null) {
return handler;
}
}
}
return null;
}
processDispatchResult源码:
/**
* Handle the result of handler selection and handler invocation, which is
* either a ModelAndView or an Exception to be resolved to a ModelAndView.
*/
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
boolean errorView = false;
//判断是否由异常
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
//渲染视图,源码如下render
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
render
/**
* Render the given ModelAndView.
* <p>This is the last stage in handling a request. It may involve resolving the view by name.
* @param mv the ModelAndView to render
* @param request current HTTP servlet request
* @param response current HTTP servlet response
* @throws ServletException if view is missing or cannot be resolved
* @throws Exception if there's a problem rendering the view
*/
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine locale for request and apply it to the response.
Locale locale =
(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
response.setLocale(locale);
View view;
String viewName = mv.getViewName();
if (viewName != null) {
// We need to resolve the view name.解析视图名
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
else {
// No need to lookup: the ModelAndView object contains the actual View object.
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name '" + getServletName() + "'");
}
}
// Delegate to the View object for rendering.
if (logger.isDebugEnabled()) {
logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
getServletName() + "'", ex);
}
throw ex;
}
}
内容太多了,不往下写了
须知最终是返回视图,并将之放入request域
获取转发器
进行转发
最终可在jsp中取到数据输出到页面中
详细解析
https://www.cnblogs.com/yoci/p/10642493.html
11、Mybatis中当实体类中的属性名和表中的字段名不一样,怎么办?
导致取值不到的现象
有三种解决方案
1.写sql语句时起别名
2.在MyBatis的全局配置文件中开启驼峰命名规则
3.在Mapper映射文件中使用resultMap来自定义映射规则
12、Linux常用服务类相关命令
13、git分支相关命令
14、redis持久化
15、Mysql什么时候建索引
索引是什么?
优势?
劣势?
那些情况不要创建索引?
16、JVM垃圾回收机制
我的理解
java垃圾回收机制?
GC发生在JVM那部分?
堆,方法区
jdk1.8及以后永久代改成元空间
有几种GC,他们的算法是什么?
java有4种,详情可看ppt
17、redis在项目中的应用场景
String:封锁一个IP地址:即是经常访问同一个IP地址。使用Incrby命令记录当前IP地址被次数
Hash:如果用String存储用户信息,当修改时,需要将全部的String用户信息反序列化,如果用Hash存储,需要修改什么就反序列化什么,因为序列化和反序列化都是要进行IO操作的,用String会增加IO次数,使用Hash比String性能要好。所以存储对象时不建议用String存储
18、Elasticsearch和solr的区别
19、单点登录实现过程
20、购物车实现过程
21、消息队列在项目中的应用
行锁
行锁的劣势:开销大;加锁慢;会出现死锁
行锁的优势:锁的粒度小,发生锁冲突的概率低;处理并发的能力强
加锁的方式:自动加锁。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;对于普通SELECT语句,InnoDB不会加任何锁;当然我们也可以显示的加锁:
共享锁:select * from tableName where … + lock in share more
排他锁:select * from tableName where … + for update
InnoDB和MyISAM的最大不同点有两个:一,InnoDB支持事务(transaction);二,默认采用行级锁。加锁可以保证事务的一致性,可谓是有人(锁)的地方,就有江湖(事务);我们先简单了解一下事务知识。
表锁
表锁的优势:开销小;加锁快;无死锁
表锁的劣势:锁粒度大,发生锁冲突的概率高,并发处理能力低
加锁的方式:自动加锁。查询操作(SELECT),会自动给涉及的所有表加读锁,更新操作(UPDATE、DELETE、INSERT),会自动给涉及的表加写锁。也可以显示加锁:
共享读锁:lock table tableName read;
独占写锁:lock table tableName write;
批量解锁:unlock tables;
详解链接:https://blog.csdn.net/xts5701046/article/details/81395958