文章预览
- 测试题01
- 测试题02
- 1. char 和 varchar 的区别是什么?
- 2. Array 和 ArrayList 有何区别?
- 3. ArrayList 和 Vector 的区别是什么?
- 4. ArrayList 和 LinkedList 的区别是什么?
- 5. CSS中margin、padding的作用、以及单参、双参、四参数在方向上的顺序
- 6. java.sql.Date和java.util.Date的联系和区别
- 7. http 响应码 401和 403 代表的是什么?
- 8. PreparedStatement比Statement有什么优势?
- 9. 从表 login 中选出 name 字段包含 admin 的前 10 条结果所有信息的 sql 语句
- 测试题03
- 测试题04
- 测试题05
- 测试题06
- 测试题07
- 测试题08
- 测试题09
- 测试题10
- 1. MyBatis中collection和assosication区别?
- 2. 什么是MyBatis的一级缓存和二级缓存?
- 3. JVM中类的加载过程是怎么样的?
- 4. 什么是双亲委派模型?
- 5. Lock锁的使用
- 6. short s1 = 1;s1 = s1 + 1;报错吗?short s1 = 1;s1 += 1,报错吗?
- 7. java中this和super的区别
- 8. jsp动态include和及静态include有什么区别?
- 9. List l1 = new ArrayList();List l2 = new ArrayList();System.out.println(l1.getClass() == l2.getClass());输出是什么?
- 10. SpringMVC的工作流
- 测试题11
- 测试题12
- 测试题13
- 测试题14
- 测试题15
- 测试题16
- 测试题17
- 测试题18
- 测试题19
测试题01
1. jsp有哪些内置对象?作用分别是什么
内置对象 | 对应Servlet类 | 作用 |
---|---|---|
request | javax.servlet.http.HttpServletRequest | 客户端的请求信息:Http协议头信息、Cookie、请求参数等 |
response | javax.servlet.http.HttpServletResponse | 用于服务器响应客户端请求返回数据 |
pageContext | javax.servlet.jsp.PageContext | 页面的上下文 |
session | javax.servlet.http.HttpSession | 客户端与服务器之间的会话 |
application | javax.servlet.ServletContext | 用于获取服务器应用生命周期的信息 |
out | javax.servlet.jsp.JspWriter | 用于服务器传输内容到客户端的输出流 |
config | javax.servlet.ServletConfig | 初始化时,JSP引擎向JSP页面传递的信息 |
page | java.lang.Object | 指向JSP页面本身 |
exception | java.lang.Throwable | 页面发生异常,产生的异常对象 |
2. 说一下jsp的4种作用域
- 所谓“作用域”就是“信息共享的范围”,也就是说一个信息能够在多大的范围内有效。4个JSP内置对象作用域分别为:application、session、request、page(作用范围依次减小)
名称 | 作用域 |
---|---|
application | 在所有的应用程序中有效 |
session | 在当前会话中有效 |
request | 在当前请求中有效 |
page | 在当前页面有效 |
- Web交互的最基本单位为HTTP请求。每个用户从进入网站到离开网站这段过程称为一次HTTP会话,一个服务器的运行过程中会有多个用户访问,就是多个HTTP会话。
2.1 application 作用域
- 如果把变量放到application里,就说明它的作用域是application,它的有效范围是整个应用。
- 整个应用是指从应用启动,到应用结束。我们没有说“从服务器启动,到服务器关闭”,是因为一个服务器可能部署多个应用,当然,你关闭了服务器,就会把上面所有的应用都关闭了。
- application作用域里的变量,他们的存活时间是最长的,如果不进行手工删除,它们会一直可以使用。
- application 作用域上的信息传递是通过ServletContext实现的,它提供的主要方法如下:
Object getAttribute(String name) //从application中获取信息
void setAttribute(String name,Object value) //向application 作用域中设置信息
2.2 session 作用域
- session 作用域比较容易理解,同一浏览器对服务器进行多次访问,在这多次访问之间传递信息,就是session作用域的体现。如果把变量放到session里,就说明它的作用域是session,它的有效范围是当前会话。
- 所谓当前会话,就是指用户打开浏览器开始,到用户关闭浏览器之间的过程。
- 这个过程可能包含多个请求响应。也就是说,只要用户不关闭浏览器,服务器就有办法知道这些请求是一个人发起的,整个过程被称为一次会话(session),而放到会话中的变量就可以在当前会话的所有请求里使用。
- session 是通过HTTPSession接口实现,它提供的主要方法如下:
Object HTTPSession.getAttribute(String name) //从设施死你中获取信息
void HttpSession.setAttribute(String name,Object value) //向session中保存信息
HttpSession HttpServletRequest.getSession() //获取当前请求所在的session的对象 - session的开始时刻比较容易判断,它从浏览器发出第一个HTTP请求即可认为会话开始,但结束时刻就不好判断了,因为浏览器关闭时并不会通知服务器,所以只能通过如下这种方法判断:如果一定时间内客户端没有反应,则认为会话结束。Tomcat的默认值为120分钟,但这个值可以通过HttpSession的setMaxInactiveInterval()方法来设置:
void setMaxInactiveInterval(int interval)
如果想主动让会话结束,例如用户单击“注销”按钮的时候,可以使用HttpSession 的invalidate() 方法,用于强制结束当前session:void invalidate()
2.3 request 作用域
-
一个Http请求的处理可能需要多个Servlet合作,而这几个Servlet之间可以通过某种方式传递信息,但这个信息在请求结束后就无效了。request里的变量可以跨越forward前后的两页,但是只要刷新页面,它们就重新计算了。
-
如果把变量放到request里,就说明它的作用域是request,它的有效范围是当前请求周期。
-
所谓请求周期,就是值指从http请求发起,到服务器处理结束,返回响应的整个过程。在这个过程中可能使用forward的方式跳转了多个jsp页面,在这些页面里你都可以使用这个变量。
-
Servlet之间的信息共享是通过HttpServletRequest接口的两个方法来实现的:
void setAttribute(String name, Object value) //将对象value以name为名称保存到request作用域中。Object getAttribute(String name) //从request作用域中取得指定名字的信息。
-
JSP中的doGet()、doPost()方法的第一个参数就是HttpServletRequest对象,使用这个对象的 setAttribute()方法即可传递信息。那么在设置好信息之后,要通过何种方式将信息传给其他的Servlet呢?这就要用到RequestDispatcher接口的forward()方法,通过它将请求转发给其他Servlet。
RequestDispatcher ServletContext.getRequestDispatcher(String path) //取得Dispatcher以便转发,path为转发的目的Servlet。
void RequestDispatcher.forward(ServletRequest request, ServletResponse response)//将request和response转发 -
因此,只需要在当前Servlet中先通过setAttribute()方法设置相应的属性,然后使用forword()方法进行跳转,最后在跳转到的Servlet通过使用getAttribute()方法即可实现信息传递。
-
注意:
转发不是重定向,转发是在Web应用内部进行的。
转发对浏览器是透明的,也就是说,无论在服务器上如何转发,浏览器地址栏中显示的仍然是最初那个Servlet的地址。
2.4 page 作用域
- page对象的作用范围仅限在用户请求的当前页面,对于page对象的引用将在响应返回给客户端之后被释放,或者在请求被转发到其他地方后被释放。
- page里的变量只要页面跳转了。它们就销毁了。
- 如果把变量放pageContext里,就说明它的作用域是page,它的有效范围只在当前jsp页面里。从把变量放到pageContext开始,到jsp页面结束,你都可以用这个变量。
- request和page的生命周期都是短暂的,它们之间的区别:一个request可以包含多个page夜(include、forward及filter)
3. Maven的三个构建生命周期是什么?
- Maven 的一个核心理念,Build Lifecycle,构建生命周期,明确地定义了一个项目构建跟发布的过程。
- Maven有三个内建的构建的生命周期:default,clean和site
default:项目部署的处理
clean:项目清理的处理
site:项目站点文档创建的处理
-
构建生命周期都由不同的阶段(Phase)构成
例如:default 生命周期由以下阶段构成:
validate:验证项目是否正确且所有必须信息是可用的
compile:编译项目源码
test:使用合适的测试框架对编译好的源码尽心测试,这些测试不应要求源码被打包或部署
package:根据指定的格式打包编译好的源码,如JAP
verify:对集成测试的结果进行检查,以保证质量达标
install:安装打包的项目到本地仓库,以供其他项目使用
deploy:在构建环境中完成,将最后的包复制到远程仓库,以便与其他开发人员和项目共享 -
为了完成default生命周期,这些阶段(包括其他未在上面罗列的生命周期阶段)将被按顺序地执行。
-
命令行调用:在开发环境中,使用 mvn install 、mvn clean deploy等命令进行构建,安装工程到本地仓库
4. #{}和${}的区别是什么?
- #{} ?占位符
select * from user where username=#{name}
select * from user where username=? -
字
符
串
拼
接
s
e
l
e
c
t
∗
f
r
o
m
u
s
e
r
w
h
e
r
e
u
s
e
r
n
a
m
e
=
′
{} 字符串拼接 select * from user where username='
字符串拼接select∗fromuserwhereusername=′{name}’
PreparedStatement/Statement
5. jQuery中的常用选择器有哪些,至少5种
1. ID选择器 #id
描述:根据给定的id匹配一个元素, 返回单个元素(注:在网页中,id名称不能重复)
示例:$("#test") 选取 id 为 test 的元素
2. 类选择器 .class
描述:根据给定的类名匹配元素,返回元素集合
示例:$(".test") 选取所有class为test的元素
3. 元素选择器 element
描述:根据给定的元素名匹配元素,返回元素集合
示例:$("p") 选取所有的<p>元素
4. *
描述:匹配所有元素,返回元素集合
示例:$("*") 选取所有的元素
5. selector1,selector2,...,selectorN
描述:将每个选择器匹配到的元素合并后一起返回,返回合并后的元素集合
示例:$("p,span,p.myClass") 选取所有<p>,<span>和class为myClass的<p>标签的元素集合
6. Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
id可以重复
7. String s1 = “123”;这个语句有几个对象产生?
一个对象产生
7.1 String s2 = new String(“123”),又创建了几个对象?两个(两个语句)
s1 == s2 false
String s3 = “123”
s1 == s3 true
String s4 = new String(“123”);
s2 == s4 false
8. Servlet的生命周期
构造对象—>init->service->doGet/doPost->destroy
9. Maven 的常用命令
clean :清理
compile:编译
test:测试
package:打包
install:安装
deploy:部署
10. maven 常见的依赖范围有哪些?
包名:公司域名.项目名.模块名称
com.fy.myshop.user.controller
<groupId>com.fy</groupId>
<artifactId>myshop</artifactId>
<version>0.0.1.SNAPTSHOT</version>
<scope>compile</scope>
maven的依赖范围包括: compile,provide,runtime,test,system。
compile:表示编译范围,指A在编译时依赖B,该范围为默认依赖范围。编译范围的依赖会用在编译,测试,运行,由于运行时需要,所以编译范围的依赖会被打包。
provide:provide依赖只有当jdk或者一个容器已提供该依赖之后才使用。provide依赖在编译和测试时需要,在运行时不需要。例如:servlet api被Tomcat容器提供了。
runtime:runtime依赖在运行和测试系统时需要,但在编译时不需要。例如:jdbc的驱动包。由于运行时需要,所以runtime范围的依赖会被打包。
test:test范围依赖在编译和运行时都不需要,只在测试编译和测试运行时需要。例如:Junit。由于运行时不需要,所以test范围依赖不会被打包。
system:system范围依赖与provide类似,但是必须显示的提供一个对于本地系统中jar文件的路径。一般不推荐使用。
测试题02
1. char 和 varchar 的区别是什么?
- char 的长度是固定的,而varchar2的长度是可以变化的, 比如,存储字符串“abc",对于char (10),表示你存储的字符将占10个字节(包括7个空字符),而同样的varchar2 (10)则只占用3个字节的长度,10只是最大值,当你存储的字符小于10时,按实际长度存储。
- char的效率比varchar2的效率稍高。
- 目前varchar是varchar2的同义词。工业标准的varchar类型可以存储空字符串,但是oracle不这样做,尽管它保留以后这样做的权利。Oracle自己开发了一个数据类型varchar2,这个类型不是一个标准的varchar,它将在数据库中varchar列可以存储空字符串的特性改为存储NULL值。如果你想有向后兼容的能力,Oracle建议使用varchar2而不是varchar。
- 何时该用char,何时该用varchar2?
char与varchar2是一对矛盾的统一体,两者是互补的关系.
VARCHAR2比CHAR节省空间,在效率上比char会稍微差一些,即要想获得效率,就必须牺牲一定的空间,这也就是我们在数据库设计上常说的‘以空间换效率’。
varchar2虽然比char节省空间,但是如果一个varchar2列经常被修改,而且每次被修改的数据的长度不同,这会引起‘行迁移’(Row Migration)现象,而这造成多余的I/O,是数据库设计和调整中要尽力避免的,在这种情况下用char代替varchar2会更好一些。
2. Array 和 ArrayList 有何区别?
- Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
- Array大小是固定的,ArrayList的大小是动态变化的。
- ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
- 对于基本类型数据,ArrayList 使用自动装箱来减少编码工作量;而当处理固定大小的基本数据类型的时候,这种方式相对比较慢,这时候应该使用Array。
3. ArrayList 和 Vector 的区别是什么?
ArrayList与Vector的区别主要包括两个方面:.
(1)同步性:
- Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的。
- 如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。
(2)数据增长:
- ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector默认增长为原来两倍,而ArrayList的增长策略在文档中没有明确规定(从源代码看到的是增长为原来的1.5倍)。
- ArrayList与Vector都可以设置初始的空间大小,Vector还可以设置增长的空间大小,而ArrayList没有提供设置增长空间的方法。
- 总结:即Vector增长原来的一倍,ArrayList增加原来的0.5倍。
4. ArrayList 和 LinkedList 的区别是什么?
LinkedList :底层是双向链表,删除和修改快 O(n)
ArrayList:查询快 O(1)
5. CSS中margin、padding的作用、以及单参、双参、四参数在方向上的顺序
- margin:5px 上下左右 5px
- margin:5px 6px; 上下 5px 左右6px
- margin:5px 6px 10px; 上5px 左右6px 下10px
- margin:5px 6px 10px 20px; 上 5px 右6px 下10px 左20px
6. java.sql.Date和java.util.Date的联系和区别
- java.util.Date 是 java.sql.Date 的父类(注意拼写)
- 前者是常用的表示时间的类,我们通常格式化或者得到当前时间都是用它,后者之后在读写数据库的时候用,因为PreparedStament的setDate()的第2参数和ResultSet的getDate()方法的第2个参数都是java.sql.Date 转换是:
java.sql.Date date=new Java.sql.Date();
java.util.Date d=new java.util.Date (date.getTime());
反过来是一样的 - 继承关系:java.lang.Object --》 java.util.Date --》 java.sql.Date,具体的转换关系就是java.util.Date d=new java.util.Date (new Java.sql.Date());
- sql.date,一般是在数据库的时间字段,util.date一般是日常日期字段,java.sql.Date主要是用于sql中的,而java.util.Date用语一般的环境下都可以。
7. http 响应码 401和 403 代表的是什么?
401:未授权
403:禁止
404:文件找不到
503:服务器内部错误
200:成功
302:重定向
8. PreparedStatement比Statement有什么优势?
PreparedStatement extends Statement
采用占位符,防止sql注入
性能高
9. 从表 login 中选出 name 字段包含 admin 的前 10 条结果所有信息的 sql 语句
select * from login where name like ‘%admin%’ limit 0,10
测试题03
1. Spring 是什么?
-
Spring是一个项目管理框架,同时也是一套Java EE解决方案。
-
Spring是众多优秀设计模式的组合(工厂、单例、代理、适配器、包装器、观察者、模板、策略)。
-
Spring并未替代现有框架产品,而是将众多框架进行有机整合,简化企业级开发,俗称"胶水框架"。
官方网站:https://spring.io/
下载地址:http://repo.spring.io/release/org/springframework/spring/
2. 谈谈对Spring 的Ioc 和 DI 理解
- Inverse Of Controll:控制反转
反转了依赖关系的满足方式,由之前的自己创建依赖对象,变为由工厂推送。(变主动为被动,即反转)
解决了具有依赖关系的组件之间的强耦合,使得项目形态更加稳健 - DI(Dependency Injection)依赖注入 :在Spring创建对象的同时,为其属性赋值,称之为依赖注入。
3. Spring中Bean的注入方式有哪些?
set注入
构造注入
自动注入
4. 如何在Spring里注入集合?
list <list><value></value></list>
set <set></set>
map <map><entry key="" value=""/></map>
properties <props><prop></prop></props>
5. 解释一下Spring Bean的自动注入式什么样的?
byName
byType
6. AOP 有哪些实现方式?
动态代理:jdk + cglib
7. FactoryBean中有哪些抽象方法,分别含义是什么?
- FactoryBean创建复杂对象:
Connection
Class.forName("驱动名")
Connection conn = DriverManager.getConnection(url, username, password);
作用:让Spring可以创建复杂对象、或者无法直接通过反射创建的对象。
- 实现FactoryBean接口
- 注意:isSingleton方法的返回值,需根据所创建对象的特点决定返回true/false。
- 例如:Connection 不应该被多个用户共享,返回false。
- 例如:SqlSessionFactory 重量级资源,不该过多创建,返回true。
8. 什么是 Aspect?
切面(Aspect):由切点和通知组成,将横切逻辑织入切面所指定的连接点中。
9. 什么是 AOP?
-
概念:AOP(Aspect Oriented Programming),即面向切面编程,利用一种称为"横切"的技术,剖开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
-
AOP开发术语:
-
连接点(Joinpoint):连接点是程序类中客观存在的方法,可被Spring拦截并切入内容。
-
切入点(Pointcut):被Spring切入连接点。
-
通知、增强(Advice):可以为切入点添加额外功能,分为:前置通知、后置通知、异常通知、环绕通知等。
-
目标对象(Target):代理的目标对象
-
引介(Introduction):一种特殊的增强,可在运行期为类动态添加Field和Method。
-
织入(Weaving):把通知应用到具体的类,进而创建新的代理类的过程。
-
代理(Proxy):被AOP织入通知后,产生的结果类。
-
切面(Aspect):由切点和通知组成,将横切逻辑织入切面所指定的连接点中。
10. 有哪些类型的通知(Advice)?
前置通知:MethodBeforeAdvice://在业务方法执行前执行
最终通知:AfterAdvice //不管业务方法是否有异常,都会执行的通知
后置通知:AfterReturningAdvice //有异常不执行,方法会因异常而结束,无返回值
异常通知:ThrowsAdvice //目标对象执行出现异常才会执行的通知
环绕通知:MethodInterceptor//环绕通知
测试题04
1. 数据库的隔离级别有哪些?
isolation
隔离级别
名称 | 描述 |
---|---|
default | (默认值)(采用数据库的默认的设置) (建议) |
read-uncommited | 读未提交 |
read-commited | 读提交 (Oracle数据库默认的隔离级别) |
repeatable-read | 可重复读 (MySQL数据库默认的隔离级别) |
serialized-read | 序列化读 |
隔离级别由低到高为:read-uncommited < read-commited < repeatable-read < serialized-read
2. 什么是Dirty Read、Non-repeatable Read、Phantom Read?
问题 | 描述 |
---|---|
脏读 (Dirty Read) | 一个事务读取到另一个事务还未提交的数据。大于等于 read-commited 可防止 |
不可重复读(Non-repeatable Read) | 一个事务内多次读取一行数据的相同内容,其结果不一致。大于等于 repeatable-read 可防止 |
幻读(Phantom Read) | 一个事务内多次读取一张表中的相同内容,其结果不一致。serialized-read 可防止 |
- 脏读:读取了其他事务未提交的数据
- 不可重复读取:在一个事务中读取了另外一个事务中update之后的数据
- 幻读:在一个事务中读取了另外一个事务中insert,delete之后的数据
3. Cookie实现原理
Cookie数据存储在客户端的浏览器中,默认是放在浏览器的缓存中,所以关闭浏览器就被删除了,我们也可以设置Cookie的有效期,这个时候就会将Cookie数据存储在本地磁盘中,通过Http协议实现Cookie的传递。
4. AOP的实现原理?
动态代理:JDK、cglib
5. AOP一般应用在项目的哪些地方?
日志、事务、权限控制
6. Spring中Bean的生命周期
- 单例:启动创建对象 -》set注入 -》后置处理器的前置过程 -》init -》后置处理的后置过程 -》使用 -》destroy
- 多例:使用是创建对象 -》set注入 -》后置处理器的前置过程 -》init -》后置处理的后置过程 -》使用 -》JVM进行对象销毁
7. Spring框架中用到了哪些设计模式
工厂、单例、代理、模板模式
JdbcTemplate
8. java中事务的ACID是什么?
- 原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;
- 一致性(Consistent):事务结束后系统状态是一致的;
- 隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
- 持久性(Durable):事务完成后所做的改动都会被持久化。即使发生灾难性的失败,通过日志和同步备份可以在故障发生后重建数据。
9. 表单提交中,get和post区别
doGet:GET方法会把键值对追加在请求的URL后面,因为URL对字符数目有限制,进而限制了用在客户端请求的参数值的数目,并且请求中的参数值是可见的,因此,敏感信息不能用这种方式传递。
doPost:POST方法通过请求参数值放在请求体中克服GET方法的限制,因此,可以发送的参数的数目是无限制的。最后,通过POST请求传递的敏感信息对外部客户端是不可见的。
测试题05
1. @Resource和@Autowired区别?
- @Resource(这个注解属于J2EE的),默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
- @Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。
@Autowired默认按类型装配(这个注解是属于spring),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false) 。
2. 请写出Spring中基于xml的事务配置过程?
1.配置事务管理器
<bean id="tx" class="DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2.配置事务特性
<tx:advice id="txAdvice" transaction-manager="tx">
<tx:attributes>
<td:method name="delete*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
3.配置事务切面
<aop:config>
<aop:pointcut expression="" id="xx">
<aop:advisor adivce-ref="txAdvice" pointcut-ref='xx'>
</aop:config>
3. HashMap 与 HashTable 有什么区别?
- HashMap几乎可以等价于HashTable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键(key)和值(value),而HashTable则不行)。
- HashMap是非synchronized,而HashTable是synchronized,这意味着HashTable是线程安全的,多个线程可以共享一个HashTable;而如果没有正确的同步的话,多个线程是不能共享HashTable的。Java 5 提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
- 另外一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而HashTabled enumerator迭代器不是fail-fast的。所以当有其他线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出 ConcurrentModificationException 异常。但这并不是一个一定发生的行为,要看JVM,这条同样也是 Enumeration 和 Iterator 的区别。
- 由于HashTable是线程安全的,也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好于HashTable。
- HashMap 不能保证随着时间的推移Map中的元素次序是不变的。
4. 创建线程的方式有几种?
- 继承Thread类
- 实现Runnable
- 实现Callable
- 线程池
5. Java中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思? 重写和重载的区别?
重写:继承,
重载:同一类中定义多个同名的方法,参数列表要不同
6. 接口和抽象类的区别是什么?
-
抽象类:抽象类是指这个对象是什么
-
接口:接口是指这个对象能做什么
举例: 定义一个狗类(抽象类):哈士奇,金毛都属于狗类(实现类)狗:睡觉,拆家…可以定义一个接口,让实现类去实现接口
-
因此在Java语言中,一个类只能继承一个类(抽象类)(正如狗不可能同时是生物和非生物),但是接口可以多继承,一个类能够实现多个接口。
-
接口中的所有方法是抽象的(abstract修饰)而抽象类是声明方法而不去实现它的类。
-
接口可以多继承,抽象类单继承
-
接口定义方法,不能实现,而抽象类可以实现部分方法
-
接口中的基本数据类型为static,而抽象类不是。
注:
抽象类的功能远超过接口,但是,定义抽象类的代价比较高。因为高级语言来说(从实际设计出发也是),每个类只能继承一个类。在这个类中你必须继承或编写出其所有子类的所有共性。虽然接口在功能上会弱化许多,但是接口是针对一个动作的实现,而且一个类能够继承多个接口,在设计中难度会相对降低。
7. Java中Exception和Error有什么区别?
- Exception 和 Error 都是继承了 Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。
- Exception 和 Error 体现了 Java 平台设计者对不同异常情况的分类。
- Exception 是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理。
- Error 是指在正常情况下,不大可能出现的情况,绝大部分的 Error 都会导致程序(比如 JVM 自身)处于非正常的、不可恢复状态。
8. throw和throws有什么区别?
throw:产生异常
throws:抛出异常
9. sql语句分类是哪些?
DQL
DML
DDL
DCL
10. delete、drop、truncate区别?
delete删除数据
truncate删除数据,表内存结构
drop删除表,删库
测试题06
1. SpringMVC中常用的注解有哪些?
@RequestMapping
@ResponseBody
@PathVariable
@SessionAtrributes
@Controller/@Service/@Repository/@Component/@Autowired/@Resource/@Value
-
@Controller
Controller控制器是通过服务接口定义的提供访问应用程序的一种行为,它解释用户的输入,将其转换成一个模型然后将试图呈献给用户。 -
@RequestMapping
@RequestMapping 注解将URL映射到整个类或特定的处理方法上。 -
@PathVariable
可以使用 @PathVariable 注解方法参数并将其绑定到URI模板变量的值上。 -
@RequestParam
@RequestParam将请求的参数绑定到方法中的参数上 -
@RequestBody
@RequestBody是指方法参数应该被绑定到HTTP请求Body上。 -
@ResponseBody
@ResponseBody与@RequestBody类似,它的作用是将返回类型直接输入到HTTP response body中。 -
@ModelAttribute
@ModelAttribute可以作用在方法或方法参数上,当它作用在方法上时,标明该方法的目的是添加一个或多个模型属性(model attributes)。
2. 阐述JDBC操作数据库的步骤。
- 加载驱动
- 建立连接
- 创建申明对象
- 执行SQL
- 解析结果集
- 关闭
3. 线程的生命周期
-
新建状态(New):至今尚未启动的线程的状态。线程刚被创建,但尚未启动。如:Thread t = new MyThread();
-
就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;
-
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
-
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。
-
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
3.2 根据阻塞产生的原因不同,阻塞状态又可以分为三种:
-
等待阻塞—位于对象等待池中的阻塞状态(Blocked in object’s wait pool):当线程处于运行状态时,如果执行了某个对象的wait()方法,Java虚拟机就会把线程放到这个对象的等待池中,这涉及到“线程通信”的内容。
-
同步阻塞 --位于对象锁池中的阻塞状态(Blocked in object’s lock pool):当线程处于运行状态时,试图获得某个对象的同步锁时,如果该对象的同步锁已经被其他线程占用,Java虚拟机就会把这个线程放到这个对象的锁池中,这涉及到“线程同步”的内容。【线程在获取synchronized同步锁失败(因为锁被其它线程所占用)】
-
其他阻塞状态(Otherwise Blocked):当前线程执行了sleep()方法,或者调用了其他线程的join()方法,或者发出了I/O请求时,就会进入这个状态。线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
4. final finally finalize区别?
- final:常量、防止方法重写、防止被继承
- finally:异常 System.exit(0)/return
- finalize:Object 回收垃圾对象最后执行的方法
5. == 和 equals 的区别是什么?
== : 它的作用是判断两个对象的地址是不是相等的,即判断两个对象是不是同一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的是地址)
equals():它的作用是判断两个对象是否相等。但它一般有两种情况:
- 类没有覆盖 equals() 方法,则通过 equals() 比较该类的两个对象时,等价于通过 “==” 比较这两个对象。
- 类覆盖了equals() 方法。 一般,我们都覆盖 equals() 方法来比较两个对象的内容相等,若内容相等,则返回true(即,认为这两个对象相等)
6. 什么是 java 序列化?什么情况下需要序列化?
序列化:将 Java 对象转换成字节流的过程。
反序列化:将字节流转换成 Java 对象的过程。
当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。
序列化的实现:类实现 Serializable 接口,这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化。
注意事项:
- 某个类可以被序列化,则其子类也可以被序列化
- 声明为 static 和 transient 的成员变量,不能被序列化。
- static 成员变量是描述类级别的属性,transient 表示临时数据
- 反序列化读取序列化对象的顺序要保持一致
7. 获取数组长度?获取String长度?
length
length()
8. JVM概念
概念:JVM 是可运行 Java 代码的假想计算机 ,包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收,堆 和一个存储方法域。JVM 是运行在操作系统之上的,它与硬件没有直接的交互。
测试题07
1. 事务的四大特性
⑴ 原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
⑵ 一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态 变换到 另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
⑶ 隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。
⑷ 持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。
2. String能被继承吗?为什么?
不能,因为String是被final修饰,所以不能被继承
3. 两个对象的hashCode()相同,则equals()也一定为true,对吗?
不一定。解析如下:
3.1 hashCode()介绍
(1)hashCode()的作用是获取哈希值,也称为散列码,它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。
(2)散列表存储的是键值对(key-value),它的特点是根据“键”快速的检索出对应的“值”。这其中就利用到了散列码(可以快速找到所需要的对象)
3.2 为什么要有hashCode?
(1)以“HashSet如何检查重复”为例:HashSet 会先计算对象的 hashCode 值来判断对象加入的位置,同时也会与加入的对象的 hashCode 值作比较,如果没有相符的hashCode,HashSet会假设对象没有重复出现。但是如果发现有相同的 hashCode 值的对象,这时会调用equals() 方法来检查 hashCode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入成功。如果不同的话,就会重新散列到其他位置。这样就大大减少了equals的次数,相应就大大提高了执行速度。
(2)hashCode()与equals() 相关的规定
- 如果两个对象相等,则hashCode一定也是相同的
- 两个对象相等,对两个对象分别调用equals方法都返回true
- 两个对象有相同的hashCode值,它们不一定是相等的
- 因此,equals方法被覆盖过,则hashCode 方法也必须被覆盖
- hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
3.3 对象的相等与指向他们的引用相等,两者有什么不同?
对象的相等比较的是内存中存放的内容是否相等;而引用相等比较的是他们指向的内存地址是否相等。
4. ThreadLocal 用过么,用途是什么?
4.1 Threadlocal定义
Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的ThreadLocal变量。
4.2 Threadlocal的使用场景
-
就是当我们只想在本身的线程内使用的变量,可以用 ThreadLocal 来实现,并且这些变量是和线程的生命周期密切相关的,线程结束,变量也被销毁。所以说 ThreadLocal 不是为了解决线程间的共享变量问题的,如果是多线程都需要访问的数据,那需要用全局变量加同步机制。
例如:
(1)比如用来存储用户 Session。Session 的特性很适合 ThreadLocal ,因为 Session 之前当前会话周期内有效,会话结束便销毁。
(2)通过threadlocal 传递session,token等。
5. Java创建线程之后,直接调用start()方法和run()的区别
start():启动线程
run():线程执行
6. sleep() 和 wait() 有什么区别?
sleep():设置时间,不会释放锁
wait():唤醒,释放锁、notify/notifyall
7. forward和redirect的区别?
forward:内部转发
redirect:重定向
详细请看:https://blog.csdn.net/zhu_fangyuan/article/details/108820874
8. session和cookie有什么区别?
session:数据存储在服务端,各种数据类型,无大小限制,session默认基于cookie实现的
cookie:存储在客户端, 字符串,有大小限制
详细解析:https://blog.csdn.net/zhu_fangyuan/article/details/108628743
9. 说一下JSP的4种作用域?
page->request->session->application
- page:代表与一个页面相关的对象和属性。
- request:代表与客户端发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件;需要在页面显示的临时数据可以置于此作用域。
- session:代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的 session 中。
- application:代表与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域。
10. JSP和servlet有什么区别
-
JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类。
-
JSP 工作原理:
JSP页面在执行的时候都会被服务器端的JSP引擎转换为Servelet(.java),然后又由JSP引擎调用Java编译器,将Servelet(.java)编译为Class文件(.class),并由Java虚拟机(JVM)解释执行。下面验证这一点:
有一个JSP页面Test.jsp,在浏览器地址栏中输入http://localhost:8080/Test.jsp,将会出现执行结果。同时在%CATALINA_HOME%/work/Catalina/localhost下多出两个文件:_Test_jsp.java和_Test_jsp.class,他们分别就是Servelet和Class文件。 -
.Servlet的应用逻辑是在Java文件中,从Java代码中动态输出HTML,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。
测试题08
1. 数据库索引的作用及其索引原理
- 作用:提高查询效率 全表扫描
- 索引原理:采用某种数据结构存储索引,二叉树、平衡树、Hash表、BTree、B+Tree
- 主键索引(聚集索引)、唯一索引、联合索引、普通索引
create unique index 索引名(字段)
2. Eunumeration和Iterator接口的区别?
共同:都是接口,都可以对集合进行迭代
不同:
- Enumeration一般对Hashtable和Vector这种安全类型的集合进行迭代
- Iterator可以对实现了Collection接口的集合进行迭代
- Iterator支持fail-fast(Concurrent Modification Exception), 推荐使用Iterator
3. SQL语句的执行顺序
select 字段 from 表1 join 表2 on 链表条件 where 筛选条件 group by 分组字段 having 分组过滤 order by 排序字段 limit xxx
- from:得到一个虚拟表v1
- join之后的带一个笛卡尔表v2
- on 对v2表中的数据进行过滤 v3
- where 对v3中的数据进行筛选 v4
- select选择v4表中的对应字段 v5
- group by 对v5进行分组 v6
- having 对v6进行筛选 v7
- order by 对v7进行排序 v8
- limit 对v8进行限制 v9
4. 事务在什么时候会失效
A-》B
- 抛出了检测异常
- trycatch处理了
5. 什么是Spring的Bean循环依赖,如何解决?
A->B->A
<bean id="a" class="A">
<property name="b" ref=“b”>
</bean>
<bean id=“b” class="B">
<property name="a" ref="a">
</bean>
5.1 什么是循环依赖?
- 如何解决循环依赖-》set注入可以解决
- Bean的生命周期:容器启动-》构造对象-》set赋值-》后置处理的前置方法-》init-》后置处理的后置方法-》使用对象-》容器关闭-》销毁
6. mysql int(5)和int(11)的区别
- int(M) 中的M指示最大显示宽度,最大有效显示宽度是 255,且显示宽度与存储大小或类型包含的值的范围无关。
- 所以,int(5)与int(11)显示的宽度不同
7. js中json字符串转换集json对象、json对象转换json字符串
json对象-》string JSON.stringify(json对象)
string-》json对象 JSON.parse(json字符串)
8. for和for-each区别,哪个效率更快,原因?
for:通过下标
for-each:采用迭代器进行迭代
9. 常见的异常类有哪些,说出10个?
-
NullPointerException
-
CastClassException
-
RuntimeException
-
IOException
-
SQLException
-
SocketException
-
ClassNotFoundException
-
ArrayIndexOutOfException
-
NumberFormatException
-
FileNotFoundException
10. springMVC拦截器怎么配置
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/login"/>
<bean class="拦截器">
</mvc:interceptor>
</mvc:interceptors>
测试题09
数据库表的增删改查案例
学生表:| 学号 | 姓名 | 专业 | 班级 |
成绩表:| 学号 | 课程编号 | 成绩 |
-
查找显示成绩表中"学号"字段的全部数据,要求查询结果中不包含重复记录
select distinct 学号 from 成绩; -
在成绩表中,找出02号课程成绩中的最高分
select max(成绩) from 成绩表 where 课程编号=‘02’ ; -
在学生表中找出姓刘或姓李的学生
select *from 学生表 where 姓名 like ‘刘%’ or 姓名 like ‘李%’ -
查找01号课程成绩介于60与80之间的学生记录
select * from 学生表 where 学号 in (
select 学号 from 成绩 where 课程编号=01 and 成绩 between 60 and 80)select 学生表.* from 学生表 join 成绩表 on 学生表.学号=成绩表.学号
where 成绩表.课程编号=01 and 成绩表.成绩 between 60 and 80 -
把成绩表中课程编号='01’的所有学生记录按成绩从高到低排列显示出来
select * from 学生表 where 学号 in(
select 学号 from 成绩表 where 课程编号=01 order by 成绩 desc) -
统计每个课程的平级成绩
select 课程编号, avg(成绩) from 成绩表 group by 课程编号 -
找出挂科最多的课程
select 课程编号,count(*) 个数 from 成绩表 where 成绩 < 60 group by 课程编号 order by 个数 desc limit 0,1 -
在成绩表中,计算每个学生各门功课的总成绩和平均成绩,并按照总成绩降序排列
select sum(成绩) 总成绩,avg(成绩) 平均成绩 from 成绩表 group by 学号 order by 总成绩 desc; -
查询01号课程成绩进前三名的同学的课程编号,成绩
select 课程编号,成绩 from 成绩表where 课程编号=01 order by 成绩 desc limit 0, 3; -
将课程编号='01’中最高分的学员姓名显示出来
select 姓名 from 学生表 join 课程表 on 学生表.学号=成绩表.学号 where 课程编号=01 order by 成绩 desc limit 0,1select max_salary,
CASE
WHEN max_salary >15000 then ‘高工资’
WHEN max_salary >10000 then ‘一般水平’
else ‘低水平’
END 等级
from t_jobs
测试题10
1. MyBatis中collection和assosication区别?
collection是用来关联实体类的,assosication是用来关联集合的,
也就是平时的一对一(assocication),一对多(collection)
所以association是用于一对一和多对一,而collection是用于一对多的关系
2. 什么是MyBatis的一级缓存和二级缓存?
- 一级缓存
Mybatis的一级缓存是指Session缓存。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。
也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中;第二次以后是直接去缓存中取。
当执行SQL查询中间发生了增删改的操作,MyBatis会把SqlSession的缓存清空。
一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。
- 二级缓存
Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。
二级缓存是默认启用的(要生效需要对每个Mapper进行配置),如想取消,则可以通过Mybatis配置文件中的元素下的子元素来指定cacheEnabled为false。
3. JVM中类的加载过程是怎么样的?
- 加载(Loading)
- 连接(Linking)(验证(Verification)、准备(Preparation)、解析(Resolution))
- 初始化
- 使用
- 卸载
4. 什么是双亲委派模型?
当需要加载一个类的时候,子类加载器并不会马上去加载,而是依次去请求父类加载器加载,一直往上请求到最高类加载器:启动类加载器。
当启动类加载器加载不了的时候,依次往下让子类加载器进行加载。当达到最底下的时候,如果还是加载不到该类,就会出现ClassNotFound的情况。
好处:保证了程序的安全性。例子:比如我们重新写了一个String类,加载的时候并不会去加载到我们自己写的String类,因为当请求上到最高层的时候,启动类加载器发现自己能够加载String类,因此就不会加载到我们自己写的String类了。
5. Lock锁的使用
synchroniezed:关键词,通过JVM的底层实现,
锁的升级过程(无锁-》偏向锁-》轻量级锁-》重量级锁)
Lock:接口,通过代码实现锁的过程,状态+CAS+链表(ABC),公平锁和非公平锁,可中断锁
Lock lock = new ReentrantLock();//默认是非公平锁
try{
lock.lock();//上锁
//执行上锁的代码
}finally{
lock.unlock();//释放锁
}
6. short s1 = 1;s1 = s1 + 1;报错吗?short s1 = 1;s1 += 1,报错吗?
- 对于short s1 = 1;s1 = s1 + 1; 由于1 是int类型,因此,s1 + 1运算结果也是int()类型,需要强制转换类型才能赋值给short类型,所以,会报错。
- short s1 = 1; s1+=1;可以正常编译,因为s1+=1;相当于s1= (short)(s1+1);其中隐含有强制类型转换。
7. java中this和super的区别
(1)super:它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中的成员数据或函数),基类与派生类中有相同成员定义时如:super.变量名,super.成员函数名(实参)
(2)this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需要用this来指明成员变量名)
(3)super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其他构造方法。
(4)super()和this()均需放在构造方法内第一行。尽管可以使用this调用一个构造器,但却不能调用两个。
(5)this和super不能同时出现在一个构造方法中,因为this必然会调用其他的构造函数,其他的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
(6)this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
(7)从本质上讲,this是一个指向本对象的指针,然而super是一个Java关键字。
8. jsp动态include和及静态include有什么区别?
静态包含:<%@ include file=“文件”%>
动态包含:<jsp:include page=“文件” />
9. List l1 = new ArrayList();List l2 = new ArrayList();System.out.println(l1.getClass() == l2.getClass());输出是什么?
true
原因:泛型擦除,在程序运行中是没有泛型类型
10. SpringMVC的工作流
测试题11
1. InnoDB和MyISAM的区别
InnoDB:支持事务、主外键,效率要低,(B+Tree)索引结构不同(索引和数据在一起)
MyISAM:都不支持,效率高(索引和数据是分开)
2. 使用synchronized修饰静态方法和非静态方法有什么区别
- 类文件
- 对象
3. 高并发下,如何做到安全的修改同一行数据
乐观锁:版本号 v 1
悲观锁: select *from 表 where 条件 for update
4. int和Integer有什么区别
地址:https://blog.csdn.net/zhu_fangyuan/article/details/108545790
5. 简述synchronized 和java.util.concurrent.locks.Lock的异同
区别:
- Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
- synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
- Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
- 通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
- Lock可以提高多个线程进行读操作的效率。
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。- synchronized实现的机理依赖于软件层面上的JVM,synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。
- ReentantLock继承接口Lock并实现了接口中定义的方法,除了能完成synchronized所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等避免多线程死锁的方法。
- 尽管Java实现的锁机制有很多种,并且有些锁机制性能也比synchronized高,但还是强烈推荐在多线程应用程序中使用该关键字,因为实现方便,后续工作由JVM来完成,可靠性高。只有在确定锁机制是当前多线程程序的性能瓶颈时,才考虑使用其他机制,如ReentrantLock等。
- ReentrantLock通过方法lock()与unlock()来进行加锁与解锁操作,与synchronized会被JVM自动解锁机制不同,ReentrantLock加锁后需要手动进行解锁。为了避免程序出现异常而无法正常解锁的情况,使用ReentrantLock必须在finally控制块中进行解锁操作。
6. 创建一个类的类对象有哪些方式
- java.lang.Class
- 类.class
- 对象.getClass();
- Class.forName(“类全名”)
7. 什么是CAS?
-
CAS是compare and swap的缩写,即我们所说的比较交换。cas是一种基于锁的操作,而且是乐观锁。在java中锁分为乐观锁和悲观锁。悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加version来获取数据,性能较悲观锁有很大的提高。
-
CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。CAS是通过无限循环来获取数据的,若果在第一轮循环中,a线程获取地址里面的值被b线程修改了,那么a线程需要自旋,到下次循环才有可能机会执行。
8. 类加载器工作机制
加载-》连接(验证-》准备-》解析)-》初始化-》使用-》卸载
9. Java 中,Comparator 与Comparable 有什么不同?
-
Comparable和Comparator都是用来实现集合中元素的比较、排序的。
Comparable是在集合内部定义的方法实现的排序,位于java.lang下。
Comparator是在集合外部实现的排序,位于java.util下。 -
Comparable是一个对象本身就已经支持自比较所需要实现的接口,如String、Integer自己就实现了Comparable接口,可完成比较大小操作。自定义类要在加入list容器中后能够排序,也可以实现Comparable接口,在用Collections类的sort方法排序时若不指定Comparator,那就以自然顺序排序。所谓自然顺序就是实现Comparable接口设定的排序方式。
-
Comparator是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足要求时,可写一个比较器来完成两个对象之间大小的比较。Comparator体现了一种策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。
-
总而言之Comparable是自已完成比较,Comparator是外部程序实现比较。
10. 请说明一下eden区和survial区的含义以及工作原理?
-
目前主流的虚拟机实现都采用了分代收集的思想,把整个堆区划分为新生代和老年代;新生代又被划分成Eden 空间、 From Survivor 和 To Survivor 三块区域。
-
我们把Eden : From Survivor : To Survivor 空间大小设成 8 : 1 : 1 ,对象总是在 Eden 区出生, From Survivor 保存当前的幸存对象, To Survivor 为空。
-
一次 gc 发生后:
1)Eden 区活着的对象 + From Survivor 存储的对象被复制到 To Survivor ;
2)清空 Eden 和 From Survivor ;
3)颠倒 From Survivor 和 To Survivor 的逻辑关系: From 变 To , To 变 From 。可以看出,只有在 Eden 空间快满的时候才会触发 Minor GC 。而 Eden 空间占新生代的绝大部分,所以 Minor GC 的频率得以降低。当然,使用两个 Survivor 这种方式我们也付出了一定的代价,如 10% 的空间浪费、复制对象的开销等。
测试题12
1. Ajax的状态码有哪些?
-
readyState 属性表示Ajax请求的当前状态。它的值用数字代表。
0 代表未初始化。 还没有调用 open 方法
1 代表正在加载。 open 方法已被调用,但 send 方法还没有被调用
2 代表已加载完毕。send 已被调用。请求已经开始
3 代表交互中。服务器正在发送响应
4 代表完成。响应发送完毕
-
常用状态码(status)及其含义:
404 没找到页面(not found)
403 禁止访问(forbidden)
500 内部服务器出错(internal service error)
200 一切正常(ok)
304 没有被修改(not modified)(服务器返回304状态,表示源文件没有被修改 )
2. 写一个安全的单例模式?
3. 线程池有哪些?
-
newCachedThreadPool创建一个可缓存线程池程
-
newFixedThreadPool 创建一个定长线程池
-
newScheduledThreadPool 创建一个定长线程池
-
newSingleThreadExecutor 创建一个单线程化的线程池
4. 两个对象的hashCode()相同,则equals()也一定为true,对吗?
不一定。解析如下:
4.1 hashCode()介绍
(1)hashCode()的作用是获取哈希值,也称为散列码,它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。
(2)散列表存储的是键值对(key-value),它的特点是根据“键”快速的检索出对应的“值”。这其中就利用到了散列码(可以快速找到所需要的对象)
4.2 为什么要有hashCode?
(1)以“HashSet如何检查重复”为例:HashSet 会先计算对象的 hashCode 值来判断对象加入的位置,同时也会与加入的对象的 hashCode 值作比较,如果没有相符的hashCode,HashSet会假设对象没有重复出现。但是如果发现有相同的 hashCode 值的对象,这时会调用equals() 方法来检查 hashCode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入成功。如果不同的话,就会重新散列到其他位置。这样就大大减少了equals的次数,相应就大大提高了执行速度。
(2)hashCode()与equals() 相关的规定
- 如果两个对象相等,则hashCode一定也是相同的
- 两个对象相等,对两个对象分别调用equals方法都返回true
- 两个对象有相同的hashCode值,它们不一定是相等的
- 因此,equals方法被覆盖过,则hashCode 方法也必须被覆盖
- hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
4.3 对象的相等与指向他们的引用相等,两者有什么不同?
- 对象的相等比较的是内存中存放的内容是否相等;
- 引用相等比较的是他们指向的内存地址是否相等。
5. Java中的Math.round(1.5)、Math. round(-1. 5)等于多少?
- Math.round(1.5)的返回值是2,Math.round(-1.5)的返回值是-1。
- 采用四舍五入的原理,在参数上加0.5然后做向下取整。
6. HTTP有哪些method?
-
HTTP1.0定义了三种请求方法: GET、POST 和 HEAD方法。
-
HTTP1.1新增了五种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
7. String、StringBuilder、StringBuffer区别?
地址:https://blog.csdn.net/zhu_fangyuan/article/details/108739935
8. String类的常用方法都有那些?
String类常用方法 | 用法 |
---|---|
indexOf() | 返回指定字符得索引 |
charAt() | 返回指定索引处得字符 |
repalce() | 字符串替换 |
trim() | 去除字符串两端的空白 |
split() | 分割字符串 返回分割后的字符串数组 |
getBytes() | 返回字符串的byte类型数组 |
length() | 返回字符串的长度 |
toLowerCase() | 字符串转小写 |
toUpperCase() | 字符串转大写 |
substring() | 截取字符串 |
equals() | 字符串比较 |
9. Collection和Collections有什么区别?
- Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
- Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作
10. 在Queue中poll()和 remove()有什么区别?
- remove():获取并移除此队列的头,如果此队列为空,则抛出NoSuchElementException异常
- poll():获取并移除此队列的头,如果此队列为空,则返回 null
测试题13
1. SpringMVC的执行流程
Dispatcher->HandlerMapping->HanderAdapter->Handler->ViewResolver->View
2. Integer a= 128 与 Integer b = 128相等吗?
不相等,两个不同的对象
3. Mybatis的一级、二级缓存
一级缓存
Mybatis的一级缓存是指Session缓存。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。
也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中;第二次以后是直接去缓存中取。当执行SQL查询中间发生了增删改的操作,MyBatis会把SqlSession的缓存清空。
一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。
二级缓存
- Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。
- 二级缓存是默认启用的(要生效需要对每个Mapper进行配置),如想取消,则可以通过Mybatis配置文件中的元素下的子元素来指定cacheEnabled为false。
4. 列举工作中常用的几个git命令?
git init
git add
git commit
git push
git pull
git clone
git checkout
git branch 分支名称
5. 提交时发生冲突,你能解释冲突是如何产生的吗?你是如何解决的?
-
冲突是如何产生的
我们都知道,Git的实现途径是1棵树。比如有一个节点树(point1),
我们基于point1进行开发,开发出了结点point2;
我们基于point1进行开发,开发出了结点point3;
如果我们在point2和point3内操作了同一类元素,那么势必会导致冲突的存在。 -
冲突是如何解决的?
解决冲突通常使用如下的步骤即可:
情况1 无冲突
先拉取远端的代码,更新本地代码。然后提交自己的更新代码即可。
情况2 有冲突
拉取远端代码。存在冲突,会报错。
此时我们需要将本地代码暂存起来 stash;
更新本地代码,将本地代码版本更新和远端的代码一致即可;
将暂存的代码合并到更新后的代码后,有冲突解决冲突(需要手动进行解决冲突);
提交解决冲突后的代码。
6. Git中如果代码出现bug,你们是如何解决的?
开启一个bug分支
7. 项目中常见的分支 有哪些?
master:主分支,对外发布
dev:开发分支
test:测试分支
bug:修复bug分支
feature:特性分支
hotfixes:热线分支
8. String a = “ab”; String b = “a” + “b”; a == b 是否相等,为什么?
相等,string 性能优化
String a =“a”+“b”+“c”+“d”;
9. volatile作用?
a、防止执行指令重排序
b、内存可见性
10. Java 中,Comparator 与Comparable 有什么不同?
- Comparable 接口用于定义对象的自然顺序,而 comparator 通常用于定义用户定制的顺序。Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。
- Comparable是在集合内部定义的方法实现的排序,位于java.lang下。
Comparator是在集合外部实现的排序,位于java.util下。
测试题14
1. CAS原理及作用
AtomicInteger
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
//var1:当前对象
//var2:原有内存值
//var4:需要自增的值
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);//获取当前内存值
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
if(var2 == var5){
var5 = var5+var4;
return true;
}
return false;
return var5;
}
CAS原理:获取旧的内存值V,获取当前内存值A, 只有当V==A,才将内存值修改成B,原子变量都是基于CAS实现的
AtomicInteger,AtomitLong
问题:ABA问题,通过版本号
A a -> b->a
B a->a->c
public class MyTest1 {
public static void main(String[] args) {
AtomicDemo demo = new AtomicDemo();
for(int i=0; i<8; i++){
new Thread(demo).start();
}
}
}
class AtomicDemo implements Runnable{
//private int num = 0;
private AtomicInteger num = new AtomicInteger(0);//原子变量
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(num.getAndIncrement());//原子操作
//int temp;
//temp = num;
//temp = temp + 1;
//num = temp
}
}
2. 如何实现Ajax的跨域?
- 用代理服务器代理
- 使用jsonp
- 服务端设置Request Header头中Access-Control-Allow-Origin为指定可获取数据的域名
3. String内部如何实现equals方法
- 首先是和自己比;
- 被比较的对象是否是String类型的;
- 再看它的长度是否相等;
- 比较它里面的每一个字符串;
4. ArrayList如何实现线程安全
- 使用synchronized关键字
- 使用Collections.synchronizedList();
假如你创建的代码如下:List<Map<String,Object>> data=new ArrayList<Map<String,Object>>();
那么为了解决这个线程安全问题你可以这么使用Collections.synchronizedList(),如:
List<Map<String,Object>> data=Collections.synchronizedList(new ArrayList<Map<String,Object>>());
5. 冒泡排序算法
//简单选择排序算法
private void selectSort(int[] datas){
int length = datas.length;
for(int i=0;i<length;i++){
int min = i;
for(int j=i+1;j<length;j++){
int a = datas[min];
int b = datas[j];
if(a>b){//这里为升序,如果要降序则直接这里改成小于即可
min = j;
}
}
int temp = datas[min];
datas[min] = datas[i];
datas[i] = temp;
Log.i("sort", Arrays.toString(datas)+" i:"+i);
}
}
//冒泡排序算法
private void bubbleSort(int[] datas) {
int length = datas.length;
boolean flag;
for (int i = 0; i < length - 1; i++) {
flag = false;//使用flag对冒泡排序进行优化
for (int j = 0; j < length - i-1; j++) {
if (datas[j] > datas[j+1]) {//这里为升序,如果要降序则直接这里改成小于即可
int temp = datas[j];
datas[j] = datas[j+1];
datas[j+1] = temp;
flag = true;
}
Log.i("sort", Arrays.toString(datas) + " j:" + j + " length-i:" + (length - i));
}
if(!flag){//如果这里flag为false,表示现在数据已经是有序的了,则可以直接退出for循环了
break;
}
}
}
6. Spring中事务在什么情况下回失效。
a、try,catch
b、抛出检测异常
c、数据库引擎MyISAM
7. 主键索引和普通索引的区别,为什么主键要比普通快?
数据库的引擎是Innodb
主键索引:索引的叶子节点中存储行数据
普通索引:索引的叶子节点存储的是主键值,存在二次索引过程
主键索引建议用自增
8. 什么是脏读、幻读、不可重复读?
问题 | 描述 |
---|---|
脏读 (Dirty Read) | 一个事务读取到另一个事务还未提交的数据。大于等于 read-commited 可防止 |
不可重复读(Non-repeatable Read) | 一个事务内多次读取一行数据的相同内容,其结果不一致。大于等于 repeatable-read 可防止 |
幻读(Phantom Read) | 一个事务内多次读取一张表中的相同内容,其结果不一致。serialized-read 可防止 |
9. 如何防止表单重复提交
1、JavaScript防止表单重复提交(主要用于网络延迟情况下用户点击多次submit按钮导致表单重复提交)
在jsp页面中,添加JavaScript代码来防止表单的重复提交。主要是针对在网络延迟情况下用户有时间点击多次submit按钮导致表单重复提交,使用javascript控制Form表单只能提交一次。
2、**将提交按钮设置为不可用,**让用户点击第一次提交之后,没有机会点击第二次提交按钮的机会。(也可以将提交按钮隐藏起来,在点击第一次之后,将提交按钮隐藏起来)
3、利用Session防止表单重复提交(主要用于表单提交之后,点击浏览器刷新按钮导致表单重复提交,以及点击浏览器返回按钮退回到表单页面后进行再次提交)
(1)表单页面由servlet程序(服务器端)生成,servlet为每次产生的表单页面分配一个唯一的随机标识号(Token令牌),并在FORM表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号。
(2)当用户提交FORM表单时,负责处理表单提交的serlvet得到表单提交的标识号,并与session中存储的标识号比较,如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。如果不一致,就是重复提交了,此时服务器端就可以不处理重复提交的表单了。
(3)服务器程序将拒绝用户提交的表单请求情况如下:
1):存储Session域中的表单唯一的标识号与表单提交的标识号不同
2):当前用户的Session中不存在表单标识号
3):用户提交的表单数据中没有标识号字段
(4)创建标识号
String token = TokenProccessor.getInstance().makeToken();
(5)在服务器端使用Session保存标识号
request.getSession().setAttribute(“token”,token);
(6)、在form表单中也就是JSP页面中,使用隐藏域来存储标识号(Token令牌)
10. 原生js ajax请求有几个步骤?分别是什么?
//第一步,创建XMLHttpRequest对象
var xmlHttp = new XMLHttpRequest();
function CommentAll() {
//第二步,注册回调函数
xmlHttp.onreadystatechange =callback1;
//{
// if (xmlHttp.readyState == 4)
// if (xmlHttp.status == 200) {
// var responseText = xmlHttp.responseText;
// }
//}
//第三步,配置请求信息,open(),get
//get请求下参数加在url后,.ashx?methodName = GetAllComment&str1=str1&str2=str2
xmlHttp.open("post", "/ashx/myzhuye/Detail.ashx?methodName=GetAllComment", true);
//post请求下需要配置请求头信息
//xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//第四步,发送请求,post请求下,要传递的参数放这
xmlHttp.send("methodName = GetAllComment&str1=str1&str2=str2");//"
}
//第五步,创建回调函数
function callback1() {
if (xmlHttp.readyState == 4)
if (xmlHttp.status == 200) {
//取得返回的数据
var data = xmlHttp.responseText;
//json字符串转为json格式
data = eval(data);
$.each(data,
function(i, v) {
alert(v);
});
}
}
//后台方法
private void GetAllComment(HttpContext context)
{
//Params可以取得get与post方式传递过来的值。
string methodName = context.Request.Params["methodName"];
//QueryString只能取得get方式传递过来的值。
string str1 = context.Request.Form["str1"];
//取得httpRequest传来的值,包括get与post方式
string str2 = context.Request["str2"];
List<string> comments = new List<string>();
comments.Add(methodName);
comments.Add(str1);
comments.Add(str2);
//ajax接受的是json类型,需要把返回的数据转给json格式
string commentsJson = new JavaScriptSerializer().Serialize(comments);
context.Response.Write(commentsJson);
}
测试题15
1. ArrayList和Vector的区别
区别:
ArrayList非安全,Vector安全
扩容ArrayList 1.5倍 Vector 2倍
2. List, Set, Map三个接口,存取元素时,各有什么特点?
List:有序
Set:无序
Map:key->value(key 不可以重复;value 可以重复)
3. Collection 和 Collections的区别
- Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
- Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作
4. HashMap的实现原理
数组+链表+红黑树
5. volatile关键字的作用?能否保证线程安全?
不能保证线程安全
- 保持可见性
禁止进行指令的重排序(volatile关键字能确保变量在线程中的操作不会被重排序而是按照代码中规定的顺序进行访问) 有序性
- 并不能保证原子性
在使用volatile关键字时要慎重,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作,当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,可以使用synchronized来代替volatile。
6. 高并发应该使用什么Map?
Hashtable
ConcurrentHashMap
7. 什么是乐观锁和悲观锁?
简单理解下悲观锁:当一个事务锁定了一些数据之后,只有当当前锁提交了事务,释放了锁,其他事务才能获得锁并执行操作。
乐观锁是首先假设数据冲突很少,只有在数据提交修改的时候才进行校验,如果冲突了则不会进行更新。
8. 数据库的三大范式
1NF:一个表中每个字段都是独立
2NF:表中的每一行数据都是唯一的,所有非主键字段都和主键字段关联,不能存在间接依赖
3NF:表中不能存在传递依赖
9. synchronized锁是公平锁还是非公平锁
非公平锁
10. 十进制数12的二进制表示应该是?
1100
测试题16
1. ConcurrentHashMap在JDK1.8之后结构做了哪些改进?
HashMap
Hashtable
CocurrentHashMap->分段锁segement(RetreenLock)->synchronized+cas+红黑色
改进一:取消segments字段,直接采用
transient volatile HashEntry<K,V> table
保存数据,采用table数组元素作为锁,从而实现了对每一行数据进行加锁,进一步减少并发冲突的概率。
改进二:将原先table数组+单向链表的数据结构,变更为table数组+单向链表+红黑树的结构。对于hash表来说,最核心的能力在于将key hash之后能均匀的分布在数组中。如果hash之后散列的很均匀,那么table数组中的每个队列长度主要为0或者1。但实际情况并非总是如此理想,虽然ConcurrentHashMap类默认的加载因子为0.75,但是在数据量过大或者运气不佳的情况下,还是会存在一些队列长度过长的情况,如果还是采用单向列表方式,那么查询某个节点的时间复杂度为O(n);因此,对于个数超过8(默认值)的列表,jdk1.8中采用了红黑树的结构,那么查询的时间复杂度可以降低到O(logN),可以改进性能。
2. Spring Bean作用域的有哪些?
singleton
prototype
request
session
application
3. Spring中Bean的注入方式有哪些?
set注入
构造注入
自动注入
4. 如何获取自动生成的(主)键值?
last_insert_id()
5. 了解过哪些JDK8的新特性,举例描述下相应的特性?
接口中定义Default和static
函数式接口@FunctionInterface
lambda表达式 ()->{}
stream流
日期时间
Optional
6. hashCode的作用?
-
Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。
-
要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一 次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它 就要调用1000次equals方法。这显然会大大降低效率。
-
于是,Java采用了哈希表的原理。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。
-
如果这个位置上没有元素,它就可以 直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了;不相同,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同hashcode的对象放到这个单链表上去,串在一起。
-
所以这里存在一个冲突解决的问题(很少出现)。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。
-
所以,Java对于eqauls方法和hashCode方法是这样规定的:
如果两个对象相等,那么它们的hashCode值一定要相等;
如果两个对象的hashCode相等,它们并不一定相等。 上面说的对象相等指的是用eqauls方法比较。
7. 深拷贝和浅拷贝区别
深拷贝和浅拷贝都是对象拷贝
- 深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
- 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。
8. JAVA遍历Map的方式有几种
for(String key :map.keySet()){
System.out.println(key+":"+map.get(key));
}
for(String val : map.values()){
System.out.println(val);
}
for(Map.Entry<String,String> e : map.entrySet()){
System.out.println(e.getKey()+":"+e.getValue());
}
Set<Map.Entry<String, String>> set = map.entrySet();
Iterator<Map.Entry<String, String>> iterator = set.iterator();
while(iterator.hasNext()){
Map.Entry<String, String> next = iterator.next();
System.out.println(next.getKey()+":"+next.getValue());
}
9. 怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?
String newStr = new String(str.getBytes(“GB2312”), “ISO-8859-1”);
10. forward 和 redirect 的区别?
(1). 从地址栏显示来说
- forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
- redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.
(2). 从数据共享来说
- forward:转发页面和转发到的页面可以共享request里面的数据.
- redirect:不能共享数据.
(3). 从运用地方来说
- forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
- redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.
(4). 从效率来说
- forward:高.
- redirect:低.
测试题17
1. Shiro认证和授权的流程?
主体-》SecurityManager-》认证器(Authentication)-》Realm实现具体认证过程
主体-》SecurityManager-》授权器(Authorization)-》Realm实现具体的授权过程
2. 传递一个集合作为参数给函数时,如何能确保函数将无法对其进行修改?
- final
- Collections.unmodifiableCollection(Collection);
- 如何修改集合则抛出UnsupportedOperationException
3. 哪一个List实现了最快插入?
LinkedList
4. Java的concurrent包中的有哪些API?
Lock
原子变量:AtomicInteger
ConcurrentHashMap
Executor
5. 怎么判断对象是否可以被回收?
- 可达性分析
- 引用计算
6. 一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?
InnoDB->内存->6
MyISAM->文件->8
7. AQS是什么?
AQS:AbstractQueuedSynchronizer
抽象队列同步器,实现锁机制(CAS+FIFO)
ReentrantLock
8. java的基础类型和字节大小
1. 基本数据类型(布尔)
类型 | 字节 | 取值范围 | 描述 |
---|---|---|---|
boolean | 1字节 | true/false | 仅可描述“真”或者“假” |
-
可直接赋值true/false
-
也可以直接赋值一个结果为true/false的表达式
boolean result = 3 > 2; //注:Java中的boolean不能参与算术运算
2. 基本数据类型(字符)
类型 | 字节 | 取值范围(无符号数) | 字符编码 |
---|---|---|---|
char | 2字节 | 0~65535 | Unicode字符集(万国码) |
-
char :character
1). 应额嗯对应的ASCCI编码,中文或者其他国家语言对应Unicode编码。
2). 每个字符都有对应的整数变现形式。
3). 赋值:char c1 = ‘A’; 或者 char c2 = 65; 或者 char c3 = ‘\u0041’;
-
Unicode 字符集支持ASCII编码(美国标准信息交换码)。
-
Unicode中每个字符都对应一个十进制整数,从而可以使用多种方式赋值。
-
字符赋值:char c1 = ‘A’;(通过’'描述字符赋值)
-
整数赋值:char c2 = 65;(通过十进制65在字符集中对应的字符赋值)
-
进制赋值:char c3 = ‘\u0041’;(通过十六进制数41在字符集中对应的字符赋值)
3. 转义字符
-
如果需要在程序中输出一个单引号字符,该如何完成?
-
package demo; public class TestChar { public static void main(String[] args) { char c = '\''; System.out.println(c); } }
转义字符 | 描述 |
---|---|
\n | 换行符 |
\t | 缩进(制表符) |
\\ | 反斜线 |
\’ | 单引号 |
\’’ | 双引号 |
class Demo {
public static void main(String[] args) {
char c1 = 'A';
char c2 = 'B';
char c3 = 67;
char c4 = '好';
//char c5 = "K";
/* Demo.java:12: 错误: 不兼容的类型: String无法转换为char
char c5 = "K";
^
1 个错误
*/
char c6 = '\u0041';
char c7 = '\'';//转义字符
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println((int)c4);
/*System.out.println(c5);
Demo.java:30: 错误: 找不到符号
System.out.println(c5);
^
符号: 变量 c5
位置: 类 Demo
1 个错误
*/
System.out.println(c6);
System.out.print("Hello\n");
System.out.print("world");
}
}
整数类型
类型 | 字节 | 取值范围(二进制) | 取值范围(十进制) |
---|---|---|---|
byte | 1字节 | -27~27-1 | -128~127 |
short | 2字节 | -215~215-1 | -32768~32767 |
int | 4字节 | -231~231-1 | -2147483648~2147483647 |
long | 8字节 | -263~263-1 | -9223372036854775808~9223372036854775807 |
小数/浮点数
类型 | 字节 | 负数取值范围 | |
---|---|---|---|
float | 4字节 | -3.4E+38~1.4E-45 | 1.4E-45~3.4E+38 |
double | 8字节 | -1.7E+3.8~-4.9E-324 | 4.9E-45~3.4E+38 |
9. CAS机制是什么,如何解决ABA问题。
ABA问题,简单描述就是存在一个变量值为A,第一个线程把变量值从A改成了B,第二个线程又把变量值从B改成了A,这样,后面的线程读取这个变量的时候就会以为变量值没有发生过任何变化。
- CAS概述
CAS:Compare and Swap,即比较再交换,它是一条CPU并发原语。
它的功能是判断内存某个位置的值是否为预期值,如果是,则更改为最新值,这个过程是原子的。
CAS并发原语体现在Java语言中的sun.misc.Unsafe类中的各个方法,调用Unsafe类中的CAS方法,JVM会帮我们实现CAS汇编指令,它是一种完全依赖于硬件的功能,通过它实现了原子操作,再次强调,由于CAS是一种系统原语,原语属于操作系统用语的范畴,是由若干条指令组成的,用于完成某个功能的一个过程,并且原语的执行是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题。
jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronzied同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。
对CAS的理解,CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
10. http1.0和http1.1有什么区别
长连接: 长连接(HTTP persistent connection ,也有翻译为持久连接),指数据传输完成了保持TCP连接不断开(不发RST包、不四次握手),等待在同域名下继续用这个通道传输数据;相反的就是短连接。
Host域
带宽优化
消息传递
缓存
测试题18
1 如何实现数组和 List 之间的转换
1.1 数组转List:使用Arrays.asList(array) 进行转换
1.2 List 转数组:使用自带的 toArray()方法
代码示例:
//list to array
List<String> list = new ArrayList<String>();
list.add("123");
list.add("456");
list.toArray();
//array to list
String[] array = new ArrayList<String>();
Arrays.asList(array);
2. 迭代器Iterator 是什么?
Iterator 提供遍历任何Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。
2.1 Iterator 怎么使用?有什么特点?
Iterator 使用代码如下:
List<String> list = new ArrayList();
Iterator<String> it = List.iterator();
while(it.hasNext()) {
String obj = it.next();
System.out.println(obj);
}
Iterator 的特点是只能单项遍历,但是更安全,因为它可以确保在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。
2.2 如何遍历边移除 Collection 中的元素?
边遍历边修改 Collection 的唯一正确方式是使用 Iterator.remove()方法,如下:
Iterator<Integer> it = list.iterator(); while(it.hasNext()){ //do something it.remove(); }
一种常见的的错误代码:
for(Integer i :list) { list.remove(i); }
运行以上错误代码会报 ConcurrentModificationException 异常。这是因为当使用 foreach(for(Integer i : list)) 语句时,会自动生成一个 Iterator 来遍历该 list,但同时该list 正在被 Iterator.remove()修改。Java一般不允许一个线程在遍历Collection 时另外一个线程修改它。
2.3 Iterator 和ListIterator 有什么区别?
- Iterator 可以遍历 Set 和 List 集合,而 ListIterator 只能遍历LIst。
- Iterator 只能单向遍历,而 ListIterator 可以上双向遍历(向前/向后遍历)
- ListIterator 实现 Iterator 接口,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
测试题19
1. 说一下 HashSet 的实现原理?
HashSet 是基于HashMap 实现的,HashSet的值存放于 HashMap 的 key 上,HashMap 的 value 统一为 PRESENT,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成,HashSet 不允许重复的值。
2. HashSet 如何检查重复?HashSet 是如何保证数据不可重复的?
- 向 HashSet 中add()添加元素时,判断元素是否存在的依据,不仅要比较hash值,同时还要结合equals 方法比较。
- HashSet() 中的 add() 方法会使用 HashMap 的 put() 方法。
- HashMap的 key 是唯一的,由源码可以看出 HashSet 添加进去的值就是作为 HashMap 的key,并且在HashMap 中如果 K/V 相同时,会用新的V覆盖掉旧的V,然后返回旧的V。所以不会重复(HashMap 比较 key 是否相同时先比较 hashcode 再比较 equals)。
HashSet 部分源码:
private static final Object PRESENT = new Object();
private transient HashMap<E,Object> map;
public HashSet() {
map = new HashMap<>();
}
public boolean = add(E e) {
return map.put(e,PRESENT) == null;
}
3. hashcode() 与 equals() 的相关规定:
- 如果两个对象相等,则hashCode一定也是相同的
- 两个对象相等,对两个equals方法返回为true
- 两个对象有相同的hashCode值,它们也不一定是相等的
- 综上,equals方法被覆盖过,则hashCode方法也必须被覆盖
- hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该class 的对象无论如何都不会相等(即使这两个对象指向形同的数据)。
4. == 与 equals 的区别
- == 是判断两个变量或者实例是不是指向同一个内存空间 equals 是判断两个变量或者实例所指向的内存空间的值是不是相同。
- == 是指对内存地址进行比较 equals()是对字符串的内容进行比较。
- == 指引用是否相同 equals 指的的是值是否相同
5. HashSet 与 HashMap 的区别
HashMap | HashSet |
---|---|
实现了Map接口 | 实现了set接口 |
存储键值对 | 仅存储对象 |
调用put()向map 中添加元素 | 调用 add() 方法向set中添加元素 |
HashMap 使用键(Key)计算 HashCode | HashSet使用成员对象来计算 hashCode 值,对于两个对象来说 hashCode 可能相同,所以 equals() 方法用来判断对象的相等性,如果两个对象不同的话,那么返回false |
HashMap 相对于HashSet较快,因为它是使用唯一的键获取对象 | HashSet 较 HashMap来说比较慢 |
6. HashMap 的实现原理
- HashMap 概述:HashMap 是基于哈希值的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
- HashMap的数据结构:在Java编程语言中,最基本的结构就是两种,一个数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个"链表散列"的数据结构,即数组和链表的结合体。
6.1 HashMap 基于Hash 算法实现的
- 当我们往 HashMap 中 put 元素时,利用 key 的hashCode 重新 hash 计算出当前对象的元素在数组中的下标。
- 存储时,如果出现 hash 值相同的key,此时有两种情况:(1)如果 key 相同,则覆盖原始值。(2)如果 key 不同(出现冲突),则将当前的 key-value 放入链表中。
- 获取时,直接找到 hash 值对应的下标,再进一步判断 key 是否相同,从而找到对应值。
- 理解了以上过程不难明白 HashMap 的实现是如何解决hash冲突的问题,核心就是使用了数组的存储方式,然后将冲突的key的对象放入链表中,一旦发生冲突就在链表中作进一步的对比。
- JDK1.8中对HashMap的实现做了优化,当链表中的节点数超过8个之后,该链表会转为红黑树来提高效率。