学习原本就不是一件简单的事情,更需要持之以恒的毅力。虽然苦,但是也不件是毫无回报的事。众所周知,程序员这个行业,学习和回报率是要高于其他行业的,不断提升自己的技术水平和认知,是绝对没有坏处的。
Spring面试专题
1、什么是spring、为什么要用spring及其优点、spring有哪些模块组成 ?
什么是spring
Spring 是个Java企业级应用的开源开发框架。Spring主要用来开发Java应用, 但是有些扩展是针对构建J2EE平台的web应用。Spring 框架目标是简化Java企业级应用开发,它使得开发者只需要关心业务需求。
spring优点 :spring属于低侵入式设计,代码的污染极低;
spring的DI机制将对象之间的依赖关系交由框架处理,减低组件的耦合性;
spring提供了AOP技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用;
spring对于主流的应用框架提供了集成支持。
spring有哪些模块组成
Spring Core:核心类库,提供IOC服务;
Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);
Spring AOP:AOP服务;
Spring DAO:对JDBC的抽象,简化了数据访问异常的处理;
Spring ORM:对现有的ORM框架的支持;
Spring Web:提供了基本的面向Web的综合特性,例如多方文件上传;
Spring MVC:提供面向Web应用的Model-View-Controller实现。
2、什么是IOC、DI 及其两者的优点 、 有哪几种注入方式
IOC:控制反转,把创建对象的控制权利由代码转移到spring的配置文件中。 最直观的表达就是,IOC让对象的创建不用去new了,可以由spring自动生产, 使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对 象,并调用对象的方法的。
DI:依赖注入,在程序运行期间,由外部容器动态地将依赖对象注入到组件中。 简单定义就是当一个对象需要另一个对象时,可以把另一个对象注入到对象中 去。
优点就是把应用的代码量降到最低,达到松散耦合度。
注入的方式: 构造注入
Set注入
接口注入
Spring提供以下几种集合的配置元素:类型用于注入一列值,允许有相同的值。
3、谈谈对AOP理解?
aop面向切面编程,关键在于代理模式,Spring AOP使用的动态代理,所谓的 动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。动态代理可以减少系统中的重 复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认 证、日志、事务处理。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:
JDK代理:基于接口的代理,不支持类的代理。核心InvocationHandler接口和 Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动 态创建一个符合某一接口的的实例, 生成目标类的代理对象。 Proxy.newProxyInstance(ClassLoader,Interfaces,InvocationHandler);
CGLIB动态代理:如果代理类没有实现 InvocationHandler 接口(或者说是基于父子类的),那 么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是 一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并 添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记 为final,那么它是无法使用CGLIB做动态代理的
4、Spring有几种配置方式?
将Spring配置到应用开发中有以下三种方式:
基于XML的配置
基于注解的配置(主流)
基于Java的配置
5、Spring 框架中都用到了哪些设计模式?
工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
单例模式:Bean默认为单例模式。
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
模板方法: 用来解决代码重复的问题。比 如. RestTemplate, JmsTemplate, JpaTemplate。
观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现-- ApplicationListener。
6、Spring 事务实现方式
编程式事务管理:这意味着你可以通过编程的方式管理事务,这种方式带来了很大的灵活性,但很难维护。
声明式事务管理:这种方式意味着你可以将事务管理和业务代码分离。你只需要通过注解或者XML配置管理事务。
7、Spring框架的事务管理有哪些优点
它为不同的事务API(如JTA, JDBC, Hibernate, JPA, 和JDO)提供了统一的编程模型。
它为编程式事务管理提供了一个简单的API而非一系列复杂的事务API(如JTA).
它支持声明式事务管理。
它可以和Spring 的多种数据访问技术很好的融合。
8、spring事务定义的传播规则
PROPAGATION_REQUIRED: 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS: 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY: 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW: 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,就把当 前事务挂起。
PROPAGATION_NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED: 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
9、BeanFactory和ApplicationContext有什么区别?
ApplicationContext提供了一种解决文档信息的方法,一种加载文件资源的方式(如图片),他们 可以向监听他们的beans发送消息。另外,容器或者容器中beans的操作,这些必须以bean工厂 的 编 程 方 式 处 理 的 操作 可 以 在 应 用 上 下 文 中 以 声 明 的 方 式 处 理 。 应 用 上 下 文 实 现 了 MessageSource,该接口用于获取本地消息,实际的实现是可选的。
相同点:两者都是通过xml配置文件加载bean,ApplicationContext和BeanFacotry相比,提供了更 多的扩展功能。
不同点:BeanFactory是延迟加载,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至 第一次使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,这 样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用ApplicationContext。
10、说一下Spring中支持的bean作用域
Spring框架支持如下五种不同的作用域:
singleton:在Spring IOC容器中仅存在一个Bean实例,Bean以单实例的方式存在。
prototype:一个bean可以定义多个实例。
request:每次HTTP请求都会创建一个新的Bean。该作用域仅适用于WebApplicationContext 环境。
session:一个HTTP Session定义一个Bean。该作用域仅适用于WebApplicationContext环 境。
globalSession : 同 一 个 全 局 HTTP Session 定 义 一 个 Bean 。 该 作 用 域 同样 仅 适 用 于 WebApplicationContext环境。
bean默认的scope属性是"singleton"
11、 什么是 spring 装配
当 bean 在 Spring 容器中组合在一起时,它被称为装配或 bean 装配。
Spring 容器需要知道需要什么 bean 以及容器应该如何使用依赖注入来将 bean 绑定在一起,同时装配 bean。 Spring 容器能够自动装配 bean。也就是说,可以通过检查 BeanFactory 的内容让 Spring 自动解析 bean 的协作者。
自动装配的不同模式:
no - 这是默认设置,表示没有自动装配。应使用显式 bean 引用进行装配。
byName - 它根据 bean 的名称注入对象依赖项。它匹配并装配其属性与 XML 文件中由 相同名称定义的 bean。
byType - 它根据类型注入对象依赖项。如果属性的类型与 XML 文件中的一个 bean 名 称匹配,则匹配并装配属性。
构造函数 - 它通过调用类的构造函数来注入依赖项。它有大量的参数。
autodetect - 首先容器尝试通过构造函数使用 autowire 装配,如果不能,则尝试通过 byType 自动装配。
13、 如何在 spring 中启动注解装配?
默认情况下,Spring 容器中未打开注解装配。因此,要使用基于注解装配,我 们必须通过配置< context: annotation-config / >元素在 Spring 配置 文件中启用它。
14、@Component, @Controller, @Repository, @Service 有何区别?
@Controller: 用于标注控制层,相当于struts中的action层
@Service: 用于标注服务层,主要用来进行业务的逻辑处理
@Repository: 用于标注数据访问层,也可以说用于标注数据访问组件,即 DAO组件
@Component:把普通pojo实例化到spring容器中,相当于配置文件中的 , 泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用 @Component来标注这个类
15、什么是Spring MVC ?简单介绍下你对springMVC的理解?
Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级 Web框架,通过把Model,View,Controller分 离,将web层进行职责解耦, 把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开 发人员之间的配合。
16、SpringMVC的流程?
(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器, 请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器 拦截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器;
(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制 器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给 DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行 解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图 中)
(11)DispatcherServlet响应用户。
17、SpringMvc怎么和AJAX相互调用的?
通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。
具体步骤如下 :
(1)加入Jackson.jar
(2)在配置文件中配置json的映射
(3)在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上 @ResponseBody注解。
Mybatis面试专题
1、什么是Mybatis?
(1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开 发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、 创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执 行性能,灵活度高。
(2)MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果 集。
(3)通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通 过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最 后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回 result的过程)。
2、Mybaits的优点
(1)基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提 供XML标签,支持编写动态SQL语句,并可重用。
(2)与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码, 不需要手动开关连接。
(3)很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以 只要JDBC支持的数据库MyBatis都支持)。
(4)能够与Spring很好的集成。
(5)提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系 映射标签,支持对象关系组件维护
3、MyBatis框架的缺点
(1)SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
(2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库
4、MyBatis框架适用场合
(1)MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。
(2)对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis 将是不错的选择。
5、MyBatis与Hibernate有哪些不同
(1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需 要程序员自己编写Sql语句。
(2)Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非 常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需求变化要求迅速输出成果。但是灵活的前提是mybatis无法做到数据库无关 性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工 作量大。
(3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高 的软件,如果用hibernate开发可以节省很多代码,提高效率。
6、#{}和${}的区别是什么?
#{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的 set方法来赋值;
Mybatis在处理${}时,就是把${}替换成变量的值。 使用#{}可以有效的防止SQL注入,提高系统安全性。
7、当实体类中的属性名和表中的字段名不一样 ,怎么办?
第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类 的属性名一致。
第2种: 通过来映射字段名和实体类属性名的一一对应的关系。
8、Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行 的内存分页,而非物理分页。
可以在sql内直接书写带有物理分页的参数来完成 物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对 应的物理分页语句和物理分页参数。
9、Mybatis动态sql有什么用?执行原理?有哪些动态sql?
Mybatis动态sql可以在Xml映射文件内,以标签的形式编写动态sql,执行原理 是根据表达式的值 完成逻辑判断并动态拼接sql的功能。
Mybatis提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。
10、Mybatis动态sql有什么用?执行原理?有哪些动态sql?
Mybatis动态sql可以在Xml映射文件内,以标签的形式编写动态sql,执行原理 是根据表达式的值 完成逻辑判断并动态拼接sql的功能。
Mybatis提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。
11、讲下 MyBatis 的缓存
MyBatis 的缓存分为一级缓存和二级缓存,一级缓存放在 session 里面,默认就有, 二级缓存放在它的命名空间里,默认是不打开的,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态),可在它的映射文件中配置。
12、Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
1)Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false。
2)它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。
13、什么是 MyBatis 的接口绑定,有什么好处?
接口绑定就是在 MyBatis 中任意定义接口,然后把接口里面的方法和 SQL 语句绑 定,我们直接调用接口方法就可以,这样比起原来了 SqlSession 提供的方法我们可 以有更加灵活的选择和设置。
14、接口绑定有几种实现方式,分别是怎么实现的?什么情况下用注 解绑定,什么情况下用 xml 绑定?
接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select@Update 等注解里面包含 Sql 语句来绑定,
另外一种就是通过 xml 里面写 SQL 来绑定,在这种情况下,要指定 xml 映射文件里面的 namespace 必须为接 口的全路径名。
当 Sql 语句比较简单时候,用注解绑定;当 SQL 语句比较复杂时候,用 xml 绑定, 一般用xml 绑定的比较多。
15、说一下resultMap和resultType
resultmap是手动提交,人为提交,resulttype是自动提交。
MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以 用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部 ResultMap的引用,但是resultType跟resultMap不能同时存在。
在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的 Map里面的,其中键是属性名,值则是其对应的值。
1.当提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出 赋给resultType所指定的对象对应的属性。所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,只是当提供的返回类型属性是resultType的时候,MyBatis对自动的给把对应的值赋给resultType所指定对象的属性。
2.当提供的返回类型是resultMap时,因为Map不能很好表示领域模型,就需 要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用。
Java面试专题
1. JDK 和 JRE 有什么区别?
JDK:Java Development Kit 的简称,Java 开发工具包,提供了 Java 的开发 环境和运行环境。
JRE:Java Runtime Environment 的简称,Java 运行环境,为 Java 的运行提 供了所需环境。 具体来说 JDK 其实包含了 JRE,同时还包含了编译 Java 源码的编译器 Javac,还 包含了很多 Java 程序调试和分析的工具。
简单来说:如果你需要运行 Java 程序, 只需安装 JRE 就可以了,如果你需要编写 Java 程序,需要安装 JDK。
2. == 和 equals 的区别是什么?
equals比较的是两个字符串内容是否相等
==比较的是两个字符串的内存地址是否相同。
3. String 属于基础的数据类型吗?
String 不属于基础类型,基础类型有 8 种:byte、boolean、char、double,float、int、long、short .而 String 属于对象。
4. String str="i"与 String str=new String("i")一样吗?
不一样,因为内存的分配方式不一样。String str="i"的方式,Java 虚拟机会将其分配 到常量池中;而 String str=new String("i") 则会被分到堆内存中。
5、int和Integer有什么区别?
Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入 了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自 动装箱/拆箱机制,使得二者可以相互转换。
6、float f=3.4是否正确?
不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于 下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转 换float f =(float)3.4; 或者写成float f =3.4F。
7、&和&&的区别?
虽然二者都要求运算符左右两端的布尔值都是true整个表达式的值才是true。 &&之所以称为短路运算是因为,如果&&左边的表达式的值是false,右边的表 达式会被直接短路掉,不会进行运算。
8、用最有效率的方法计算2乘以8?
2 << 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。
9、是否可以继承String类?
String 类是final类,不可以被继承。
10、String和StringBuilder、StringBuffer的区别?
Java平台提供了两种类型的字符串:String和StringBuffer/StringBuilder,它 们可以储存和操作字符串。 其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变 的。 而StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改。 StringBuilder是Java 5中引入的,线程不安全的,它和StringBuffer的方法完全相同,区别在 于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修 饰,因此它的效率也比StringBuffer要高。
11.普通类和抽象类有哪些区别?
普通类不能包含抽象方法,抽象类可以包含抽象方法。
抽象类不能直接实例化,普通类可以直接实例化。
12.接口和抽象类有什么区别?
接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象 的方法。
类可以实现很多个接口,但是只能继承一个抽象类类可以不实现抽象 类和接口声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。 抽象类可以在不提供接口方法实现的情况下实现接口。
Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。
Java接口中的成员函数默认是public的。抽象类的成员函数可以是private, protected或者是public。
接口是绝对抽象的,不可以被实例化,抽象类也不可以被实例化。
13、 什么是Java虚拟机?为什么Java被称作是“平台无关的编程 语言”?
java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能 被Java虚拟机执行的字节码文件。
因为它有虚拟机(JVM),JAVA程序不是直接在电脑上运行的,是在虚拟机上 进行的,每个系统平台都是有自己的虚拟机(JVM),所以JAVA语言能跨平 台。
14、 重载(Overload)和重写(Override)的区别?
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态 性,而后者实现的是运行时的多态性。
重载发生在一个类中,同名的方法如果 有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法 有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比 父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。 一句话:重载就是同类同名不同参,重写就是同名同参不同类。
15、 什么是值传递和引用传递?
值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。
引用传递一般是对于对象型变量而言的,也可以成为传地址, 方法调用时,实际参数是对象(或数组),这时实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,这个结果在方法结束后 被保留了下来,所以方法执行中形式参数的改变将会影响实际参数。
16、final、finalize 和 finally 的不同之处?
final 是一个修饰符,可以修饰变量、方法和类。如果 final 修饰变量,意味着 该变量的值在初始化后不能被改变。
Java 技术允许使用 finalize() 方法在垃圾 收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收 集器在确定这个对象没有被引用时对这个对象调用的,但是什么时候调用 finalize 没有保证。
finally 是一个关键字,与 try 和 catch 一起用于异常的处 理。finally 块一定会被执行,无论在 try 块中是否有发生异常。
17、String s = new String(“xyz”);创建了几个字符串对象?
两个对象,一个是静态区的”xyz”,一个是用new创建在堆上的对象。
18、 怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符 串?
String s1 = "你好";
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");
19、列出一些你常见的运行时异常?
- ArithmeticException(算术异常)
- ClassCastException (类转换异常)
- IllegalArgumentException (非法参数异常)
- IndexOutOfBoundsException (下标越界异常)
- NullPointerException (空指针异常)
- SecurityException (安全异常) ...
20、获得一个类的类对象有哪些方式?
- 方法1:类型.class,例如:String.class
- 方法2:对象.getClass(),例如:”hello”.getClass()
- 方法3:Class.forName(),例如:Class.forName(“java.lang.String”)
21、Collection 和 Collections 有什么区别?
Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如 List、Set 等。
Collections 是一个包装类,包含了很多静态方法,不能被实例化,就像一个工具类,比如提供的排序方法: Collections. sort(list)。
22. HashMap 和 Hashtable 有什么区别?
存储:HashMap 运行 key 和 value 为 null,而 Hashtable 不允许。
线程安全:Hashtable 是线程安全的,而 HashMap 是非线程安全的。
推荐使用:在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使 用,推荐在单线程环境下使用 HashMap 替代,如果需要多线程使用则用 ConcurrentHashMap 替代。
23. 如何决定使用 HashMap 还是 TreeMap?
对于在 Map 中插入、删除、定位一个元素这类操作,HashMap 是最好的选 择,因为相对而言 HashMap 的插入会更快,但如果你要对一个 key 集合进行 有序的遍历,那 TreeMap 是更好的选择。
24. 说一下 HashMap 的实现原理?
HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获 取。当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 bucket 里。当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时,使用链表否则使用红黑树。
25. 说一下 HashSet 的实现原理?
HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有 元素,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接 调用底层 HashMap 的相关方法来完成,HashSet 不允许重复的值。
26、Thread类的sleep()方法和对象的wait()方法都可以让线程暂 停执行,它们有什么区别?
sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依 然保持,因此休眠时间结束后会自动恢复。
wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁 (线程暂停执行),进入对象的等待池(wait pool),只有调用对象的 notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。
27、线程的sleep()方法和yield()方法有什么区别?
① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运 行的机会;
② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转 入就绪(ready)状态;
③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
④ sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植 性。
28、当一个线程进入一个对象的synchronized方法A之后,其它线 程是否可进入此对象的synchronized方法B?
不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非 静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经 进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池 (注意不是等待池哦)中等待对象的锁。
29、请说出与线程同步以及线程调度相关的方法。
- wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
- sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常;
- notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;
- notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;
30、编写多线程程序有几种实现方式?
一种是继承Thread类;
另一种是实现Runnable接口。两种方式都要通过重写 run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,显然使用 Runnable接口更为灵活。
关注本站,可以了解更多相关java架构师面试题哦。