Java面试题
闲来无事从网上找了一些面试题来做,发现还是有些难度的。整理了一下,共享给大家。如果有错误的地方请指出。另外有些超出了我目前的学习范围(其实还是技术差,暂时接受不了。)就只是粘贴了一个连接。
面试题
MySQ5.7表innodb存储引擎(下面试题,除非特殊说明,均是)
1假设订单有三种状态:0已下单,1已支付,2已完成
业务需求,查询未完成的订单,哪个SQL更快呢?其中status订单状态有普通索引
//innodb先指向二级索引,再指向主键索引--查询具体数据。
//负向查询用不到索引,他是全表扫描
select * from order where status!=2
// or的新版本的能够用到索引,否则也是全表扫描explain可以查询到语句是否使用到了索引或者是全表扫描
select * from order where status=0 or status=1
//子查询,简单的子查询也是能用到索引,子查询尽量不要用,他在老版本中效率低。
//如果status没有索引,子查询会在老版本的数据库中,将全表数据扫描出来,再挑出来显示
select * from order where status IN (0,1)
//肯定能用到索引。
select * from order where status=0
union
select * from order where stauts=1
2假设有用户表user,表字段有username,pwd,我们建有(username,pwd)联合索引
那么以下语句哪些能命中索引
1 select * from user where username=? and pwd=?
2 select * from user where pwd=? and username=?
3 select * from user where pwd=?----》用不到索引,做前缀规则是必须前一个用到,后一个才能
4 select * from user where username like‘%小’----》模糊查询不以百分号开头才能用到索引
5select * from user where username like‘小%’----》模糊查询不以百分号开头才能用到索引
//只能使用到一个索引,因为and前面链接有模糊查询
6select * from user where username like‘小%’and pwd=?
3 Spring框架注入都有哪几种方式.
(1).构造函数注入
(2).set方法注入
(3).p名称空间注入
(4).复杂属性的注入
a)对象的注入
b)数组注入
c)List集合注入
d)Map注入
e)Preoperties注入
4谈谈你对Spring事物的理解(分值较高,详细说)
Spring事物的本其实就是数据库对事物的支持,没有数据库的事物支持,spring是无法提供事物功能的。
对于纯JDBC操作数据库,想要用到事物可以按照以下步骤进行:
获取连接Connection con = DriverManager.getConnection()
开启事务con.setAutoCommit(true/false);
执行CRUD
提交事务/回滚事务con.commit() / con.rollback();
关闭连接conn.close();
在使用Spring的事物管理功能后,我们可以不再写步骤2和步骤4的代码,而是由Spring自动完成。Spring是如何在我们书写的CRUD之前和之后开启事务和关闭事务的呢?
Spring的事务管理实现原理:
配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。spring在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据
@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了(开启正常提交事
务,异常回滚事务)真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。
Spring事物有三大特性:
传播属性;数据库隔离级别;Spring中的隔离级别;
传播属性:
所谓spring事务的传播属性,就是定义在存在多个事务同时存在的时候,spring应该如何处理这些
事务的行为。这些属性在TransactionDefinition中定义,具体常量的解释见下表
PROPAGATION_REQUIRED支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是Spring默认的事务的传播。
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,内层事务
失败抛出异常,外层事务捕获,也可以不处理回滚操作
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按
REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。
数据库隔离级别:
隔离级别隔离级别的值导致的问题
Read-Uncommitted 0导致脏读
Read-Committed 1避免脏读,允许不可重复读和幻读
Repeatable-Read 2避免脏读,不可重复读,允许幻读
Serializable 3串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读。执行效率慢,使用时慎重
脏读:一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。
不可重复读:一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一个事务对数据进行了修改,这时候两次读取的数据是不一致的。
幻读:第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改。
总结:
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
大多数的数据库默认隔离级别为Read Commited,比如SqlServer、Oracle
少数数据库默认隔离级别为:Repeatable Read比如:MySQL InnoDB
Spring中的隔离级别:
常量解释
ISOLATION_DEFAULT这是个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。
ISOLATION_READ_UNCOMMITTED这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
ISOLATION_REPEATABLE_READ这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
ISOLATION_SERIALIZABLE这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
5 Spring @Qualifer注解用在哪些场合?Spring Springmvc常用的注解都有哪些?
@Qualifer标注的对象与上一个相同,不同的是它指定了注入对象的类型,在使用@Autowried时如果没有指定注入参数的类型就会报错,因此@Qualifer是对@Autowried的有益补充。
@required负责检查一个bean在初始化时其声明的set方法是否被执行,当某个被标注了@Required的Setter方法没有被调用,则Spring在解析的时候会抛出异常,以提醒开发者对相应属性进行设置。@Required注解只能标注在Setter方法之上。因为依赖注入的本质是检查Setter方法是否被调用了,而不是真的去检查属性是否赋值了以及赋了什么样的值。如果将该注解标注在非setXxxx()类型的方法则被忽略。
@Component:标准一个普通的spring Bean类。
@Controller:标注一个控制器组件类。
@Service:标注一个业务逻辑组件类。
@Repository:标注一个DAO组件类。
在spring未来的版本中,@Controller,@Service,@Repository会携带更多语义。尽量考虑使用@Controller,@Service,@Repository代替通用的@Component。可以通过为添加或子元素来指定spring bean类,只要位于指定路径下的java类满足这种规则,即使这些java类没有使用任何annotation标注,spring一样会将他们当初bean类来处理。
:满足该规则的java类会被当初bean类处理。
:指定满足该规则的java类不会被当初bean类处理。
@Resource:位于java.annotation包下,来自于java EE规范的一个annotation。使用该annotation为目标bean指定协作者Bean。@Resource有一个name属性,在默认情况下,spring将这个值解释为需要被注入的Bean实例的名字。@Resource也可以直接修饰Filed,如果@Resource修饰Field,这时候连该属性的setter方法就不需要了。
使用@Resource可以省略name属性。
修饰方法时,省略name属性,则该name值是该setter方法去掉前面的set字符串,首字母小写后得到的子串。修饰Field时,省略name属性,则该name与该Field同名。
6谈谈你对Spring IOC AOP的理解
{http://blog.csdn.net/luoshenfu001/article/details/5816408/}
Spring IOC:容器的基础IoC容器负责容纳bean,并对bean进行管理。在Spring中,BeanFactory是IoC容器的核心接口。它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。Spring的IOC(控制反转)和DI(依赖注入)其实是一样的,依赖注入的方式有三种①接口注入②Construct注入③Set方法注入
引入IOC的目的是为了1.脱开,降低耦合;2.倡导面向切面编程,实施依赖倒换原则3.提高系统可插入、可测试、可修改等特性
具体做法:
(1)将bean之间的依赖关系尽可能地抓换为关联关系;
(2)将对具体类的关联尽可能地转换为对Javainterface的关联,而不是与具体的服务对象相关联;
(3)Bean实例具体关联相关javainterface的哪个实现类的实例,在配置信息的元数据中描述;
(4)由IoC组件(或称容器)根据配置信息,实例化具体bean类、将bean之间的依赖关系注入进来。
org.springframework.beans及org.springframework.context包是
Spring AOP:面向切面(方面)编程,可以用来很好的解决应用系统中分布于各个模块的交叉关注点问题轻量级的J2EE中应用开发中,使用AOP来灵活处理一些具有横切性质的系统级服务,如事务处理、安全检查、缓存、对象池管理等,已经成为一种非常适用的解决方案。
拦截器是用来实现对连接点进行拦截,从而在连接点前或后加入自定义的切面模块功能。在大多数JAVA的AOP框架实现中,都是使用拦截器来实现字段访问及方法调用的拦截(interception)。Spring AOP及JBoos AOP实现都是采用拦截器来实现的,面向切面编程(AOP)解决问题的关键则在于对关注点的抽象。也就是说,系统中对于一些需要分散在多个不相关的模块中解决的共同问题,则交由AOP来解决;
方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是一个很好的横切关注点例子。方面用Spring的Advisor或拦截器实现,然后可以通过@Aspect标注或在applictionContext.xml中进行配置:
连接点(Joinpoint):程序执行过程中的行为,如方法的调用或特定的异常被抛出,在代码上有JoinPoint类和ProceedingJoinPoint类,如下所示,可以通过JoinPoint获取很多参数,JoinPoint一般用在Advice实现方法中作为参数传入,ProceedingJoinPoint用于实现围绕Advice的参数传入。通过下面JoinPoint的接口可以看出通过JoinPoint可以得到代理对象和Target对象。
切入点(Pointcut):指定一个Adivce将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点,例如,使用正则表达式。
xml中配置:
或使用Annoation:@pointcut("execution * transfer(..)")并用一个返回值为void,方法体为空的方法来命名切入点如:privatevoidanyOldTransfer(){}
之后就可以在Advice中引用,如:@AfterReturning(pointcut="anyOldTransfer()", returning="reVal")
7 Spring AOP都有哪些通知?
许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Advice中必须用到PointCut
@Before
@AfterReturning
@AfterThrowing
@After
@Around
·AfterReturning增强处理,处理只有在目标方法成功完成后才会被织入。
·After增强处理不管目标方法如何结束(保存成功完成和遇到异常中止两种情况),它都会被织入。
8简单的谈一下SpringMVC的工作流程?
流程
1、用户发送请求至前端控制器DispatcherServlet
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、DispatcherServlet调用HandlerAdapter处理器适配器
5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9、ViewReslover解析后返回具体View
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户
Handler是Controller
9 SpringMVC的一个请求如何返回JSON类型
http://www.cnblogs.com/ssslinppp/p/4528892.html
@responseBody加入这个注解
//@requestBody
-
10怎么实现mybatis查询返回结果中的对象一个属性为list ,怎样实现一对多的关系?
在xml文件中使用resultMap标签返回的对象为一个list属性的对象。进行一对多,
1对1。
1对多。
11 MyBatis的SQL中#和$有什么区别?分别在什么情况下用?
#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.
$将传入的数据直接显示生成在sql中。#方式能够很大程度防止sql注入。$方式无法防止Sql注入。$方式一般用于传入数据库对象,例如传入表名.一般能用#的就别用$.
12 MyBatis如何获取自动生成的(主)键值?
useGeneratedKeys true,需要你表主键自动增长
keyProperty id,主键名称为id
比如又一个实体类User,实例化成user,里面有id name sex,三个属性,name sex赋值之后,调用insert,此时user的id值会自动赋值进去。
13 Spring bean的作用域
·当通过spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为bean设置作用域。Bean的作用域一共有五种,singleton(单例模式),prototype(原型模式),request,session,globalsession。
Singleton:使用这个模式的时候,在整个IOC容器中定义的bean将只有一个实例。
Prototype:每次通过容器的getBean方法获取prototype修饰的bean的时候,都将创建一个新的bean实例。
Request:只有在web应用中使用Spring的时候,该作用域才会生效。每一次http请求使用request修饰的作用会产生不同的bean实例。
Session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效
Globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效
比较常用的是singleton和prototype模式,对于singleton作用域的bean,每次请求该bean都将获得相同的实例。容器负责跟踪bean实例,负责维护bean实例的声明周期行为;如果一个bean被设置成prototype作用域,程序每次请求该id的bean,Spring都将会创建一个新的实例,然后返回给程序。在这种情况下,Spring容器仅仅使用new关键期i创建bean实例,一旦创建成功,容器不再跟踪实例,也不会维护bean实例的状态。
如果不指定Bean的作用域,Spring默认使用singleton作用域。Java在创建Java实例的时候,需要进行内存申请。销毁实例时需要完成垃圾回收,这些工作都会导致系统开销的增加。因此,使用prototype作用域笨啊的创建销毁代价比较大。而singleton作用域的bean实例,一旦创建成功,可重复使用。因此除非必要,否则尽量避免将bean设置成prototype作用域。
14 ThreadLocal的作用与实现
线程局部变量:当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本在Java中编写线程局部变量的代码相对来说要笨拙一些,因此造成线程局部变量没有在Java开发者中得到很好的普及。
ThreadLocal的接口方法
ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:
void set(Object value)设置当前线程的线程局部变量的值。
public Object get()该方法返回当前线程所对应的线程局部变量。
public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。
在JDK5.0中,ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal。API方法也相应进行了调整,新版本的API方法分别是void set(T value)、T get()以及T initialValue()。
15 Java内存模型是怎样的?
16 spring事物中隔离级别
17 hashmap,hashtable,concurrenthashmap区别与应用场景
HashMap和HashTable有什么区别:
1、HashMap是非线程安全的,HashTable是线程安全的。
2、HashMap的键和值都允许有null值存在,而HashTable则不行。
3、因为线程安全的问题,HashMap效率比HashTable的要高。
HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
HashMap不能保证随着时间的推移Map中的元素次序是不变的。
18 session是什么,怎么实现的?
19 Spring如何配置事务?
http://www.blogjava.net/robbie/archive/2009/04/05/264003.html
20 spring mvc中的@PathVariable主要用来做什么的?
spring mvc中的@PathVariable是用来获得请求url中的动态参数的