开学大四了,最近也在找java后端开发的实习生工作,根据经历的面试经验总结了一下高频面试题,希望可以帮助到和我一样在找实习的小伙伴们。本帖将会持续更新,若有错误欢迎指正~
面试题总结
Spring 的面试常考题
1.Spring中bean的scope属性、区别
- singleton 表示在spring容器中的单例,通过spring容器获得该bean时总是返回唯一的实例
- prototype表示每次获得bean都会生成一个新的对象
- request表示在一次http请求内有效(只适用于web应用)
- session表示在一个用户会话内有效(只适用于web应用)
- globalSession表示在全局会话内有效(只适用于web应用)
2.Spring Bean 的生命周期
首先是实例化、属性赋值、初始化、销毁这 4 个大阶段
3.谈一谈对IOC、AOP的理解
IOC:控制反转。在面向对象的软件系统中,其实底层都是又N个对象构成的,各个对象之间相互联系合作,最终实现了业务逻辑。但是在这个过程中若某个部分出现了问题,将会导致全局崩盘,因此我们需要降低各个模块的关联,也就是解耦。IOC是一种设计思想,简单的说就是将复杂的系统分解成相互合作的对象,然后这些对象通过封装以后,内部实现对外部是透明的,从而降低了问题的复杂度。
AOP:面向切面编程。比如你写了个方法用来做一些事情,但这个事情要求登录用户才能做,你就可以在这个方法执行前验证一下,执行后记录下操作日志,把前后的这些与业务逻辑无关的代码抽取出来放一个类里,这个类就是切面(Aspect),这个被环绕的方法就是切点(Pointcut),你所做的执行前执行后的这些方法统一叫做增强处理(Advice)。
静态代理和动态代理:自己手写的代理类就是静态代理。而动态代理就是交给程序去自动生成代理类(反射等机制),两种方式:JDK动态代理和cglib动态代理。
- JDK动态代理只能对实现了接口的类生成代理,而不能针对类
- CGLib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)
4.Spring用的啥
Spring会根据具体的Bean是否具有接口去选择动态代理方式,如果有接口,使用的是Jdk的动态代理方式,如果没有接口,使用的是cglib的动态代理方式。
5.依赖注入的时候?
getbean() 的时候。
Http和TCP
HTTP与HTTPS有什么区别?
HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。
HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
HTTP状态码
1XX:通知
2XX: 成功
3XX 重定向
4XX:客户端错误
5XX 服务端错误
SpringBoot
SpringBoot自动配置的原理
在spring程序main方法中 添加@SpringBootApplication,中的@EnableAutoConfiguration会自动去maven中读取每个starter中的spring.factories文件 该文件里配置了所有需要被创建spring容器中的bean
2.SpringBoot的核心注解是哪个?它主要由哪几个注解组成的?
启动类: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
主成:
@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能:
@ComponentScan: Spring组件扫描。
Mysql
1.MySQL 中 varchar 与 char 的区别?varchar(50) 中的 50 代表的涵义?
- 1、varchar 与 char 的区别,char 是一种固定长度的类型,varchar 则是一种可变长度的类型。
- 2、varchar(50) 中 50 的涵义最多存放 50 个字符。varchar(50) 和 (200) 存储 hello 所占空间一样,但后者在排序时会消耗更多内存,因为 ORDER BY col 采用 fixed_length 计算 col 长度(memory引擎也一样)。所以,实际场景下,选择合适的 varchar 长度还是有必要的。
2.如何避免 sql 注入?
PreparedStatement(简单又有效的方法)、使用正则表达式过滤传入的参数、字符串过滤、检查是否包函非法字符、页面判断代码。
3.说一下数据库的事务隔离?
读未提交,读提交,可重复读,可串行。
4. 1.MySQL 的内连接、左连接、右连接有什么区别?
内连接,显示两个表中有联系的所有数据;2.左链接,以左表为参照,显示所有数据;3.右链接,以右表为参照显示数据
#内连接关键字 inner join on
#左连接 left join on
#右连接 left join on
5. Mysql性能优化调优
-
修改 SQL 或者尽量让 SQL 走索引
-
使用 explain 等工具分析 SQL
explain 可以帮助我们分析 select 语句,让我们知道查询效率低下的原因。这个关键字一般放在 select 语句的前面,用于描述 MySQL 如何执行查询操作以及 MySQL 成功返回结果集需要执行的行数,执行会输出一些 explain 的字段。
//type 字段的返回值,性能从最优到最差: system -> const -> eq_ref -> ref -> fulltext -> ref_or_null -> index_merge -> unique_subquery -> index_subquery -> range -> index -> all id:表示了 MySQL 的执行顺序,id 越大越先执行; type:表示 MySQL 找到数据行的方式; key:实际使用的索引; Extra:额外信息。
Mybatis
1.#{ }和${ }的区别是什么?
#{}是预编译处理,${}是字符串替换
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理 时 , 就 是 把 {}时,就是把 时,就是把{}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。
2.当实体类中的属性名和表中的字段名不一样 ,怎么办
第一种:让实体类属性名和表中字段保持一致
第二种:用resultMap来映射字段名和实体类属性名,让其一一对应
<select id="getOrder" parameterType="int" resultMap="order_resultmap">
select * from orders where order_id=#{id}
</select>
<resultMap type=”类路径” id=”order_resultmap”>
<!–用id属性来映射主键字段–>
<id property=”id” column=”order_id”>
<!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–>
<result property = “orderno” column =”order_no”/>
<result property=”price” column=”order_price” />
</reslutMap>
3.Hibernate 和 MyBatis 的区别
ORM一般指对象关系映射
相同点
都是对jdbc的封装,都是持久层的框架,都用于dao层的开发。
不同点
映射关系
MyBatis 是一个半自动映射的框架,配置Java对象与sql语句执行结果的对应关系,多表关联关系配置简单
Hibernate 是一个全表映射的框架,配置Java对象与数据库表的对应关系,多表关联关系配置复杂
SQL优化和移植性
- Hibernate 对SQL语句封装,提供了日志、缓存、级联(级联比 MyBatis 强大)等特性,此外还提供 HQL(Hibernate Query Language)操作数据库,数据库无关性支持好,但会多消耗性能。如果项目需要支持多种数据库,代码开发量少,但SQL语句优化困难。
- MyBatis 需要手动编写 SQL,支持动态 SQL、处理列表、动态生成表名、支持存储过程。开发工作量相对大些。直接使用SQL语句操作数据库,不支持数据库无关性,但sql语句优化容易。
开发难易程度和学习成本
- Hibernate 是重量级框架,学习使用门槛高,适合于需求相对稳定,中小型的项目,比如:办公自动化系统
- MyBatis 是轻量级框架,学习使用门槛低,适合于需求变化频繁,大型的项目,比如:互联网电子商务系统
总结
MyBatis 是一个小巧、方便、高效、简单、直接、半自动化的持久层框架,
Hibernate 是一个强大、方便、高效、复杂、间接、全自动化的持久层框架。
4.Mybatis的执行流程
// 1.加载配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 2. 创建SqlSessionFactory对象实际创建的是DefaultSqlSessionFactory对象
SqlSessionFactory builder = new SqlSessionFactoryBuilder().build(is);
// 3. 创建SqlSession对象实际创建的是DefaultSqlSession对象
SqlSession sqlSession = builder.openSession();
// 4. 创建代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 5. 执行查询语句
List<User> users = mapper.selectUserList();
第一步:通过Resources加载配置好的mybatis.xml配置文件。
第二步:然后看第二句话,这句话是关键。我们首先new了一个SqlSessionFactoryBuilder对象,他是SqlSessionFactory的构建者。我们调用了他的build()方法。
//XMLConfigBuilder,是用来解析XML文件的一个构建者,通过他的parse()方法解析mybatis配置文件
XMLConfigBuilder parser = new XMLConfigBuilder (inputStream,environment,properties);
return build(parser.parse());
第三步:继续往下走,我们最终的目的是获取一个SqlSession对象,现在我们有了一个SqlSessionFactory了,就愉快的生成SqlSession吧。从第三句看,调用了openSession()(在这一步实际创建的是DefaultSqlSession对象)
//environment(xml中配置的),而且是从configuration中获得的。通过这些参数transactionFactory就帮我们产生了transaction。
return new DefaultSq1Session (configuration,executor,autoCommit);
5.介绍一下Mybatis框架
MyBatis 是一个可以自定义 SQL、存储过程和高级映射的持久层框架。
6.Mybatis的执行器
三种:
- SIMPLE(simple): 默认的执行器, 对每条sql进行预编译->设置参数->执行等操作
- BATCH(batch): 批量执行器, 对相同sql进行一次预编译, 然后设置参数, 最后统一执行操作
- REUSE(reuse): REUSE 执行器会重用预处理语句
SpringMVC
核心组件
1.DispatcherServlet:前端控制器
2.Handler:控制器,完成具体的业务逻辑
3.HandlerMapper:将请求映射到Handler
4.HandlerInterceptor:处理器拦截器
5.HandlerExecutionChain:处理器执行链
6.HandlerAdapter:处理器适配器
7.ModelAndView:装载模型数据和视图
8.ViewResolver:视图解析器
1.SpringMvc的执行流程
客户端发送请求,到web.xml中然后DispatcherServlet接收到后根据handlerMapper的映射,将请求映射到Handler。生成Handler以及HandlerInterceptor,返回给DispatcherServlet。DispatcherServlet通过HandlerAdapter执行Handler的具体业务方法,这里会返回一个ModelAndView。DispatcherServlet通过视图解析器进行解析,返回这个填充了模型数据的view,相应给客户端。
- 用户点击某个请求路径,发起一个request请求,此请求会被前端控制器处理。
- 前端控制器请求处理器映射器去查找Handler。可以依据注解或者XML配置去查找。
- 处理器映射器根据配置找到相应的Handler(可能包含若干个Interceptor拦截器),返回给前端控制器。
- 前端控制器请求处理器适配器去执行相应的Handler处理器(常称为Controller)。
- 处理器适配器执行Handler处理器。
- Handler处理器执行完毕之后会返回给处理器适配器一个ModelAndView对象(SpringMVC底层对象,包括Model数据模型和View视图信息)。
- 处理器适配器接收到Handler处理器返回的ModelAndView后,将其返回给前端控制器。
- 前端控制器接收到ModelAndView后,会请求视图解析器(ViewResolver)对视图进行解析。
- 视图解析器根据View信息匹配到相应的视图结果,反馈给前端控制器。
- 前端控制器收到View具体视图后,进行视图渲染,将Model中的模型数据填充到View视图中的request域,生成最终的视图(View)。
- 前端控制器向用户返回请求结果。
2.转发和重定向区别
- 直接请求转发Forward
- 间接请求转发 Redirect
- 请求转发在服务器端完成的;重定向是在客户端完成的。
- 请求转发的速度快;重定向速度慢。
- 请求转发的是同一次请求;重定向是两次不同请求。
- 请求转发不会执行转发后的代码;重定向会执行重定向之后的代码。
- 请求转发地址栏没有变化;重定向地址栏有变化。
- 请求转发必须是在同一台服务器下完成;重定向可以在不同的服务器下完成。
3.拦截器如何实现
定义类实现HandlerInterceptor 接口,通过重写preHandle、postHandle、afterCompletion
-
preHandle:预处理拦截
-
postHandle:后处理方法
-
afterCompletion:最后执行的方法
只有当preHandle方法放行后才会执行。
拦截器的使用步骤:
-
定义类实现HandlerInterceptor 接口
-
在springmvc 配置文件中,声明拦截器,让框架知道拦截器的存在
<!--声明拦截器:拦截器可以有多个或0个--> <mvc:interceptors> <!--声明第一个拦截器--> <mvc:interceptor> <!--指定拦截的请求URI地址 path:就是uri地址,可以使用通配符 **:表示任意的字符,文件或者多级目录和目录中的文件--> <mvc:mapping path="/**"/> <!--声明拦截器对象--> <bean class="cn.edu.huat.handler.MyInterceptor" /> </mvc:interceptor> </mvc:interceptors>
拦截器的执行时间:
- 在请求处理之前,也就是Controller 类中的方法执行之前先被拦截
- 在控制器方法执行之后也会执行拦截器
- 在请求处理完成后也会执行拦截器
当有多个拦截器时,形成拦截器链。拦截器链的执行顺序,与其注册顺序一致。需要再次强调一点的是,当某一个拦截器的preHandle() 方法返回 true并被执行到时,会向一个专门的方法栈中放入该拦截器的 afterCompletion() 方法。
4.拦截器和过滤器的区别
(1)过滤器是servlet中的对象,拦截器是框架中的对象
(2)过滤器实现Filter接口的对象,拦截器是实现HandlerInterceptor接口
(3)过滤器是用来设置request,response的参数,属性的,侧重对数据过滤的。拦截器是用来验证请求的,能截断请求。
(4)过滤器是在拦截器之前先执行的
(5)过滤器是tomcat服务器创建的对象。拦截器是springmvc容器中创建的对象
(6)过滤器是一个执行时间点。拦截器有三个执行时间点
(7)过滤器可以处理 jsp、js、html 等等。拦截器是侧重拦截对Controller 的对象,如果请求不能被DispatcherServlet 接收,这 个请求不会执行拦截器内容
(8)拦截器拦截普通类方法执行,过滤器过滤servlet 请求响应
5.什么是SpringMVC
Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把模型-视图-控制器分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
Model是指要处理的业务逻辑和数据操作,它接收视图请求的数据并返回最终的处理结果;
View视图主要是指的跟用户打交道并且显示给用户看的;
Controller看成是Model和View的桥梁,枢纽,响应请求,处理跳转,使模型和视图保持一致。
6.Spring MVC与Struts2区别
相同点
都是基于mvc的表现层框架,都用于web项目的开发。
不同点
1.前端控制器不一样。Spring MVC的前端控制器是servlet:DispatcherServlet。struts2的前端控制器是filter:StrutsPreparedAndExcutorFilter。
2.请求参数的接收方式不一样。SpringMvc通过在coontroller方法中定义形参接收参数,springmvc可以使用单例模式管理controller,基于方法的开发,线程安全,推荐使用单例模式的开发(执行效率更高),默认就是单例开发模式。struts2是通过类的成员变量接收请求的参数(action类中定义成员变量接收参数),是基于类的开发,线程不安全,只能设计为多例的开发。
3.Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,Spring MVC通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
4.与spring整合不一样。Spring MVC是spring框架的一部分,不需要整合。在企业项目中,Spring MVC使用更多一些。
7.如果在拦截请求中,我想拦截get方式提交的方法,怎么配置
可以在@RequestMapping注解里面加上method=RequestMethod.GET。
线程
1.什么是线程
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。
2.线程和进程有什么区别?
一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。一个进程可以有多个线程
3.Thread 类中的start() 和 run() 方法有什么区别?
start()方法被用来启动新创建的线程,使该被创建的线程状态变为可运行状态。调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。
4.线程的生命周期
线程的生命周期包含5个阶段,包括:新建、就绪、运行、阻塞、销毁。
- 新建:就是刚使用new方法,new出来的线程;
- 就绪:就是调用的线程的start()方法后,这时候线程处于等待CPU分配资源阶段,谁先抢的CPU资源,谁开始执行;
- 运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能;
- 阻塞:在运行状态的时候,可能因为某些原因导致运行状态的线程变成了阻塞状态,比如sleep()、wait()之后线程就处于了阻塞状态,这个时候需要其他机制将处于阻塞状态的线程唤醒,比如调用notify或者notifyAll()方法。唤醒的线程不会立刻执行run方法,它们要再次等待CPU分配资源进入运行状态;
- 销毁:如果线程正常执行完毕后或线程被提前强制性的终止或出现异常导致结束,那么线程就要被销毁,释放资源;
5.如何优雅的中断线程?
main线程通过中断操作和cancel()方法均可使CountThread得以终止。这种通过标识位或者中断操作的方式能够使线程在终止时有机会去清理资源,而不是武断地将线程停止,因此这种终止线程的做法显得更加安全和优雅。
Mysql
1.mysql的四种事务隔离级别
事务的基本要素(ACID):原子性、一致性、隔离性、持久性
隔离级别 | 脏读 | 不可重复度 | 欢读 |
---|---|---|---|
读未提交(read-uncommitted) | 1 | 1 | 1 |
不可重复读(read-committed) | 0 | 1 | 1 |
可重复读(repeatable-read) | 0 | 0 | 1 |
可串行化(serializable) | 1 | 0 | 0 |
2.drop和delete的区别
drop主要用于删除结构(如表、数据库、字段);字段也是结构的一种,但是我们改变了表结构要先alter方法。例如,我们要删除student表上的age字段的信息,可以这样写:alter table student drop age
delete主要用于删除数据
3.什么是索引?索引的关键字是什么?如何创建索引
索引是一种数据结构。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。
索引的关键字是index
unique index 唯一索引
索引对数据插入的效率有一定的影响
对于数据重复度高,值范围有限的列如果建索引建议使用位图索引
可以在多个列上建立联合索引
4.什么是视图?如何创建视图?有什么作用?
视图(view)是一种虚拟存在的表,是一个逻辑表,本身并不包含数据。作为一个select语句保存在数据字典中的。通过视图,可以展现基表的部分数据;视图数据来自定义视图的查询中使用的表,使用视图动态生成。
create VIEW s_View as select * from student where sex = '男';
5.事务的并发问题
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
6.除了自动编号字段外,如果表中某个字段在 INSERT 中没有出现,那么该字段该取什么值?
默认值
7.数据库相关语言描述
1.数据查询语言(DQL) select语句—>查询
2.数据操纵语言(DML语句)data manipulation language
insert, update, delete
3.数据定义语言(DDL语句)data definition language
create(创建), alter(修改), drop(删除), rename(重命名), truncate(删除表中的数据)
4**.[事务]控制语句**(TCL语句)transction control
commit(提交), rollback(回滚), savepoint(记录点,用来回滚)
5.数据控制语言(DCL语句)data control language
grant【授权】, revoke【回收】
8.常见符号解释
+=
<<=:左移赋值
>>>= 右移赋值,左边空出的位以0填充
9.DBMS 中实现事务隔离性的子系统是
并发控制子系统
JSP、Servlet
1、jsp有哪些内置对象作用分别是什么
9中基本内置组件
request 用户端请求,此请求会包含来自GET/POST请求的参数
response 网页传回服务器端的回应
pageContext 网页的属性是在这里管理
session 与请求有关的会话期
application : 服务器启动时创建,服务器关闭时停止,为多个应用程序保存信息
out 用来传送回应的输出
config servlet的构架部件
page JSP网页本身
exception 针对错误网页,未捕捉的例外
2. Servlet的生命周期(运行流程)
Servlet的生命周期分为三个阶段:
- 初始化:Web容器加载servlet,调用init()方法
- 处理请求:当请求到达时,运行其service()方法。service()自动派遣运行与请求相对应的doXXX(doGet或者doPost)方法。
- 销毁:服务结束,web容器会调用servlet的distroy()方法销毁servlet。
3. Jsp和Servlet的区别
-
jsp进过编译过后就变成了Servlet(jsp的本质就是Servlet,JVM只能之别java类,不能识别jsp代码,Web容器将JSP的代码编译成JVM能够识别的java类)
-
jsp更擅长表现于页面显示,servlet更擅长于逻辑控制.
-
Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到.
4. Servlet实现方式
- 使用时限servlet接口的方法来实现,使用的时候需要引用servlet-api.jar
- 实现servlet程序,继承 GenericServlet 这种方法很简单
- 通过继承HttpServlet,重写doGet、doPost方法
5. get提交和post提交有何区别
- get一般用于从服务器上获取数据,post一般用于向服务器传送数据
- 请求的时候参数的位置有区别,get的参数是拼接在url后面,用户在浏览器地址栏可以看到。post是放在http包的包体中。
- 能提交的数据有区别,get方式能提交的数据只能是文本,且大小不超过1024个字节,而post不仅可以提交文本还有二进制文件。
- servlet在处理请求的时候分别对应使用doGet和doPost方式进行处理请求
1.git常用的命令
# 在当前目录新建一个Git代码库
$ git init
# 新建一个目录,将其初始化为Git代码库
$ git init [project-name]
# 下载一个项目和它的整个代码历史
$ git clone [url]
# 添加当前目录的所有文件到暂存区
$ git add .
代码提交
# 提交暂存区到仓库区
$ git commit -m [message]
# 提交暂存区的指定文件到仓库区
$ git commit [file1] [file2] ... -m [message]
# 提交工作区自上次commit之后的变化,直接到仓库区
$ git commit -a
# 提交时显示所有diff信息
$ git commit -v
# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
$ git commit --amend -m [message]
# 重做上一次commit,并包括指定文件的新变化
$ git commit --amend [file1] [file2] ...
分支
# 列出所有本地分支
$ git branch
# 列出所有远程分支
$ git branch -r
# 列出所有本地分支和远程分支
$ git branch -a
# 新建一个分支,但依然停留在当前分支
$ git branch [branch-name]
# 新建一个分支,并切换到该分支
$ git checkout -b [branch]
# 新建一个分支,指向指定commit
$ git branch [branch] [commit]
# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]
# 切换到指定分支,并更新工作区
$ git checkout [branch-name]
# 切换到上一个分支
$ git checkout -
# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]
# 合并指定分支到当前分支
$ git merge [branch]
# 选择一个commit,合并进当前分支
$ git cherry-pick [commit]
# 删除分支
$ git branch -d [branch-name]
# 删除远程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]
集合
1. Set方法如何去重
实现原理,先利用HashCode码比对,HashCode码相同再调用equals方法,查看是否同一个对象,是则无法存入
2. HashMap实现原理
当我们往HashMap中put元素时,首先根据key的HashCode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。
3. HashMap和Hashtable的区别
HashMap是线程不安全的,效率高,可以存储null键和null值。
Hashtable是线程安全的,但是效率低,不可以存储null键和null值。
Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现
基础
1. String、StringBuffer 与 StringBuilder 的区别
String 被声明为 final,因此它不可被继承,不可被改变。内部使用 char 数组存储数据,该数组被声明为 final,这意味着 value 数组初始化之后就不能再引用其它数组。并且 String 内部没有改变 value 数组的方法,因此可以保证 String 不可变。
常用方法:
replace() 字符串替换
split() 字符串拆分
substring() 字符串的截取
contains() 字符串查找
indexOf() 返回字符串第一次出现时的下标
equals()
charAt() 返回指定索引处的字符。索引范围为从 0 到 length() - 1
trim() 去掉前后的空格
isEmpty() 判空
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的。在单线程下StringBuilder 效率更高
2. StringBuffer 与 StringBuilder线程安全问题
StringBuilder对象底层使用的是可变的char类型数组,其append
方法是调用了父类AbstractStringBuilder
的append方法,两者append方法代码片段如下所示:
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;
}
在拼接的过程中,主要分为三个步骤:
首先是获取变量count
与len
的值
两者相加
最后将和赋值给count
变量
假设此时count值为1,len 值为1。A、B两个线程都同时执行到了这一行语句,两个线程执行第一步操作获取count的值都为1,线程A执行了第二步操作,但是还没来得及执行第三步操作的时候,线程B也执行了第二步操作,这就造成了2个线程执行后的count值都为2而不是3。所以这也是上面测试的代码输出的值小于期望值的原因。
3.反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
总结:反射就是把java类中的各种成分映射成一个个的Java对象
4.异常的分类
try、catch、finally
Throwable
Error Exception
IO Runtime
5.什么是多态?
多态是同一个行为具有多个不同表现形式或形态的能力。
6. Java面向对象的三大特征
封装:是将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
继承、多态
7.如何解决跨域问题
第一种:注解
@CrossOrigin
第二种:在拦截器的相应头中加入Access-Control-Allow-Origin
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
response.setHeader("Access-Control-Allow-Origin", "*"); //解决跨域访问报错
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600"); //设置过期时间
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 支持HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // 支持HTTP 1.0. response.setHeader("Expires", "0");
chain.doFilter(req, resp);
}
第三种:nginx反向代理请求到后台同域处理
第四种:ajax的jsonp
第五种:vue.router的api域对象
8.抽象类和接口的区别
接口中,属性都是默认public static final修饰的
接口和抽象类的区别:
(1)抽象类可以有构造方法,接口中不能有构造方法。
(2)抽象类中可以有普通成员变量,接口中没有普通成员变量
(3)抽象类中可以包含静态方法,接口中不能包含静态方法
(4) 一个类可以实现多个接口,但只能继承一个抽象类。
(5)接口可以被多重实现,抽象类只能被单一继承
(6)如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法
接口和抽象类的相同点:
(1) 都可以被继承
(2) 都不能被实例化
(3) 都可以包含方法声明
(4) 派生类必须实现未实现的方法
9.接口可以继承接口吗,抽象类可以继承接口吗,抽象类可以继承实体类吗?
接口可以继承接口,抽象类不可以继承接口,但可以实现接口。
抽象类可以继承实体类。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。
10. J2E常用的设计模式,什么是工厂模式?
工厂模式、工厂方法模式、单例模式、建造者模式、策略模式、代理模式、门面模式、装饰模式、观察者模式。工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
11. inner class和static inner class的区别
inner class:内部类。及定义在另一个类中的类。B是A的内部类。
内部类可以访问到该类所定义在的作用域中的数据,包括私有数据。
//若内部类被static修饰则可以直接new,若没有则需先new出外部类,再new内部类
//B b = new B()
//A.B b = new A().new B()
public class A{
class B{}
}
1、内部类中的变量和方法不能声明为静态的。
2、内部类实例化:B是A的内部类,实例化B:A.B b = new A().new B()。
3、内部类可以引用外部类的静态或者非静态属性及方法。
静态内部类:
1、静态内部类属性和方法可以声明为静态的或者非静态的。
2、实例化静态内部类:B是A的静态内部类,A.B b = new A.B()。
3、静态内部类只能引用外部类的静态的属性及方法。
12.Object类
object类是所有java类的父类,是java类层中的最高层。类都是继承与Object类,自定义的类也是继承于Object类,所以在定义类的时候省略了extends Object关键字。
常用方法:
getClass()、toString()、equals()、clone()、hashCode()、wait()、notify()、notifyAll()
13.什么是序列化?反序列化?
- 序列化:把对象转换为字节序列的过程称为对象的序列化。(将对象的状态信息转换为可以存储或传输的形式的过程)
- 反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
14.关于finlly执行的顺序
1、finally块一定会执行,无论是否try…catch。
2、finally前有return,会先执行return语句,并保存下来,再执行finally块,最后return。
3、finally前有return、finally块中也有return,先执行前面的return,保存下来,再执行finally的return,覆盖之前的结果,并返回。