SpringMVC模型视图控制器
它用于web层,相当于controller(等价于传统的servlet和struts的action),用来处理用户请求。举个例子,用户在地址栏输入http://网站域名/login,那么springmvc就会拦截到这个请求,并且调用controller层中相应的方法
SpringMVC模型视图控制器
它用于web层,相当于controller(等价于传统的servlet和struts的action),用来处理用户请求。举个例子,用户在地址栏输入http://网站域名/login,那么springmvc就会拦截到这个请求,并且调用controller层中相应的方法
M-Model 模型(完成业务逻辑:有javaBean构成,service+dao+entity/pojo)
V-View 视图(做界面的展示 jsp,html……)
C-Controller 控制器(接收请求—>调用模型—>根据结果派发页面)
Spring MVC Interceptor 拦截器 :HandlerInterceptorAdapter
Spring 统一异常处理有 3 种方式,分别为:
- 使用 @ ExceptionHandler 注解
- 实现 HandlerExceptionResolver 接口
- 使用 @controlleradvice 注解
SpringMVC框架执行原理和步骤
1.用户的请求到服务器web.xml配置的Servlet:DispatcherServlet并拦截*.do请求
2.DispatcherServlet请求HandlerMapping查找并返回Handler和HandlerExecutionChain
3.DispatcherServlet请求HandlerAdapter执行Handler(Controller)返回ModelAndView
4.DispatcherServlet请求ViewResolver解析ModelAndView返回View
5.DispatcherServlet渲染model给View返回给用户
详细原理和步骤:
1.一个post/get请求根据服务器地址的入口最先会到web.xml里配置的初始化的Servlet的DispatcherServlet前端控制器,并拦截*.do请求
dispatcherServlet是springmvc的核心进行全局流程控制 web.xml加载顺序 context-param-listener-filter-servlet
2.前端控制器DispatcherServlet根据发送活来的请求信息,调用HandlerMapping(处理器映射器)获得能够处理请求的Handler(处理器,通常称为controller)的所有相关对象(通过springmvc.xml配置或者注解进行查找),最后以HandlerExecutionChain(执行链)对象的形式返回; HandlerMapping 将会把请求映射为HandlerExecutionChain 对象(包含一个Handler 处理器(页面控制器)对象、多个HandlerInterceptor 拦截器) 3.前端控制器DispatcherServlet根据上一步返回的handler的信息,选择一个合适的HandlerAdapter(处理器适配器);
提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作: HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
Controller执行过程:将这次请求交由Controller后端控制器进行处理,所以需要进行这个类的实例化. 在实例化Controller的时候,注入ServiceImpl接口 在实例化ServiceImpl的时候,又注入Mapper接口 根据ApplicationContext.xml中的配置信息,将Mapper和Mapper.xml关联起来了。 这样就拿到了实例化好了的Controller,并调用方法.
执行结果是ModelAndView 对象(包含模型数据、逻辑视图名);再返回给DispatcherServlet
4.前端控制器DispatcherServlet接收到ModleAndView以后,调用合适的ViewResolver(视图解析器)准备渲染图像; 返回View 5.ViewResolver根据Modle和View进行视图渲染;View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构 进行渲染最后响应结果(json/字符串)给用户.前端通过js展示出来响应结果也是程序员需要完成的
下边两个组件通常情况下需要开发:
Handler:处理器,即后端控制器用controller表示。
View:视图,即展示给用户的界面,视图中通常需要标签语言展示模型数据
常用注解
SpringMVC常用注解都有哪些? @requestMapping 用于请求 url 映射 @RequestBody 注解实现接收 http 请求的 json 数据,将 json 数据转换为 java 对象。 入参使用
@ResponseBody 注解实现将 controller 方法返回对象转化为 json 响应给客户。
controller层:
@RestController
@RequestMapping("/seller")
public class SellerController {
@Reference
private SellerService sellerService;
@RequestMapping("/add")
public Result add(@RequestBody TbSeller seller){
try {
sellerService.add(seller);
return new Result(true, "增加成功");
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "增加失败");
}
}
service实现层:
@Service
public class SellerServiceImpl implements SellerService {
@Autowired
private TbSellerMapper sellerMapper;
dao层放 Mapper接口和Mapper.xml映射文件
Spring IOC容器和 AOP切面 框架
管理每个Bean的整个生命周期的 一个bean对应一个请求 Spring就像是整个项目中装配bean的工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。: 控制反转(IOC),传统的java开发模式中,当需要一个对象时,我们会自己使用new或者 getInstance 等直接 或者间接调用构造方法创建一个对象。而在spring开发模式中,spring容器使用了工厂模式为我们创建了所需要的对 象,不需要我们自己创建了,直接调用spring提供的对象就可以了,这是控制反转的思想。 依赖注入(DI),spring 使用 javaBean 对象的 set 方法或者带参数的构造方法为我们在创建所需对象时将其属 性自动设置所需要的值的过程,就是依赖注入的思想。 面向切面编程(AOP),在面向对象编程(oop)思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程 中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事物管理,记录日志等 公用操作处理的过程就是面向切面编程的思想。AOP 底层是动态代理,如果是接口采用JDK 动态代理,如果是类采用 CGLIB方式实现动态代理。
Spring 中的设计模式 a. 单例模式——spring中两种代理方式,若目标对象实现了若干接口, spring使用jdk的java.lang.reflect.Proxy
@Component:通用注解 @Repository:持久化层组件注解
@Service:业务层组件注解;@Controller:控制层组件注解
配置方式如下: <context:annotation-config /> 常用的注解: @Required:该注解应用于设值方法 @Autowired:该注解应用于有值设值方法、非设值方法、构造方法和变量。 @Qualifier:该注解和@Autowired 搭配使用,用于消除特定bean自动装配的歧义。
Mybatis ORM对象关系映射 持久层框架
mybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到各实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。
Mybatis中#和$的区别?(2017-11-23-gxb)
相当于对数据 加上 双引号,$相当于直接显示数据 将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是 111,那么解析成 sql时的值为order by “111”, 如果传入的值是 id,则解析成的sql为order by “id”.
Mysql的事物隔离级别?
答:Mysql的事物隔离级别 其实跟 Spring的事物隔离级别一样,都是1、Read Uncommitted(读取未提交内容), 2、Read Committed(读取提交内容),3、Repeatable Read(可重读),4、Serializable(可串行化)
这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:
脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
Shiro 认证、授权、加密的安全框架
三个核心组件:Subject, SecurityManager 和 Realms. Subject:即“当前操作用户”。但是,在 Shiro中,Subject 这一概念并不仅仅指人,也可以是第三方进程、后台帐 户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途, 你可以把它认为是Shiro的“用户”概念。 Subject代表了当前用户的安全操作,SecurityManager 则管理所有用户的安全操作。 SecurityManager:它是 Shiro 框架的核心,典型的 Facade 模式,Shiro 通过 SecurityManager 来管理内部组 件实例,并通过它来提供安全管理的各种服务。 Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登 录)和授权(访问控制)验证时,Shiro 会从应用配置的Realm中查找用户及其权限信息。
Shiro主要的四个组件(2017-12-2-wzz)
1)SecurityManager
典型的 Facade,Shiro 通过它对外提供安全管理的各种服务。
2)Authenticator
对“Who are you ?”进行核实。通常涉及用户名和密码。 这个组件负责收集 principals 和 credentials,
并将它们提交给应用系统。如果提交的 credentials 跟应用系统中提供的 credentials 吻合,就能够继续访问,
否则需要重新提交 principals 和 credentials, 或者直接终止访问。
3)Authorizer
身份份验证通过后,由这个组件对登录人员进行访问控制的筛查,比如“who can do what”, 或者“who
can do which actions”。 Shiro 采用“基于 Realm”的方法,即用户(又称 Subject)、 用户组、角 色和
permission 的聚合体。
410
4)Session Manager
这个组件保证了异构客户端的访问,配置简单。它是基于 POJO/J2SE 的,不跟任何的客户 端或者协议绑定。
Shiro运行原理(2017-12-2-wzz)
1、Application Code:应用程序代码,就是我们自己的编码,如果在程序中需要进 行权限控制,需要调用
Subject 的 API。
2、Subject:主体,代表的了当前用户。所有的 Subject 都绑定到 SecurityManager, 与 Subject 的所有
交互都会委托给 SecurityManager,可以将 Subject 当成一个 门面,而真正执行者是 SecurityManager 。
3、SecurityManage:安全管理器,所有与安全有关的操作都会与 SecurityManager 交互,并且它管理所有
的 Subject 。
4、Realm:域 shiro 是从 Realm 来获取安全数据(用户,角色,权限)。就是说 SecurityManager
要验证用户身份, 那么它需要从 Realm 获取相应的用户进行比较以确定用户 身份是否合法;也需要从
Realm 得到用户相应的角色/权限进行验证用户是否 能进行操作; 可以把 Realm 看成 DataSource,即安全数
据源 。
Redis 内存缓存数据库/Key-Value 类型的内存数据库
数据类型,如:string、list、set、zset(sorted set)、hash
ActiveMQ消息队列框架
Dubbox分布式服务框架
zookeeper注册中心
Dubbo注册中心和广播注册中心配置类似,不过需要指定注册中心类型和注册中心地址,这个时候就不是把服务 信息进行广播了,而是告诉给注册中心进行管理,这个时候我们就需要有一个注册中心。 官方推荐使用 zookeeper作为注册中心。 3.3.1、Zookeeper 介绍 zookeeper 在dubbo所处的位置:
1)Provider: 暴露服务的服务提供方。 2)Consumer: 调用远程服务的服务消费方。 3)Registry: 服务注册与发现的注册中心。 4) Monitor: 统计服务的调用次调和调用时间的监控中心。 5)Container: 服务运行容器。
Nginx反向代理服务器
solr 基于Lucene的全文搜索服务器
简单介绍一下solr(2017-11-24-gxb)
Solr 是一个独立的企业级搜索应用服务器,它对外提供类似于 Web-service 的 API 接口。 用户可以通过 http
请求,向搜索引擎服务器提交一定格式的 XML 文件,生成索引;也可以 通过 Http Get 操作提出查找请求,并得到
XML 格式的返回结果。
特点:
Solr 是一个高性能,采用 Java5 开发,基于 Lucene 的全文搜索服务器。同时对其进行 了扩展,提供了比
Lucene 更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能 进行了优化,并且提供了一个完善的功能管
理界面,是一款非常优秀的全文搜索引擎。
工作方式:
文档通过 Http 利用 XML 加到一个搜索集合中。查询该集合也是通过 http 收到一个 XML/JSON 响应来实现。
它的主要特性包括:高效、灵活的缓存功能,垂直搜索功能,高亮 显示搜索结果,通过索引复制来提高可用性,提供一
套强大 Data Schema 来定义字段,类 型和设置文本分析,提供基于 Web 的管理界面等。
solr怎么设置搜索结果排名靠前?(2017-11-24-gxb) 可以设置文档中域的 boost 值,boost 值越高,计算出来的相关度得分就越高,排名也就越靠前。此方法可以把 热点商品或者推广商品的排名提高。
455
solr中IK分词器原理是什么?(2017-11-24-gxb)
Ik 分词器的分词原理本质上是词典分词。先在内存中初始化一个词典,然后在分词过程中挨个读取字符,和字典
中的字符相匹配,把文档中的所有的词语拆分出来的过程。
八、webService
Restful
谈谈你对restful 的理解以及在项目中的使用?(2017-11-30-wzz) 注意:下面回答内容来自百度百科。 一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交 互类的软件。REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。它结 构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。 给大家推荐如下一篇博客,该博客从多个维度讲解了什么是 Restful并且给了 Restful风格样式的API 接口。 http://blog.csdn.net/liuwenbiao1203/article/details/52351129
Spring boot 简化配置基于Spring的应用开发框架
spring cloud分布式微系统开发工具包
一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发.
SOA面向服务的架构有:dubbo->zookeeper->comcat->监控->集群->健康检查 rpc协议
微服务:相当于SOA里面包括整个环节的服务
核心组件:spring Cloud Netflix 是对Netflix开发的一套分布式服务框架的封装,包括服务的发现和注册,负载均衡、断路器、REST客户端、http协议 请求路由等。
SQL语句
sql类型 :
整型 int 2的32次方还大的话,就使用bigint
浮点型: float或者double
字符串: varchar(10);可变长度,最大可以放10个字符 char(20),固定20字符长度
日期date: yyyy-MM-dd; datetime:日期和时间; timeStamp: 时间戳sql类型
text或者longtext: 文本
约束:
not null; 非空
unique;唯一约束
primary key;主键约束(非空+唯一);
auto_increment;自动增长列和主键一起使用通常给id int类型设置主键约束,auto_increment
创建一张明星表star
(明星id id是主键,并自动增长,明星名字,明星年龄,明星身价,明星性别,明星类型)
语句:create table star(id int primary key auto_increment,name varchar(30),age int,price int,sex varchar(10),type int);
增:
insert into star values(null,“宝宝”,35,5000,“男”,1);
insert into star values(null,“蓉蓉”,24,100,“女”,2);
insert into star values(null,“房祖名”,29,3000,“男”,3);
insert into star values(null,“周立波”,40,1000,“男”,3);
insert into star values(null,“小白”,30,8000,“女”,2);
删:
delete from star where name=“房祖名”
改:
update star set price=1500 where name=“周立波”
所有身价加1000:update star set price=price+1000
查:
去重+全部+名字别名+身份别名+区间条件+排序 select distinct *,name 名字,price 身价 from star WHERE age between 26 and 45 order by price asc
集合内select * from star where id in(1,2)
姓周select * from star where name like “周%” 周后面只能有两个字符:周__ 包含周字:%周%
逻辑 and or not 排序order by price asc/esc 聚合函数: 计数count()求和sum() 平均avg() 最大max() 最小min()
分组查询出每个分组和星个数:select type,count(id) from star group by type
以type分组 查询type名和各组最高身份 select type,max(price)from star group by type
分组后再以数量筛选 having:select type,max(price)from star group by type having count(type)>2
子查询
身价最高的明星所有信息:select * from star where price=(select max(price) from star)
和周杰一个分组的明星但不包括周杰的 select*from star where type=(select type from star where name=“周杰”) and name!=“周杰”
所有类别名为category表中cid对应的cname是宝剑队的明星:不需要外键约束 select*from star where type=(select cid from category where cname=“宝剑队”)
联表查询
查询出名星表和类型名的字段相等情况下 明星表id 别名 明星名 和所属类型表名
select s.id,s.name 明星名字,c.cname 属性哪个队 from star s join category c on s.type=c.cid
1对多 在多的一方添加 一个外键指向1的一方的主键
多对多 创建一张第三方表 除了id字段外 还有两个字段分别作为外键指向两张表的主键
优化:
经常作为查询where条件的 ORDER BY排序 建索引 平衡树索引 B-TREE索引
尽量使用数字型字段) 只返回需要的字段 应该尽量把字段设置为NOT NULL 比较多用区间
分页:
对明星进行按年龄从高到低排序,然后分页 0条开始一页3个 SELECT * from star order by age desc LIMIT 0,3
选择:select * from table1 where 范围 插入:insert into table1values(value1,‘value2’) 删除:delete from table1 where 范围 更新:update table1 set field1=‘value1’ where 范围 查找:select * from table1 where field1 like ’%value1’—like的语法很精妙,查资料! 排序:select * from table1 order by field1,field2 [desc] 总数:select count * as totalcount from table1
创建索引:create [unique] index idxname on tabname(user_id,..)
CREATE INDEX sc_tb_address_index ON tb_address(user_id)
删除索引:drop index idxname
谈谈你对NIO的理解
答:IO是面向流,NIO是面向缓冲
IO NIO 面向流 面向缓冲 阻塞IO 非阻塞IO 无 选择器
日期时间
System.out.println(new SimpleDateFormat("yyyy/MM/dd hh:mm:ss").format(new Date()));
java没有全局变量和全局方法这个概念
全局方法,被加上static关键字,全局的变量是,static final
http和https
http是HTTP协议运行在TCP之上。所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。
https是HTTP运行在SSL/TLS之上,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。此外客户端可以验证服务器端的身份,如果配置了客户端验证,服务器方也可以验证客户端的身份。。
集合接口 单列Collection 双列Map
|-ArrayList 动态数组 可null 查快
|-List -|-LinkedList链表 增删快
|有序可重|-Vector ArrayList相似 多线程安全
Collection|
| |-HashSet 以哈希表的形式存放元素,插入删除速度很快
|-Set-|-LinkedHashSet 集合迭代时,维护插入顺序
无序不重|-TreeSet 升序排好序的集合
Map(键值对、键唯一、值可不唯一 以键map.get(key))
|-HashMap 快速 线程不安全 键可一个null 散列表的通用映射表,无序
|-HashTable HashMap相似 线程安全 较慢 不可Null
Map|-LinkedHashMap 保存了记录的插入顺序 Iteraor遍历时先进先出
|-TreeMap 根据键升序排序 可指定比较器
for(Integer key : map.keySet()){
System.out.println("key:"+key+"value:"+map.get(key));
for(Entry<Integer , String> entry : map.entrySet()){
System.out.println("key:"+entry.getKey()+" value:"+entry.getValue());
Iterator it = map.entrySet().iterator();
while(it.hasNext()){
Entry e =(Entry) it.next();
System.out.println("键"+e.getKey () + "的值为" + e.getValue());
Iterator接口 所有集合都实现此迭代器接口
数组(可以存储基本数据类型和对象)一种容器,长度固定
集合(只能存储对象)长度可变
Map(只能存对象 键值对、键唯一、值可不唯一 以键map.get(key))
所有的集合类,都实现了 Iterator 接口,这是一个用于遍历集合中元素的接口,主要包含以下三种方法:
- hasNext() 是否还有下一个元素。
- next() 返回下一个元素。
- remove() 删除当前元素。
Ajax
在不刷新整个页面的前提下传输数据。实现局部刷新,
Json
var json={“name”:“张三”,“age”:25} 获取 document.write(“名:” + json.name+“年龄”+json.age)
var json=[{“name”:“张三”,“age”:21},{“name”:“李四”,“age”:50}]
获取document.write(“名1:” + json[0].name+“年龄1”+json[0].age)
01 Java面试题库及答案解析
形参出现方法定义中,在整个方法体内都可以使用,离开方法则不能使用。
实参出现在类中方法外,进入被调方法后,实参变量也不能使用.this.可使用
形参和实参的功能是做数据传送。发生方法调用时,主调方法把实参的值传送给被调方法的形参从而向被调方法传送数据。
在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的内存地址值,所以都统称按 值传递。
Java方法基本数据类型是传值,对象类型传引用 ,当参数是对象时,无论方法体内进行了何种操作,都不会改变实参对象的引用。
对象存在的空间堆,方法和变量存在空间栈,变量存在于哪一个空间要看他的类型而定,实例变量属于对象,存在于堆,局部变量又叫栈变量(包括方法参数和内部的变量)
1、面向对象编程(OOP)有哪些优点?
- 代码开发模块化,更易维护和修改。
- 代码复用。
- 增强代码的可靠性和灵活性。
- 增加代码的可理解性。
2、面向对象编程有哪些特性?
封装、继承、多态、抽象
封装
封装给对象提供了隐藏内部特性和行为的能力。对象提供一些能被其他对象访问的方法来改变它内部的数据。在Java当中,有3种修饰符:public,private和protected。每一种修饰符给其他的位于同一个包或者不同包下的对象赋予了不同的访问权限。
下面列出了使用封装的好处:
- 通过隐藏对象的属性来保护对象内部的状态。
- 提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展。
- 禁止对象之间的不良交互提高模块化。
继承
继承给对象提供了从基类获取字段和方法的能力。继承提供了代码的重用,也可以在不修改类的情况下给现存的类添加新特性。
多态
多态是编程语言给不同的底层数据类型做相同的接口展示的一种能力。一个多态类型上的操作可以应用到其他类型的值上面。
抽象
抽象是把想法从具体的实例中分离出来的步骤,因此,要根据他们的功能而不是实现细节来创建类。Java支持创建只暴露接口而不包含方法实现的抽象的类。这种抽象技术的主要目的是把类的行为和实现细节分离开。
3、什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?
Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。
Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。
4、JDK和JRE的区别是什么?
JRE(Java运行时环境) 是将要执行Java程序的Java虚拟机。它同时也包含了执行applet需要的浏览器插件。JDK(Java开发工具包) 是完整的Java软件开发包,包含了JRE,编译器和其他的工具(比如:JavaDoc,Java调试器),可以让开发者 开发、编译、执行Java应用程序。
5、“static”关键字是什么意思?Java中是否可以覆盖(override) 一个private或者是static的方法?
“static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例的情况下被访问。
Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。
6、是否可以在static环境中访问非static变量?
不可以。static变量在Java中是属于类的,它在所有的实例中的值是一样的。当类被Java虚拟机载入的时候,会对static变量进行初始化。如果你的代码尝试不用实例来访问非static的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。
7、Java支持的数据类型有哪些?什么是自动拆装箱?
字符类型char用单引号’‘括起来的 1 个字符(可以是一个中文字符)字符类型的本质就是整形数 字符赋值给一个字符变量的时候,它首先会去查ASCII码表,布尔类型(boolean):true 真 和 false 假。以及数值类型四种整数类型(byte、short、int、long)两种浮点数类型(float、double)
- byte
- short
- int
- long
- float
- double
- boolean
- char
自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。比如:把int转化成Integer。反之就是自动拆箱。
8、Java中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思?
方法覆盖是说子类重新实现父类的方法。方法覆盖必须有相同的方法名,参数列表和返回类型。
方法重载发生在同一个类里面,两个或者是多个方法的方法名相同但是参数列表不同。
9、Java中,什么是构造函数?什么是构造函数重载?什么是复制构造函数?
当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一个默认的构造函数。
Java中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数必须有它自己唯一的参数列表。
Java不支持像C++那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java不会创建默认的复制构造函数。
10、Java支持多继承么?
不支持,Java不支持多继承。每个类都只能继承一个类,但是可以实现多个接口。
11、抽象类和接口的区别是什么?
Java支持创建抽象类和接口。它们的区别在于:
- 接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。
- 类可以实现很多个接口,但是只能继承一个抽象类
- 类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,在这种情况下,类也必须得声明成是抽象的。
- 抽象类在实现接口时,可以不实现接口里面的方法。
- Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。
- Java接口中的成员方法默认是public的。抽象类的成员方法可以是private,protected或者是public。
- 接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。
12、什么是值传递?什么是引用传递?
对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响源对象的值。
对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象所做的改变会反映到所有的对象上。
13、进程和线程的区别是什么?
进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。
14、创建线程有几种不同的方式?你喜欢哪一种?为什么?
创建线程有以下几种方式:
- 继承Thread类
- 实现Runnable接口
- 应用程序可以使用Executor框架来创建线程池
实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在已经继承了别的类的情况下,这需要多继承(而Java不支持多继承),只能实现接口。同时,线程池也是非常高效的,很容易实现和使用。
15、解释一下线程的几种可用状态
线程可以处于以下几种状态:
- 就绪(Runnable):线程准备运行,不一定立马就能开始执行。
- 运行中(Running):程序正在执行线程的代码。
- 等待中(Waiting):线程处于阻塞的状态,等待外部的处理结束。
- 睡眠中(Sleeping):线程被强制睡眠。
- I/O阻塞(Blocked on I/O):等待I/O操作完成。
- 同步阻塞(Blocked on Synchronization):等待获取锁。
- 死亡(Dead):线程完成了执行。
16、同步方法和同步代码块的区别是什么?
同步方法就是在方法前加关键字synchronized,然后被同步的方法一次只能有一个线程进入,其他线程等待。
而同步代码块则是在方法内部使用大括号使得一个代码块得到同步。同步块会有一个锁定的“对象”。同步代码块的同步范围更加准确。
17、在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步?
监视器和锁在Java虚拟机中是一起使用的。监视器监视同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。
18、什么是死锁(deadlock)?
两个线程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个线程都陷入了无限的等待中。
19、如何确保N个线程可以访问N个资源同时又不导致死锁?
使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。
20、Java集合类框架的基本接口有哪些?
Java集合类里面最基本的接口有:
- Collection:代表一组对象,每一个对象都是它的子元素。
- Set:不包含重复元素的Collection。
- List:有顺序的Collection,并且可以包含重复元素。
- Map:可以把键(key)映射到值(value)的对象,键不能重复。
21、为什么集合类没有实现Cloneable和Serializable接口?
克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。
22、什么是迭代器(Iterator)?
Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的迭代方法。迭代器可以在迭代的过程中删除底层集合的元素。
23、Iterator和ListIterator的区别是什么?
他们的区别如下:
- Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
- Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
- ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
24、快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?
Iterator的安全失败是基于对底层集合做拷贝,因此,它不受源集合上修改的影响。java.util包下面的所有的集合类都是快速失败的,而java.util.concurrent包下面的所有的类都是安全失败的。快速失败的迭代器会抛出ConcurrentModificationException异常,而安全失败的迭代器永远不会抛出这样的异常。
25、Java中的HashMap的工作原理是什么?
Java中的HashMap是以键值对(key-value)的形式存储元素的。HashMap需要一个hash函数,它使用hashCode()和equals()方法来向集合添加元素和从集合检索元素。当调用put()方法的时候,HashMap会计算key的hash值,然后把键值对存储在集合中合适的索引上。如果key已经存在了,value会被更新成新值。
26、hashCode()和equals()方法的重要性体现在什么地方?
Java中的HashMap使用hashCode()和equals()方法来确定键值对的索引,当根据键获取值的时候也会用到这两个方法。如果没有正确的实现这两个方法,两个不同的键可能会有相同的hash值,因此,可能会被集合认为是相等的。而且,这两个方法也用来发现重复元素。所以这两个方法的实现对HashMap的精确性和正确性是至关重要的。
27、HashMap和Hashtable有什么区别?
HashMap和Hashtable都实现了Map接口,他们有以下不同点:
- HashMap允许键和值是null,而Hashtable不允许键或者值是null。
- Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线程环境。
- HashMap提供了可供应用迭代的键的集合,因此,HashMap是快速失败的。另一方面,Hashtable提供了对键的列举(Enumeration)。
28、数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用Array而不是ArrayList?
Array 和ArrayList 有以下的不同点:
- Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
- Array大小是固定的,ArrayList的大小是动态变化的。
- ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
对于基本类型数据,ArrayList 使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢,这时候应该使用Array。
29、ArrayList和LinkedList有什么区别?
ArrayList和LinkedList 有以下的不同点:
- ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。而 LinkedList是以链表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。
- 相对于ArrayList,LinkedList的插入、添加、删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。
- LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。
30、Comparable和Comparator接口是干什么的?列出它们的区别。
Java提供了只包含一个compareTo()方法的Comparable接口。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。
Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序,返回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。equals()方法需要一个对象作为参数,它用来决定输入参数是否和Comparator相等。只有当输入参数也是一个Comparator并且输入参数和当前Comparator的排序结果是相同的时候,这个方法才返回true。
31、什么是Java优先级队列(Priority Queue)?
PriorityQueue是一个基于优先级堆的无界队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。
32、你了解大O符号(big-O notation)么?你能给出不同数据结构的例子么?
大O符号描述了当数据结构里面的元素增加的时候,算法的规模或者是性能在最坏的场景下有多么好。
大O符号也可用来描述其他的行为,比如:内存消耗。因为集合类实际上是数据结构,我们一般使用大O符号基于时间,内存和性能来选择最好的实现。大O符号可以对大量数据的性能给出一个很好的说明。
33、如何权衡是使用无序的数组还是有序的数组?
有序数组最大的好处在于查找的时间复杂度是O(log n),而无序数组是O(n)。有序数组的缺点是插入操作的时间复杂度是O(n),因为值大的元素需要往后移动来给新元素腾位置。相反,无序数组的插入时间复杂度是常量O(1)。
34、Java集合类框架的最佳实践有哪些?
根据应用的需要正确选择要使用的集合的类型对性能非常重要,比如:元素的大小是固定的,而且能事先知道,我们就应该用Array而不是ArrayList。
有些集合类允许指定初始容量。因此,如果我们能估计出存储的元素的数目,我们可以设置初始容量来避免重新计算hash值或者是扩容。
为了类型安全,可读性和健壮性的原因总是要使用泛型。同时,使用泛型还可以避免运行时的ClassCastException。
使用JDK提供的不变类(immutable class)作为Map的键可以避免为我们自己的类实现hashCode()和equals()方法。
编程的时候接口优于实现。
底层的集合实际上是空的情况下,返回长度是0的集合或者是数组,不要返回null。
35、Enumeration接口和Iterator接口的区别有哪些?
Enumeration速度是Iterator的2倍,同时占用更少的内存。但是,Iterator远远比Enumeration安全,因为其他线程不能够修改正在被iterator遍历的集合里面的对象。同时,Iterator允许调用者删除底层集合里面的元素,这对Enumeration来说是不可能的。
36、HashSet和TreeSet有什么区别?
HashSet是由一个hash表来实现的,因此,它的元素是无序的。add(),remove(),contains()方法的时间复杂度是O(1)。
TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),remove(),contains()方法的时间复杂度是O(logn)。
37、Java中垃圾回收(GC)有什么目的?什么时候进行垃圾回收?
垃圾回收(GC)的目的是识别并且丢弃应用不再使用的对象来释放和重用资源。
38、System.gc()和Runtime.gc()会做什么事情?
这两个方法用来提示JVM要进行垃圾回收。但是,立即开始还是延迟进行垃圾回收是取决于JVM的。
39、finalize()方法什么时候被调用?析构函数(finalization)的目的是什么?
在释放对象占用的内存之前,垃圾收集器会调用对象的finalize()方法。一般建议在该方法中释放对象持有的资源。
40、如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?
不会,在下一个垃圾回收周期中,这个对象将是可被回收的。
41、Java堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)?
JVM的堆是运行时数据区,所有类的实例和数组都是在堆上分配内存。它在JVM启动的时候被创建。对象所占的堆内存是由自动内存管理系统也就是垃圾收集器回收。
堆内存是由存活和死亡的对象组成的。存活的对象是应用可以访问的,不会被垃圾回收。死亡的对象是应用不可访问尚且还没有被垃圾收集器回收掉的对象。一直到垃圾收集器把这些对象回收掉之前,他们会一直占据堆内存空间。
42、串行(serial)收集器和吞吐量(throughput)收集器的区别是什么?
吞吐量收集器使用并行版本的新生代垃圾收集器,它用于中等规模和大规模数据的应用程序。而串行收集器对大多数的小应用(在现代处理器上需要大概100M左右的内存)就足够了。
43、在Java中,对象什么时候可以被垃圾回收?
当对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收了。
44、JVM的永久代中会发生垃圾回收么?
垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免Full GC是非常重要的原因。
45、Java中的两种异常类型是什么?他们有什么区别?
Java中有两种异常:受检查的(checked)异常和不受检查的(unchecked)异常。不受检查的异常不需要在方法或者是构造函数上声明,就算方法或者是构造函数的执行可能会抛出这样的异常。而且不受检查的异常可以传播到方法或者是构造函数的外面。相反,受检查的异常必须要用throws语句在方法或者是构造函数上声明。
46、Java中Exception和Error有什么区别?
Exception和Error都是Throwable的子类。Exception用于用户程序可以捕获的异常情况。Error定义了不期望被用户程序捕获的异常。
47、Java 为什么是高效的 ( High Performance )?
因为 Java 使用 Just-In-Time (即时) 编译器。
把Java字节码转换成可以直接发送给处理器的指令。
48、列举出2个 IDE
Eclipse
IntelliJ IDEA
49、面向对象的特征有哪些?
- 封装
- 继承
- 多态
- 抽象
50、JDK JRE JVM?
- JDK
Java Development Kit 用作开发, 包含了JRE,编译器和其他的工具(比如: JavaDoc,Java调试器),可以让开发者开发、编译、执行Java应用程序。
- JRE
Java 运行时环境,是将要执行 Java 程序的 Java 虚拟机,可以想象成它是一个容器,JVM 是它的内容。 JRE = JVM + Java Packages Classes(like util, math, lang, awt, swing etc) + runtime libraries.
- JVM
Java virtual machine (Java 虚拟机) 是一个可以执行 Java 编译产生的 Java class 文件 (bytecode) 的虚拟机进程,是一个纯的运行环境。
51、什么是对象 (Object)?
- 对象是程序运行时的实体
- 它的状态存储在 fields (也就是变量)
- 行为是通过方法 (method) 实现的
- 方法上操作对象的内部的状态
- 方法是对象对对象的通信的主要手段
52、一个类是由哪些变量构成的?
- 本地变量:在方法体,构造体内部定义的变量,在方法结束的时候就被摧毁
- 实例变量:在类里但是不在方法里,在类被载入的时候被实例化
- 类变量:在类里但是不在方法里,加了 static 关键字,也可以叫做静态变量
53、静态变量和实例变量的区别?
- 在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
- 在程序运行时的区别:
- 实例变量属于某个对象的属性,必须创建了实例对象,才能使用这个实例变量。
- 静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就可以被使用了。
- 总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来使用。
单例模式的5种写法
单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点!
1.饿汉
public class Singleton{
private static final Singleton instance=new Singleton();//直接new出该类私有静态 实例化对象instance
private Singleton() {//私有构造方法
}
public static Singleton getInstance() {//对外提供调用该类的静态方法 为返回该类的实例化对象instance
return instance;
}
}
2.懒汉 加synchronized就是线程安全的推荐
public class 懒汉 {
private static 懒汉 instance;//只声明私有静态 实例化对象
private 懒汉() {//私有构造方法
}
public static synchronized 懒汉 getInstance() {
if (instance==null){//只有在实例化对象为空时
instance=new 懒汉();//new出该对象
}
return instance;//返回实例化对象
}
}
3、双重校验锁
public class Singleton {
private volatile static Singleton singleton;//声明为简单同步Volatile静态变量
private Singleton (){}//私有化构造方法
public static Singleton getSingleton() {//对外提供调用该类的方法
if (singleton == null) {//是空 同步字节码对象
synchronized (Singleton.class) {
if (singleton == null) {//空就new出该对象
singleton = new Singleton();
}
}
}
return singleton;//返回new出的对象
}
}
4、枚举
public enum Singleton22{
INSTANCE;//定义一个枚举元素,即为单例类的实例 要获取这个单例Singleton22.INSTANCE;
private Singleton22(){}//构造方法为私有 无参
}
5、静态内部类 推荐
class 静态内部类方式 {
private int ticket=100;//int变量票数为100
private 静态内部类方式() {//构造方法设为私有
}
private static class 静态内部类 {//创建静态内部类Singleton1
private static final 静态内部类方式 instance=new 静态内部类方式();//创建静态私有的单例 静态内部类方式对象instance
}
public static 静态内部类方式 getSingleton(){//对象提供调用该类的静态方法为 获取静态内部类的INSTANCE单例对象
return 静态内部类.instance;
}
}
原理
Spring struts2 hibernate MyBatis SpringMVC 原理
Spring原理
最核心的就是IOC,动态注入DI,利用java里的反射,让一个对象的创建不用new了,可以自动的生产。Spring就是在运行时,跟xml Spring的配置文件来动态的创建对象,和调用对象里的方法的 。其实就是利用java里的反射,反射其实就是在运行时动态的去创建、调用对象。 Spring还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象 进行监督和控制(也就是 在调用这类对象的具体方法的前后去调用你指定的 模块)从而达到对一个模块扩充的功能。这些都是通过 配置类达到的。 Spring目的:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说明管理的(Spring根据这些配置 内部通过反射去动态的组装对象) spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。 Spring里用的最经典的一个设计模式就是:模板方法模式。 Spring AOP与IOC 一、 IoC(Inversion of control): 控制反转 1、IoC: 概念:控制权由对象本身转向容器;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系 核心:bean工厂;在Spring中,bean工厂创建的各个实例称作bean 二、AOP(Aspect-Oriented Programming): 面向方面编程 1、 代理的两种方式: 静态代理: ? 针对每个具体类分别编写代理类; ? 针对一个接口编写一个代理类; 动态代理: 针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类 2、动态代理: 不用写代理类,虚拟机根据真实对象实现的接口产生一个类,通过类实例化一个动态代理,在实例化动态代理时将真实对象及装备注入到动态代理中,向客户端公开的是动态代理,当客户端调用动态代理方法时,动态代理根据类的反射得到真实对象的Method,调用装备的invoke方法,将动态代理、 Method、方法参数传与装备的invoke方法,invoke方法在唤起method方法前或后做一些处理。
1、产生动态代理的类:
java.lang.refect.Proxy
2、装备必须实现InvocationHandler接口实现invoke方法
3、反射 什么是类的返射?
通过类说明可以得到类的父类、实现的接口、内部类、构造函数、方法、属性并可以根据构造器实例化一个对象,唤起一个方法,取属性值,改属性值。如何得到一个类说明:
Class cls=类.class;
Class cls=对象.getClass();
Class.forName("类路径");
如何得到一个方法并唤起它?
Class cls=类.class;
Constructor cons=cls.getConstructor(new Class[]{String.class});
Object obj=cons.newInstance(new Object[]{"aaa"});
Method method=cls.getMethod("方法名",new Class[]{String.class,Integer.class});
method.invoke(obj,new Object[]{"aa",new Integer(1)});
4、spring的三种注入方式是什么? setter
interface
constructor
5、spring的核心接口及核类配置文件是什么? FactoryBean:工厂bean主要实现ioc/di
ApplicationContext ac=new FileXmlApplicationContext("applicationContext.xml");
Object obj=ac.getBean("id值");
6、Spring框架的7个模块 这里写图片描述 Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。 struts2原理
在struts2的应用中,从用户请求到服务器返回相应响应给用户端的过程中,包含了许多组件如:Controller、ActionProxy、ActionMapping、Configuration Manager、ActionInvocation、Inerceptor、Action、Result等。 这里写图片描述 这里写图片描述
(1) 客户端(Client)向Action发用一个请求(Request) (2) Container通过web.xml映射请求,并获得控制器(Controller)的名字 (3) 容器(Container)调用控制器(StrutsPrepareAndExecuteFilter或FilterDispatcher)。在Struts2.1以前调用FilterDispatcher,Struts2.1以后调用StrutsPrepareAndExecuteFilter (4) 控制器(Controller)通过ActionMapper获得Action的信息 (5) 控制器(Controller)调用ActionProxy (6) ActionProxy读取struts.xml文件获取action和interceptor stack的信息。 (7) ActionProxy把request请求传递给ActionInvocation (8) ActionInvocation依次调用action和interceptor (9) 根据action的配置信息,产生result (10) Result信息返回给ActionInvocation (11) 产生一个HttpServletResponse响应 (12) 产生的响应行为发送给客服端。
视图:主要由JSP生成页面完成视图,Struts提供丰富的JSP 标签库: Html,Bean,Logic,Template等,这有利于分开在Struts中,承担MVC中Controller角色的是一个Servlet,叫ActionServlet。ActionServlet是一个通用的控制组件。这个控制组件提供了处理所有发送到Struts的HTTP请求的入口点。它截取和分发这些请求到相应的动作类(这些动作类都是Action类的子类)。另外控制组件也负责用相应的请求参数填充 Action From(通常称之为FromBean),并传给动作类(通常称之为ActionBean)。动作类实现核心商业逻辑,它可以访问Java bean 或调用EJB。最后动作类把控制权传给后续的JSP 文件,后者生成视图。所有这些控制逻辑利用Struts-config.xml文件来配置。表现逻辑和程序逻辑。
模型:模型以一个或多个Java bean的形式存在。这些bean分为三类:Action Form、Action、JavaBean or EJB。Action Form通常称之为FormBean,封装了来自于Client的用户请求信息,如表单信息。Action通常称之为ActionBean,获取从ActionSevlet传来的FormBean,取出FormBean中的相关信息,并做出相关的处理,一般是调用Java Bean或EJB等。
流程:在Struts中,用户的请求一般以.do作为请求服务名,所有的.do请求均被指向ActionSevlet,ActionSevlet根据Struts-config.xml中的配置信息,将用户请求封装成一个指定名称的FormBean,并将此FormBean传至指定名称的ActionBean,由ActionBean完成相应的业务操作,如文件操作,数据库操作等。每一个*.do均有对应的FormBean名称和ActionBean名称,这些在Struts-config.xml中配置。
Struts2和struts1的比较 struts2相对于struts1来说简单了很多,并且功能强大了很多,我们可以从几个方面来看: 从体系结构来看:struts2大量使用拦截器来出来请求,从而允许与业务逻辑控制器 与 servlet-api分离,避免了侵入性;而struts1.x在action中明显的侵入了servlet-api. 从线程安全分析:struts2.x是线程安全的,每一个对象产生一个实例,避免了线程安全问题;而struts1.x在action中属于单线程。 性能方面:struts2.x测试可以脱离web容器,而struts1.x依赖servlet-api,测试需要依赖web容器。 请求参数封装对比:struts2.x使用ModelDriven模式,这样我们 直接 封装model对象,无需要继承任何struts2的基类,避免了侵入性。 标签的优势:标签库几乎可以完全替代JSTL的标签库,并且 struts2.x支持强大的ognl表达式。 当然,struts2和struts1相比,在 文件上传,数据校验 等方面也 方便了好多。在这就不详谈了。
hibernate原理
hibernate 简介: hibernate是一个开源框架,它是对象关联关系映射的框架,它对JDBC做了轻量级的封装,而我们java程序员可以使用面向对象的思想来操纵数据库。 hibernate核心接口 session:负责被持久化对象CRUD操作 sessionFactory:负责初始化hibernate,创建session对象 configuration:负责配置并启动hibernate,创建SessionFactory Transaction:负责事物相关的操作 Query和Criteria接口:负责执行各种数据库查询
hibernate工作原理: 1.通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件 2.由hibernate.cfg.xml中的读取并解析映射信息 3.通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory 4.Session session = sf.openSession();//打开Sesssion 5.Transaction tx = session.beginTransaction();//创建并启动事务Transation 6.persistent operate操作数据,持久化操作 7.tx.commit();//提交事务 8.关闭Session 9.关闭SesstionFactory
为什么要用hibernate:
- 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
- Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
- hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
- hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
Hibernate是如何延迟加载?get与load的区别
对于Hibernate get方法,Hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据 库中没有就返回null。
Hibernate load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),分情况讨论:
(1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
(2)若为false,就跟Hibernateget方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
这里get和load有两个重要区别:
如果未能发现符合条件的记录,Hibernate get方法返回null,而load方法会抛出一个ObjectNotFoundException。
load方法可返回没有加载实体数据的代 理类实例,而get方法永远返回有实体数据的对象。
总之对于get和load的根本区别,一句话,hibernate对于 load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方 法,hibernate一定要获取到真实的数据,否则返回null。
Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都是对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、
说下Hibernate的缓存机制:
Hibernate缓存的作用: Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据 Hibernate缓存分类: Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存 Hibernate一级缓存又称为“Session的缓存”,它是内置的,意思就是说,只要你使用hibernate就必须使用session缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。在第一级缓存中,持久化类的每个实例都具有唯一的OID。 Hibernate二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。第二级缓存是可选的,是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件。
什么样的数据适合存放到第二级缓存中? 1 很少被修改的数据 2 不是很重要的数据,允许出现偶尔并发的数据 3 不会被并发访问的数据 4 常量数据 不适合存放到第二级缓存的数据? 1经常被修改的数据 2 .绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发 3 与其他应用共享的数据。
Hibernate查找对象如何应用缓存? 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;如果都查不到,再查询数据库,把结果按照ID放入到缓存 删除、更新、增加数据的时候,同时更新缓存
Hibernate管理缓存实例 无论何时,我们在管理Hibernate缓存(Managing the caches)时,当你给save()、update()或saveOrUpdate()方法传递一个对象时,或使用load()、 get()、list()、iterate() 或scroll()方法获得一个对象时, 该对象都将被加入到Session的内部缓存中。 当随后flush()方法被调用时,对象的状态会和数据库取得同步。 如果你不希望此同步操作发生,或者你正处理大量对象、需要对有效管理内存时,你可以调用evict() 方法,从一级缓存中去掉这些对象及其集合。
Hibernate的查询方式 Sql、Criteria,object comptosition Hql: 1、 属性查询 2、 参数查询、命名参数查询 3、 关联查询 4、 分页查询 5、 统计函数
如何优化Hibernate? 1.使用双向一对多关联,不使用单向一对多 2.灵活使用单向一对多关联 3.不用一对一,用多对一取代 4.配置对象缓存,不使用集合缓存 5.一对多集合使用Bag,多对多集合使用Set 6. 继承类使用显式多态 7. 表字段要少,表关联不要怕多,有二级缓存撑腰
hibernate的开发步骤: 开发步骤 1)搭建好环境 引入hibernate最小的jar包 准备Hibernate.cfg.xml启动配置文件 2)写实体类(pojo) 3)为实体类写映射文件”User.hbm.xml” 在hibernate.cfg.xml添加映射的实体 4)创建库表 5)写测试类 获得Configuration 创建SessionFactory 打开Session 开启事务 使用session操作数据 提交事务 关闭资源
MyBatis原理
什么是Mybatis
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。 MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手工设置参数以及抽取结果集。MyBatis 使用简单的 XML 或注解来配置和映射基本体,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。 MyBatis是iBatis的升级版,用法有很多的相似之处,但是MyBatis进行了重要的改进。例如: 1、Mybatis实现了接口绑定,使用更加方便。
在ibatis2.x中我们需要在DAO的实现类中指定具体对应哪个xml映射文件, 而Mybatis实现了DAO接口与xml映射文件的绑定,自动为我们生成接口的具体实现,使用起来变得更加省事和方便。 2、对象关系映射的改进,效率更高
3、MyBatis采用功能强大的基于OGNL的表达式来消除其他元素。
这里写图片描述
原理详解: MyBatis应用程序根据XML配置文件创建SqlSessionFactory,SqlSessionFactory在根据配置,配置来源于两个地方,一处是配置文件,一处是Java代码的注解,获取一个SqlSession。SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句,完成对数据的增删改查和事务提交等,用完之后关闭SqlSession。
MyBatis的优缺点
优点: 1、简单易学 mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
2、灵活 mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
3、解除sql与程序代码的耦合 通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
4、提供映射标签,支持对象与数据库的orm字段关系映射
5、提供对象关系映射标签,支持对象关系组建维护
6、提供xml标签,支持编写动态sql。
缺点:
1、编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
2、SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
3、框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
4、二级缓存机制不佳
总结
mybatis的优点同样是mybatis的缺点,正因为mybatis使用简单,数据的可靠性、完整性的瓶颈便更多依赖于程序员对sql的使用水平上了。sql写在xml里,虽然方便了修改、优化和统一浏览,但可读性很低,调试也非常困难,也非常受限。 mybatis没有hibernate那么强大,但是mybatis最大的优点就是简单小巧易于上手,方便浏览修改sql语句。 SpringMVC
SpringMVC框架介绍
- Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。 Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,可以选择是使用内置的 Spring Web 框架还是 Struts 这样的 Web 框架。通过策略接口,Spring 框架是高度可配置的,而且包含多种视图技术,例如 JavaServer Pages(JSP)技术、Velocity、Tiles、iText 和 POI。Spring MVC 框架并不知道使用的视图,所以不会强迫您只使用 JSP 技术。 Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。
- Spring的MVC框架主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。 SpringMVC原理图 这里写图片描述 SpringMVC接口解释 DispatcherServlet接口: Spring提供的前端控制器,所有的请求都有经过它来统一分发。在DispatcherServlet将请求分发给Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具体的Controller。 HandlerMapping接口: 能够完成客户请求到Controller映射。 Controller接口: 需要为并发用户处理上述请求,因此实现Controller接口时,必须保证线程安全并且可重用。 Controller将处理用户请求,这和Struts Action扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。 从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。 ViewResolver接口: Spring提供的视图解析器(ViewResolver)在Web应用中查找View对象,从而将相应结果渲染给客户。
ArrayList和LinkedList、Vector的区别?
答:总得来说可以理解为:.
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据
1.面向对象和面向过程的区别
面向过程 优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。 缺点:没有面向对象易维护、易复用、易扩展 面向对象 优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护 缺点:性能比面向过程低
2.Java的四个基本特性(抽象、封装、继承,多态)
抽象:就是把现实生活中的某一类东西提取出来,用程序代码表示,我们通常叫做类或者接口。抽象包括两个方面:一个是数据抽象,一个是过程抽象。数据抽象也就是对象的属性。过程抽象是对象的行为特征。 封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行封装隐藏。封装分为属性的封装和方法的封装。 继承:是对有着共同特性的多类事物,进行再抽象成一个类。这个类就是多类事物的父类。父类的意义在于抽取多类事物的共性。 多态:允许不同类的对象对同一消息做出响应。方法的重载、类的覆盖正体现了多态。
3.重载和重写的区别
overide重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修overload饰符可以不同,发生在编译时。 重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类;如果父类方法访问修饰符为private则子类中就不是重写。
4.构造器Constructor是否可被override
构造器不能被重写,不能用static修饰构造器,只能用public private protected这三个权限修饰符,且不能有返回语句。
5.访问控制符public,protected,private,以及默认的区别
private只有在本类中才能访问; public在任何地方都能访问; protected在同包内的类及包外的子类能访问; 默认不写在同包内能访问。default 6是否可以继承String类# String类是final类故不可以继承,一切由final修饰过的都不能继承。
7.String和StringBuffer、StringBuilder的区别
可变性 String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[] value,这两种对象都是可变的。 线程安全性 String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。 性能 每次对String 类型进行改变的时候,都会生成一个新的String 对象,然后将指针指向新的String 对象。StringBuffer每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
8.hashCode和equals方法的关系
equals相等,hashcode必相等;hashcode相等,equals可能不相等。
9.抽象类和接口的区别
语法层次 抽象类和接口分别给出了不同的语法定义。 设计层次 抽象层次不同,抽象类是对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。抽象类是自底向上抽象而来的,接口是自顶向下设计出来的。 跨域不同 抽象类所体现的是一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is-a" 关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上是一致的,仅仅是实现了接口定义的契约而已,“like-a"的关系。
10.自动装箱与拆箱
装箱:将基本类型用它们对应的引用类型包装起来; 拆箱:将包装类型转换为基本数据类型; Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率,由编译器来完成,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。
11.什么是泛型、为什么要使用以及泛型擦除
泛型,即“参数化类型”。 创建集合时就指定集合元素的类型,该集合只能保存其指定类型的元素,避免使用强制类型转换。 Java编译器生成的字节码是不包涵泛型信息的,泛型类型信息将在编译处理是被擦除,这个过程即类型擦除。泛型擦除可以简单的理解为将泛型java代码转换为普通java代码,只不过编译器更直接点,将泛型java代码直接转换成普通java字节码。 类型擦除的主要过程如下: 1).将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。 2).移除所有的类型参数。
12.Java中的集合类及关系图
List和Set继承自Collection接口。 Set无序不允许元素重复。HashSet和TreeSet是两个主要的实现类。 List有序且允许元素重复。ArrayList、LinkedList和Vector是三个主要的实现类。 Map也属于集合系统,但和Collection接口没关系。Map是key对value的映射集合,其中key列就是一个集合。key不能重复,但是value可以重复。HashMap、TreeMap和Hashtable是三个主要的实现类。 SortedSet和SortedMap接口对元素按指定规则排序,SortedMap是对key列进行排序。
13.HashMap实现原理
具体原理参考文章: http://zhangshixi.iteye.com/blog/672697 http://www.admin10000.com/document/3322.html
14.HashTable实现原理
具体原理参考文章: http://www.cnblogs.com/skywang12345/p/3310887.html http://blog.csdn.net/chdjj/article/details/38581035
15.HashMap和HashTable区别
1).HashTable的方法前面都有synchronized来同步,是线程安全的;HashMap未经同步,是非线程安全的。 2).HashTable不允许null值(key和value都不可以) ;HashMap允许null值(key和value都可以)。 3).HashTable有一个contains(Object value)功能和containsValue(Object value)功能一样。 4).HashTable使用Enumeration进行遍历;HashMap使用Iterator进行遍历。 5).HashTable中hash数组默认大小是11,增加的方式是old*2+1;HashMap中hash数组的默认大小是16,而且一定是2的指数。 6).哈希值的使用不同,HashTable直接使用对象的hashCode; HashMap重新计算hash值,而且用与代替求模。
16.ArrayList和vector区别
ArrayList和Vector都实现了List接口,都是通过数组实现的。 Vector是线程安全的,而ArrayList是非线程安全的。 List第一次创建的时候,会有一个初始大小,随着不断向List中增加元素,当List 认为容量不够的时候就会进行扩容。Vector缺省情况下自动增长原来一倍的数组长度,ArrayList增长原来的50%。
17.ArrayList和LinkedList区别及使用场景
区别 ArrayList底层是用数组实现的,可以认为ArrayList是一个可改变大小的数组。随着越来越多的元素被添加到ArrayList中,其规模是动态增加的。 LinkedList底层是通过双向链表实现的, LinkedList和ArrayList相比,增删的速度较快。但是查询和修改值的速度较慢。同时,LinkedList还实现了Queue接口,所以他还提供了offer(), peek(), poll()等方法。 使用场景 LinkedList更适合从中间插入或者删除(链表的特性)。 ArrayList更适合检索和在末尾插入或删除(数组的特性)。
18.Collection和Collections的区别
java.util.Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。 java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
19.Concurrenthashmap实现原理
具体原理参考文章: http://www.cnblogs.com/ITtangtang/p/3948786.html http://ifeve.com/concurrenthashmap/
20.Error、Exception区别
Error类和Exception类的父类都是throwable类,他们的区别是: Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。 Exception类表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。
21.Unchecked
Exception和Checked Exception,各列举几个# Unchecked Exception: a. 指的是程序的瑕疵或逻辑错误,并且在运行时无法恢复。 b. 包括Error与RuntimeException及其子类,如:OutOfMemoryError, UndeclaredThrowableException, IllegalArgumentException, IllegalMonitorStateException, NullPointerException, IllegalStateException, IndexOutOfBoundsException等。 c. 语法上不需要声明抛出异常。
Checked Exception: a. 代表程序不能直接控制的无效外界情况(如用户输入,数据库问题,网络异常,文件丢失等) b. 除了Error和RuntimeException及其子类之外,如:ClassNotFoundException, NamingException, ServletException, SQLException, IOException等。 c. 需要try catch处理或throws声明抛出异常。
22.Java中如何实现代理机制(JDK、CGLIB)
JDK动态代理:代理类和目标类实现了共同的接口,用到InvocationHandler接口。 CGLIB动态代理:代理类是目标类的子类,用到MethodInterceptor接口。
23.多线程的实现方式
继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。
24.线程的状态转换
20140828202610671.jpg
25.如何停止一个线程
参考文章: http://www.cnblogs.com/greta/p/5624839.html
26.什么是线程安全
线程安全就是多线程访问同一代码,不会产生不确定的结果。
27.如何保证线程安全
对非安全的代码进行加锁控制; 使用线程安全的类; 多线程并发情况下,线程共享的变量改为方法级的局部变量。
28.synchronized如何使用
synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 1). 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; 2). 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 3). 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象; 4). 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
29.synchronized和Lock的区别
主要相同点:Lock能完成synchronized所实现的所有功能 主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。Lock的锁定是通过代码实现的,而synchronized是在JVM层面上实现的,synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。Lock锁的范围有局限性,块范围,而synchronized可以锁住块、对象、类。
30.多线程如何进行信息交互
void notify() 唤醒在此对象监视器上等待的单个线程。 void notifyAll() 唤醒在此对象监视器上等待的所有线程。 void wait() 导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法。 void wait(long timeout) 导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者超过指定的时间量。 void wait(long timeout, int nanos) 导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。
31.sleep和wait的区别(考察的方向是是否会释放锁)
sleep()方法是Thread类中方法,而wait()方法是Object类中的方法。 sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态,在调用sleep()方法的过程中,线程不会释放对象锁。而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备。
32.多线程与死锁
死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 产生死锁的原因: 一.因为系统资源不足。 二.进程运行推进的顺序不合适。 三.资源分配不当。
33.如何才能产生死锁
产生死锁的四个必要条件: 一.互斥条件:所谓互斥就是进程在某一时间内独占资源。 二.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 三.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。 四.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
34.死锁的预防
打破产生死锁的四个必要条件中的一个或几个,保证系统不会进入死锁状态。 一.打破互斥条件。即允许进程同时访问某些资源。但是,有的资源是不允许被同时访问的,像打印机等等,这是由资源本身的属性所决定的。所以,这种办法并无实用价值。 二.打破不可抢占条件。即允许进程强行从占有者那里夺取某些资源。就是说,当一个进程已占有了某些资源,它又申请新的资源,但不能立即被满足时,它必须释放所占有的全部资源,以后再重新申请。它所释放的资源可以分配给其它进程。这就相当于该进程占有的资源被隐蔽地强占了。这种预防死锁的方法实现起来困难,会降低系统性能。 三.打破占有且申请条件。可以实行资源预先分配策略。即进程在运行前一次性地向系统申请它所需要的全部资源。如果某个进程所需的全部资源得不到满足,则不分配任何资源,此进程暂不运行。只有当系统能够满足当前进程的全部资源需求时,才一次性地将所申请的资源全部分配给该进程。由于运行的进程已占有了它所需的全部资源,所以不会发生占有资源又申请资源的现象,因此不会发生死锁。 四.打破循环等待条件,实行资源有序分配策略。采用这种策略,即把资源事先分类编号,按号分配,使进程在申请,占用资源时不会形成环路。所有进程对资源的请求必须严格按资源序号递增的顺序提出。进程占用了小号资源,才能申请大号资源,就不会产生环路,从而预防了死锁。
35.什么叫守护线程,用什么方法实现守护线程
守护线程是为其他线程的运行提供服务的线程。 setDaemon(boolean on)方法可以方便的设置线程的Daemon模式,true为守护模式,false为用户模式。
36.Java线程池技术及原理
参考文章: http://www.importnew.com/19011.html http://www.cnblogs.com/dolphin0520/p/3932921.html
37.java并发包concurrent及常用的类
这个内容有点多,参考文章: 并发包诸类概览: http://www.raychase.net/1912 线程池: http://www.cnblogs.com/dolphin0520/p/3932921.html 锁: http://www.cnblogs.com/dolphin0520/p/3923167.html 集合: http://www.cnblogs.com/huangfox/archive/2012/08/16/2642666.html
38.volatile关键字
用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操作。 Java语言中的volatile变量可以被看作是一种“程度较轻的 synchronized”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是synchronized的一部分。锁提供了两种主要特性:互斥(mutual exclusion)和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的,如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。Volatile变量具有synchronized的可见性特性,但是不具备原子特性。这就是说线程能够自动发现volatile 变量的最新值。 要使volatile变量提供理想的线程安全,必须同时满足下面两个条件:对变量的写操作不依赖于当前值;该变量没有包含在具有其他变量的不变式中。 第一个条件的限制使volatile变量不能用作线程安全计数器。虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作,必须以原子方式执行,而volatile不能提供必须的原子特性。实现正确的操作需要使x 的值在操作期间保持不变,而volatile 变量无法实现这点。 每一个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。
read and load 从主存复制变量到当前工作内存 use and assign 执行代码,改变共享变量值 store and write 用工作内存数据刷新主存相关内容 其中use and assign 可以多次出现,但是这一些操作并不是原子性,也就是在read load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果会和预期不一样。
39.Java中的NIO,BIO,AIO分别是什么
BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。 NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。 AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理.AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。
40.IO和NIO区别
一.IO是面向流的,NIO是面向缓冲区的。 二.IO的各种流是阻塞的,NIO是非阻塞模式。 三.Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
41.序列化与反序列化
把对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为对象的过程称为对象的反序列化。 对象的序列化主要有两种用途: 一.把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中; 二.在网络上传送对象的字节序列。 当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
42.常见的序列化协议有哪些
Protobuf, Thrift, Hessian, Kryo
43.内存溢出和内存泄漏的区别
内存溢出是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory。 内存泄漏是指分配出去的内存不再使用,但是无法回收。
44.Java内存模型及各个区域的OOM,如何重现OOM
这部分内容很重要,详细阅读《深入理解Java虚拟机》,也可以详细阅读这篇文章 http://hllvm.group.iteye.com/group/wiki/2857-JVM
45.出现OOM如何解决
一. 可通过命令定期抓取heap dump或者启动参数OOM时自动抓取heap dump文件。 二. 通过对比多个heap dump,以及heap dump的内容,分析代码找出内存占用最多的地方。 三. 分析占用的内存对象,是否是因为错误导致的内存未及时释放,或者数据过多导致的内存溢出。
46.用什么工具可以查出内存泄漏
一. Memory Analyzer-是一款开源的JAVA内存分析软件,查找内存泄漏,能容易找到大块内存并验证谁在一直占用它,它是基于Eclipse RCP(Rich Client Platform),可以下载RCP的独立版本或者Eclipse的插件。 二. JProbe-分析Java的内存泄漏。 三.JProfiler-一个全功能的Java剖析工具,专用于分析J2SE和J2EE应用程序。它把CPU、执行绪和内存的剖析组合在一个强大的应用中,GUI可以找到效能瓶颈、抓出内存泄漏、并解决执行绪的问题。 四. JRockit-用来诊断Java内存泄漏并指出根本原因,专门针对Intel平台并得到优化,能在Intel硬件上获得最高的性能。 五. YourKit-.NET & Java Profiling业界领先的Java和.NET程序性能分析工具。 六.AutomatedQA -AutomatedQA的获奖产品performance profiling和memory debugging工具集的下一代替换产品,支持Microsoft,Borland, Intel, Compaq 和 GNU编译器。可以为.NET和Windows程序生成全面细致的报告,从而帮助您轻松隔离并排除代码中含有的性能问题和内存/资源泄露问题。支持.Net 1.0,1.1,2.0,3.0和Windows 32/64位应用程序。 七.Compuware DevPartner Java Edition-包含Java内存检测,代码覆盖率测试,代码性能测试,线程死锁,分布式应用等几大功能模块
47.Java内存管理及回收算法
阅读这篇文章: http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html
48.Java类加载器及如何加载类(双亲委派)
阅读文章: https://www.ibm.com/developerworks/cn/java/j-lo-classloader/(推荐) http://blog.csdn.net/zhoudaxia/article/details/35824249
49.xml解析方式
一.DOM(JAXP Crimson解析器) 二.SAX 三.JDOM 四.DOM4J 区别: 一.DOM4J性能最好,连Sun的JAXM也在用DOM4J。目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J. 二.JDOM和DOM在性能测试时表现不佳,在测试10M 文档时内存溢出。在小文档情况下还值得考虑使用DOM和JDOM。虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C 推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。 三.SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。
50.Statement和PreparedStatement之间的区别
一.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程 二.使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement 对象的开销比Statement大,对于一次性操作并不会带来额外的好处。 三.statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译得, preparedstatement支持批处理 四. 代码片段1: String updateString = “UPDATE COFFEES SET SALES = 75 " + “WHERE COF_NAME LIKE ′Colombian′”; stmt.executeUpdate(updateString); 代码片段2: PreparedStatement updateSales = con.prepareStatement(“UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? “); updateSales.setInt(1, 75); updateSales.setString(2, “Colombian”); updateSales.executeUpdate(); 片断2和片断1的区别在于,后者使用了PreparedStatement对象,而前者是普通的Statement对象。PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。 这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需更改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。如果仅仅执行了一次的话,它应该和普通的对象毫无差异,体现不出它预编译的优越性。 五.执行许多SQL语句的JDBC程序产生大量的Statement和PreparedStatement对象。通常认为PreparedStatement对象比Statement对象更有效,特别是如果带有不同参数的同一SQL语句被多次执行的时候。PreparedStatement对象允许数据库预编译SQL语句,这样在随后的运行中可以节省时间并增加代码的可读性。 然而,在Oracle环境中,开发人员实际上有更大的灵活性。当使用Statement或PreparedStatement对象时,Oracle数据库会缓存SQL语句以便以后使用。在一些情况下,由于驱动器自身需要额外的处理和在Java应用程序和Oracle服务器间增加的网络活动,执行PreparedStatement对象实际上会花更长的时间。 然而,除了缓冲的问题之外,至少还有一个更好的原因使我们在企业应用程序中更喜欢使用PreparedStatement对象,那就是安全性。传递给PreparedStatement对象的参数可以被强制进行类型转换,使开发人员可以确保在插入或查询数据时与底层的数据库格式匹配。 当处理公共Web站点上的用户传来的数据的时候,安全性的问题就变得极为重要。传递给PreparedStatement的字符串参数会自动被驱动器忽略。最简单的情况下,这就意味着当你的程序试着将字符串“D’Angelo”插入到VARCHAR2中时,该语句将不会识别第一个“,”,从而导致悲惨的失败。几乎很少有必要创建你自己的字符串忽略代码。 在Web环境中,有恶意的用户会利用那些设计不完善的、不能正确处理字符串的应用程序。特别是在公共Web站点上,在没有首先通过PreparedStatement对象处理的情况下,所有的用户输入都不应该传递给SQL语句。此外,在用户有机会修改SQL语句的地方,如HTML的隐藏区域或一个查询字符串上,SQL语句都不应该被显示出来。
51.servlet生命周期及各个方法
参考文章 http://www.cnblogs.com/xuekyo/archive/2013/02/24/2924072.html
52.servlet中如何自定义filter
参考文章 http://www.cnblogs.com/javawebsoa/archive/2013/07/31/3228858.html
53.JSP原理
参考文章 http://blog.csdn.net/hanxuemin12345/article/details/23831645
54.JSP和Servlet的区别
(1)JSP经编译后就变成了“类servlet”。 (2)JSP由HTML代码和JSP标签构成,更擅长页面显示;Servlet更擅长流程控制。 (3)JSP中嵌入JAVA代码,而Servlet中嵌入HTML代码。
55.JSP的动态include和静态include
(1)动态include用jsp:include动作实现,如<jsp:include page=“abc.jsp” flush=“true” />,它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数。会先解析所要包含的页面,解析后和主页面合并一起显示,即先编译后包含。 (2)静态include用include伪码实现,不会检查所含文件的变化,适用于包含静态页面,如<%@ include file=“qq.htm” %>,不会提前解析所要包含的页面,先把要显示的页面包含进来,然后统一编译,即先包含后编译。
56.Struts中请求处理过程
参考文章 http://www.cnblogs.com/liuling/p/2013-8-10-01.html
57.MVC概念
参考文章 http://www.cnblogs.com/scwyh/articles/1436802.html
58.Springmvc与Struts区别
参考文章: http://blog.csdn.net/tch918/article/details/38305395 http://blog.csdn.net/chenleixing/article/details/44570681
59.Hibernate/Ibatis两者的区别
参考文章 http://blog.csdn.net/firejuly/article/details/8190229
60.Hibernate一级和二级缓存
参考文章 http://blog.csdn.net/windrui/article/details/23165845
61.简述Hibernate常见优化策略
参考文章 http://blog.csdn.net/shimiso/article/details/8819114
62.Springbean的加载过程(推荐看Spring的源码)
参考文章 http://geeekr.com/read-spring-source-1-how-to-load-bean/
63.Springbean的实例化(推荐看Spring的源码)
参考文章 http://geeekr.com/read-spring-source-two-beans-initialization/
64.Spring如何实现AOP和IOC(推荐看Spring的源码)
参考文章 http://www.360doc.com/content/15/0116/21/12385684_441408260.shtml
65.Springbean注入方式
参考文章 http://blessht.iteye.com/blog/1162131
66.Spring的事务管理
这个主题的参考文章没找到特别好的, http://blog.csdn.net/trigl/article/details/50968079这个还可以。
67.Spring事务的传播特性
参考文章 http://blog.csdn.net/lfsf802/article/details/9417095
68.springmvc原理
参考文章 http://blog.sina.com.cn/s/blog_7ef0a3fb0101po57.html
69.springmvc用过哪些注解
参考文章 http://aijuans.iteye.com/blog/2160141
70.Restful有几种请求
参考文章, http://www.infoq.com/cn/articles/designing-restful-http-apps-roth,该篇写的比较全。
71.Restful好处
(1)客户-服务器:客户-服务器约束背后的原则是分离关注点。通过分离用户接口和数据存储这两个关注点,改善了用户接口跨多个平台的可移植性;同时通过简化服务器组件,改善了系统的可伸缩性。 (2)无状态:通信在本质上是无状态的,改善了可见性、可靠性、可伸缩性. (3)缓存:改善了网络效率减少一系列交互的平均延迟时间,来提高效率、可伸缩性和用户可觉察的性能。 (4)统一接口:REST架构风格区别于其他基于网络的架构风格的核心特征是,它强调组件之间要有一个统一的接口。
72.Tomcat,Apache,JBoss的区别
Apache:HTTP服务器(WEB服务器),类似IIS,可以用于建立虚拟站点,编译处理静态页面,可以支持SSL技术,支持多个虚拟主机等功能。 Tomcat:Servlet容器,用于解析jsp,Servlet的Servlet容器,是高效,轻量级的容器。缺点是不支持EJB,只能用于java应用。 Jboss:应用服务器,运行EJB的J2EE应用服务器,遵循J2EE规范,能够提供更多平台的支持和更多集成功能,如数据库连接,JCA等,其对Servlet的支持是通过集成其他Servlet容器来实现的,如tomcat和jetty。
73.memcached和redis的区别
(1)性能对比:由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。 (2)内存使用效率对比:使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。 (3)Redis支持服务器端的数据操作:Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。
74.如何理解分布式锁
参考文章: http://blog.csdn.net/zheng0518/article/details/51607063 http://blog.csdn.net/nicewuranran/article/details/51730131。
75.你知道的开源协议有哪些
常见的开源协议有GPL、LGPL、BSD、Apache Licence vesion 2.0、MIT,详细内容参考文章: http://blog.jobbole.com/44175/、http://www.ruanyifeng.com/blog/2011/05/how_to_choose_free_software_licenses.html。
76.json和xml区别
XML: (1)应用广泛,可扩展性强,被广泛应用各种场合; (2)读取、解析没有JSON快; (3)可读性强,可描述复杂结构。 JSON: (1)结构简单,都是键值对; (2)读取、解析速度快,很多语言支持; (3)传输数据量小,传输速率大大提高; (4)描述复杂结构能力较弱。
77.设计模式
参考文章: http://www.cnblogs.com/beijiguangyong/archive/2010/11/15/2302807.html#_Toc281750445。
78.设计模式的六大原则
参考文章 http://www.uml.org.cn/sjms/201211023.asp。
79.用一个设计模式写一段代码或画出一个设计模式的UML
参考文章 http://www.cnblogs.com/beijiguangyong/archive/2010/11/15/2302807.html#_Toc281750445
80.高内聚,低耦合方面的理解
参考文章 http://my.oschina.net/heweipo/blog/423235。
81.深度优先和广度优先算法
推荐看书籍复习!可参考文章: http://blog.163.com/zhoumhan_0351/blog/static/3995422720098342257387/ http://blog.163.com/zhoumhan_0351/blog/static/3995422720098711040303/ http://blog.csdn.net/andyelvis/article/details/1728378 http://driftcloudy.iteye.com/blog/782873
82.排序算法及对应的时间复杂度和空间复杂度
推荐看书籍复习!可参考文章: http://www.cnblogs.com/liuling/p/2013-7-24-01.html http://blog.csdn.net/cyuyanenen/article/details/51514443 http://blog.csdn.net/whuslei/article/details/6442755
83.排序算法编码实现
参考 http://www.cnblogs.com/liuling/p/2013-7-24-01.html
84.查找算法
参考 http://sanwen8.cn/p/142Wbu5.html
85.B+树
参考 http://www.cnblogs.com/syxchina/archive/2011/03/02/2197251.html
86.KMP算法
推荐阅读数据复习!参考 http://www.cnblogs.com/c-cloud/p/3224788.html
87.hash算法及常用的hash算法
参考 http://www.360doc.com/content/13/0409/14/10384031_277138819.shtml
88.如何判断一个单链表是否有环
参考文章: http://www.jianshu.com/p/0e28d31600dd http://my.oschina.net/u/2391658/blog/693277?p={{totalPage}}
89.队列、栈、链表、树、堆、图
推荐阅读数据复习!
90.linux常用命令
参考 http://www.jianshu.com/p/03cfc1a721b8
91.如何查看内存使用情况
参考 http://blog.csdn.net/windrui/article/details/40046413
92.Linux下如何进行进程调度
推荐阅读书籍复习,参考文章: http://www.cnblogs.com/zhaoyl/archive/2012/09/04/2671156.html http://blog.csdn.net/rainharder/article/details/7975387
93.产生死锁的必要条件
参考 http://blog.sina.com.cn/s/blog_5e3604840100ddgq.html
94.死锁预防
参考 http://blog.sina.com.cn/s/blog_5e3604840100ddgq.html
95.数据库范式
参考 http://www.360doc.com/content/12/0712/20/5287961_223855037.shtml
96.数据库事务隔离级别
参考 http://blog.csdn.net/fg2006/article/details/6937413
97.数据库连接池的原理
参考 http://blog.csdn.net/shuaihj/article/details/14223015
98.乐观锁和悲观锁
参考 http://www.open-open.com/lib/view/open1452046967245.html
99.如何实现不同数据库的数据查询分页
参考 http://blog.csdn.net/yztezhl/article/details/20489387
100.SQL注入的原理,如何预防
参考 https://www.aliyun.com/zixun/content/3_15_245099.html
101.数据库索引的实现(B+树介绍、和B树、R树区别)
参考文章: http://blog.csdn.net/kennyrose/article/details/7532032 http://www.xuebuyuan.com/2216918.html
102.SQL性能优化
参考文章: http://database.51cto.com/art/200904/118526.htm http://www.cnblogs.com/rootq/archive/2008/11/17/1334727.html
103.数据库索引的优缺点以及什么时候数据库索引失效
参考文章: http://www.cnblogs.com/mxmbk/articles/5226344.html http://www.cnblogs.com/simplefrog/archive/2012/07/15/2592527.html http://www.open-open.com/lib/view/open1418476492792.html http://blog.csdn.net/colin_liu2009/article/details/7301089 http://www.cnblogs.com/hongfei/archive/2012/10/20/2732589.html
104.Redis的数据类型
参考 http://blog.csdn.net/hechurui/article/details/49508735
105.OSI七层模型以及TCP/IP四层模型
参考文章: http://blog.csdn.net/sprintfwater/article/details/8751453 http://www.cnblogs.com/commanderzhu/p/4821555.html http://blog.csdn.net/superjunjin/article/details/7841099
106.HTTP和HTTPS区别
参考: http://blog.csdn.net/mingli198611/article/details/8055261 http://www.mahaixiang.cn/internet/1233.html
107.HTTP报文内容
参考文章: https://yq.aliyun.com/articles/44675 http://www.cnblogs.com/klguang/p/4618526.html http://my.oschina.net/orgsky/blog/387759
108.get提交和post提交的区别
参考文章: http://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html http://www.jellythink.com/archives/806
109.get提交是否有字节限制,如果有是在哪限制的
参考 http://www.jellythink.com/archives/806
110.TCP的三次握手和四次挥手
阅读 http://www.jianshu.com/p/f7d1010fa603
111.session和cookie的区别
参考 http://www.cnblogs.com/shiyangxt/archive/2008/10/07/1305506.html
112.HTTP请求中Session实现原理
参考 http://blog.csdn.net/zhq426/article/details/2992488
113.redirect与forward区别
参考 http://www.cnblogs.com/wxgblogs/p/5602849.html
114.TCP和UDP区别
参考 http://www.cnblogs.com/bizhu/archive/2012/05/12/2497493.html
115.DDos攻击及预防
参考文章: http://blog.csdn.net/huwei2003/article/details/45476743 http://www.leiphone.com/news/201509/9zGlIDvLhwguqOtg.html
一、面试题基础总结
1、 JVM结构原理、GC工作机制详解
答:具体参照: JVM结构、GC工作机制详解 ,说到GC,记住两点:1、GC是负责回收所有无任何引用对象的内存空间。 注意:垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象本身,2、GC回收机制的两种算法,a、引用计数法 b、可达性分析算法( 这里的可达性,大家可以看基础2 Java对象的什么周期),至于更详细的GC算法介绍,大家可以参考: Java GC机制算法
2、Java对象的生命周期
答:创建阶段 、 应用阶段 、不可见阶段 、不可达阶段 、收集阶段 、终结阶段、 对象空间重新分配阶段等等,具体参照: Java 对象的生命周期
3、Map或者HashMap的存储原理
答:HashMap是由数组+链表的一个结构组成,具体参照: HashMap的实现原理
4、当数据表中A、B字段做了组合索引,那么单独使用A或单独使用B会有索引效果吗?(使用like查询如何有索引效果)
答:看A、B两字段做组合索引的时候,谁在前面,谁在后面,如果A在前,那么单独使用A会有索引效果,单独使用B则没有,反之亦然。同理,使用like模糊查询时,如果只是使用前面%,那么有索引效果,如果使用双%号匹配,那么则无索引效果
5、数据库存储日期格式时,如何考虑时区转换问题?
答:使用TimeStamp , 原因参照: Java编程中遇到的时区转换问题
6、Java Object类中有哪些方法?
答: Object有哪些方法
7、HTTP协议,GET和POST 的区别
二、线程、设计模式、缓存方面
1、SimpleDataFormat是非线程安全的,如何更好的使用而避免风险呢
答: 关于SimpleDateFormat安全的时间格式化线程安全问题
2、如何看待设计模式,并简单说说你对观察者模式的理解
3、集群环境中,session如何实现共享
答:
2、session多服务器共享方案 ,还有一种方案就是使用一个固定的服务器专门保持session,其他服务器共享
4、分布式、集群环境中,缓存如何刷新,如何保持同步?
答:
A、缓存如何刷新? 1、定时刷新 2、主动刷新覆盖 ,每个缓存框架都有自带的刷新机制,或者说缓存失效机制,就拿Redis和 Ehcache举例, 他们都有自带的过期机制,另外主动刷新覆盖时,只需获取对应的key进行数据的覆盖即可
B、缓存如何保持同步? 这个redis有自带的集群同步机制,即复制功能,具体参考: 基于Redis分布式缓存实现 ,Ehcache也有分布式缓存同步的配置,只需要配置不同服务器地址即可,参照: Ehcache分布式缓存同步
5、一条sql执行过长的时间,你如何优化,从哪些方面?
答:
1、查看sql是否涉及多表的联表或者子查询,如果有,看是否能进行业务拆分,相关字段冗余或者合并成临时表(业务和算法的优化)
2、涉及链表的查询,是否能进行分表查询,单表查询之后的结果进行字段整合
3、如果以上两种都不能操作,非要链表查询,那么考虑对相对应的查询条件做索引。加快查询速度
4、针对数量大的表进行历史表分离(如交易流水表)
5、数据库主从分离,读写分离,降低读写针对同一表同时的压力,至于主从同步,mysql有自带的binlog实现 主从同步
6、explain分析sql语句,查看执行计划,分析索引是否用上,分析扫描行数等等
7、查看mysql执行日志,看看是否有其他方面的问题
个人理解:从根本上来说,查询慢是占用mysql内存比较多,那么可以从这方面去酌手考虑
三、三大框架方面问题
1、Spring 事务的隔离性,并说说每个隔离性的区别
Spring事务详解
2、Spring事务的传播行为,并说说每个传播行为的区别
Spring事务详解
3、hibernate跟Mybatis/ ibatis 的区别,为什么选择?
Hibernate与Mybatis的比较
4、Struts跟Spring mvc的优缺点,让你选会如何选
Spring MVC 与 Struts的区别
5、简单说说Spring 事务机制
Spring事务机制
6、Spring 4.0新特性
Spring4新特性
四、负载均衡、集群相关
1、weblogic 负载均衡的原理和集群的配置
a、WEBLOGIC负载均衡原理
b、负载均衡和集群的配置(参考)
2、Nginx+Tomcat+Redis实现负载均衡、资源分离、session共享
配置参考
3、nginx配置文件详解——nginx.conf
Nginx配置文件详细说明
五、项目优化相关
1、web如何项目优化
web项目性能优化(整理)
2、单例模式有几种? 如何优化?
单例模式的7中用法
3、简单说说线程池的原理和实现
线程原理及实现
六、并发和安全方面
1、项目并发如何处理?(我们是web项目)
高并发量网站解决方案
2、简单说说功能权限存在的水平权限漏洞和垂直权限漏洞的场景和解决办法(因为我们目前权限级别就是功能权限)
水平权限漏洞和解决办法
垂直权限漏洞案例和解决方案
3、平台上的图片如何防盗链
http下载防盗链原理:http协议的字段referer记录来实现
4、如何区分上传的图片是不是木马?
文件上传-魔术数字
5、消息队列的原理和实现
1、消息队列原理
深入浅出 消息队列 ActiveMQ
七、数据库方面
1、mysql查询字段区不区分大小写?
2、简单说说数据库集群和负载均衡、分布式(我不懂这块)
数据库负载均衡和集群参考
参考2
3、存储过程的结构和优点
大概结构
存储过程的优缺点
4、触发器的原理和作用
参考
八、Java底层基础题
1、SpringMVC的原理以及返回数据如何渲染到jsp/html上?
答:Spring MVC的核心就是 DispatcherServlet , 一个请求经过 DispatcherServlet ,转发给HandlerMapping ,然后经反射,对应 Controller及其里面方法的@RequestMapping地址,最后经ModelAndView和ViewResoler返回给对应视图 。 具体可参考: Spring MVC的工作原理
2、一个类对象属性发生改变时,如何让调用者知道?
答: Java event时间监听 ,即在set方法改变属性时,触发 ,这种模式也可以理解为观察者模式,具体查看: 观察者模式简单案例和说明
3、重写equals为何要重写hashCode?
答:判断两个对象是否相等,比较的就是其hashCode, 如果你重载了equals,比如说是基于对象的内容实现的,而保留hashCode的实现不变,那么很可能某两个对象明明是“相等”,而hashCode却不一样。 hashcode不一样,就无法认定两个对象相等了
4、谈谈你对JVM的理解?
答: Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。Java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行。
JVM执行程序的过程 :I.加载。class文件 ,II.管理并分配内存 ,III.执行垃圾收集 JRE(java运行时环境)由JVM构造的java程序的运行环境
具体详情: JVM原理和调优
5、Mysql的事物隔离级别?
答:Mysql的事物隔离级别 其实跟 Spring的事物隔离级别一样,都是1、Read Uncommitted(读取未提交内容), 2、Read Committed(读取提交内容),3、Repeatable Read(可重读),4、Serializable(可串行化) 具体参照: mysql事物隔离级别
6、Spring的原理
答:Spring的核心是IOC和AOP ,IOC是依赖注入和控制反转, 其注入方式可分为set注入、构造器注入、接口注入等等。IOC就是一个容器,负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。简单理解就是:JAVA每个业务逻辑处理至少需要两个或者以上的对象协作进行工作,但是每个对象在使用它的合作对象的时候,都需要频繁的new 对象来实现,你就会发现,对象间的耦合度高了。而IOC的思想是:Spring容器来管理这些,对象只需要处理本身业务关系就好了。至于什么是控制反转,就是获得依赖对象的方式反转了。 AOP呢,面向切面编程,最直接的体现就是Spring事物管理。至于Spring事物的相关资料,就不细说了,参考: Spring注解式事物管理
7、谈谈你对NIO的理解
答:IO是面向流,NIO是面向缓冲 ,这里不细讲了,具体参照: Java NIO和IO的区别
8、ArrayList和LinkedList、Vector的区别?
答:总得来说可以理解为:.
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据
Vector和ArrayList类似,但属于强同步类,即线程安全的,具体比较参照: 比较ArrayList、LinkedList、Vector
9、随便说说几个单例模式,并选择一种线程安全的
答:单例的类别:懒汉、饿汉、枚举、静态内部类、双重校验锁 等等 , 选择线程安全我选最后一种,双重校验锁。 具体实现方式参照: Java:单例模式的七种写法
10、谈谈红黑树
答:算法和数据结构一直是我薄弱之处,这方面说自己补吧,成效不大,这里我就推荐一个: 红黑树
11、举例说说几个排序,并说明其排序原理
答:这里我就不细说了,大家自己看看 Java实现几种常见的排序算法
12、Mysql索引的原理
答:索引的作用大家都知道,就是加快查询速度,但是原理,我说不上来,这里直接看吧: Mysql索引工作原理
13、序列化的原理和作用
答:Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization是一种将这些字节重建成一个对象的过程,主要用于HTTP或者WebService接口传输过程中对象参数的传播,具体可参看: Java序列化机制和原理
九、并发及项目调优
1、说说线程安全的几种实现方式?
答:什么是线程安全? 我的理解是这样的,一个对象被多个线程同时访问,还能保持其内部属性的顺序性及同步性,则认定为线程安全。实现线程安全的三种方式:被volatile、synchronized等关键字修饰,或者使用java.util.concurrent下面的类库。 至于前两者的关系,参考: synchronized和volatile的用法区别
2、方法内部,如何实现更好的异步?
答:我们知道异步其实就是让另一个线程去跑,那么如何创建线程? 第一种直接new Thread ,第二种new 一个实现Runnable接口的实现类。 第三种,通过线程池来管理创建等 ,这里说到更好的实现异步,那就是说我们在方法内部避免频繁的new 线程,就可以考虑线程池了。 那么线程池如何创建? 这里可以new 一个线程池,但是需要考虑单例,或者在程序初始启东时,就创建一个线程池,让他跑着,然后在具体方法的时候,通过线程池来创建线程,实现异步
3、项目中为何要用缓存?如何理解nginx + tomcat + redis 集群缓存?
答1:最直接的表现就是减轻数据库的压力。避免因为数据读取频繁或过大而影响数据库性能,降低程序宕机的可能性
答2:nginx常用做静态内容服务和代理服务器,直面外来请求转发给后面的应用服务。nginx本身也能做缓存,比如静态页面的缓存什么的。而tomcat是应用服务器,处理JAVA WEB程序功能等等 。你也可以这么理解,假设把用户的请求当做是一条河流,那么nginx就相当于一个水利工程,tomcat相当于一条条分流的支流,而redis 相当于支流旁边的一个个水库。 当你洪水来了,nginx根据你每条支流的承受力度分发不同的水流量,在确保程序正常运行的情况下,分发给每条支流(tomcat)不同的水流量。而redis相当于一个个支流的水库,存储水源,降低压力,让后面的水量平稳。
4、日常项目中,如果你接手,你准备从哪些方面调优?
答:这个呢首先是了解哪些需要优化,需要优化肯定是项目性能遭遇瓶颈或者猜测即将遭遇了,我们才会去考虑优化。那么怎么优化?
a、扩容 ,扩容的理解,就是扩充服务器并行处理的能力,简单来说就是加服务器,增加处理请求的能力,例如增加nginx 、tomcat等应用服务器的个数,或者物理服务器的个数,还有加大服务器带宽等等,这里考虑的是硬件方面
b、调优 ,调优,包括系统调优和代码调优 。 系统调优就是说加快处理速度,比如我们所提到的CDN、ehcache、redis等缓存技术,消息队列等等,加快服务间的响应速度,增加系统吞吐量,避免并发,至于代码调优,这些就需要多积累了,比如重构、工厂等, 数据库调优的话这个我不是很懂,只知道索引和存储过程,具体参考: Mysql数据库调优21个最佳实践 ,其他数据库调优方面就各位自己找找吧
5、谈谈你对分布式的理解
答:个人理解:分布式就是把一个系统/业务 拆分成多个子系统/子业务 去协同处理,这个过程就叫分布式,具体的演变方式参考: Java分布式应用技术架构介绍
6、Redis实现消息队列
答: Redis实现消息队列 、 参考2
7、另总结多线程相关面试题50道
8、分享一个调优工具和方案:如何利用 JConsole观察分析Java程序的运行,进行排错调优
十、手写代码题(包含sql题)
1、假设商户表A(id , city ) ,交易流水表B (aid, amount , time) 这里的time代表交易时间, 请用sql写出查询每个城市每个月的销售业绩(答案可在评论里回复)
2、假设有一个数组 A ,int[] A = { 1 , 3 , -1 ,0 , 2 , 1 , -4 , 2 , 0 ,1 … N}; 原来是需要查出大于0的数组,但是由于传参错误或者其他原因,导致查出0和负数了,现在要求在不使用新数组和新集合的情况下(即只使用这个A数组,因数组数据比较大,且只能用一次循环) 实现正数放到数组的前面,小于等于0的数放到数组的末尾(答案可在评论里回复)
十一、设计方案相关
面试还会问到一些关于设计方案相关的问题,比如
1、你的接口服务数据被人截包了,你如何防止数据恶意提交?
答:我们可以在接口传输参数里面设置一个业务编号,这个编号用来区分是否重复提交。这样即使数据被抓包了,对方也无法区分每个字段你的含义,这时,这个业务编号的作用就来了
本文我们将要讨论Java面试中的各种不同类型的面试题,它们可以让雇主测试应聘者的Java和通用的面向对象编程的能力。下面的章节分为上下两篇, 第一篇 将要讨论面向对象编程和它的特点,关于Java和它的功能的常见问题,Java的集合类,垃圾收集器, 第二篇 主要讨论异常处理,Java小应用程序,Swing,JDBC,远程方法调用(RMI),Servlet和JSP。
开始!
目录
面向对象编程(OOP)
Java是一个支持并发、基于类和面向对象的计算机编程语言。下面列出了面向对象软件开发的优点:
- 代码开发模块化,更易维护和修改。
- 代码复用。
- 增强代码的可靠性和灵活性。
- 增加代码的可理解性。
面向对象编程有很多重要的特性,比如:封装,继承,多态和抽象。下面的章节我们会逐个分析这些特性。
封装
封装给对象提供了隐藏内部特性和行为的能力。对象提供一些能被其他对象访问的方法来改变它内部的数据。在Java当中,有3种修饰符:public,private和protected。每一种修饰符给其他的位于同一个包或者不同包下面对象赋予了不同的访问权限。
下面列出了使用封装的一些好处:
- 通过隐藏对象的属性来保护对象内部的状态。
- 提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展。
- 禁止对象之间的不良交互提高模块化。
参考 这个文档 获取更多关于封装的细节和示例。
多态
多态是编程语言给不同的底层数据类型做相同的接口展示的一种能力。一个多态类型上的操作可以应用到其他类型的值上面。
继承
继承给对象提供了从基类获取字段和方法的能力。继承提供了代码的重用行,也可以在不修改类的情况下给现存的类添加新特性。
抽象
抽象是把想法从具体的实例中分离出来的步骤,因此,要根据他们的功能而不是实现细节来创建类。Java支持创建只暴漏接口而不包含方法实现的抽象的类。这种抽象技术的主要目的是把类的行为和实现细节分离开。
抽象和封装的不同点
抽象和封装是互补的概念。一方面,抽象关注对象的行为。另一方面,封装关注对象行为的细节。一般是通过隐藏对象内部状态信息做到封装,因此,封装可以看成是用来提供抽象的一种策略。
常见的Java问题
1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?
Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。
Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。
2.JDK和JRE的区别是什么?
Java运行时环境(JRE)是将要执行Java程序的Java虚拟机。它同时也包含了执行applet需要的浏览器插件。Java开发工具包(JDK)是完整的Java软件开发包,包含了JRE,编译器和其他的工具(比如:JavaDoc,Java调试器),可以让开发者开发、编译、执行Java应用程序。
3.”static”关键字是什么意思?Java中是否可以覆盖(override)一个private或者是static的方法?
“static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。 Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。
4.是否可以在static环境中访问非static变量?
static变量在Java中是属于类的,它在所有的实例中的值是一样的。当类被Java虚拟机载入的时候,会对static变量进行初始化。如果你的代码尝试不用实例来访问非static的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。
5.Java支持的数据类型有哪些?什么是自动拆装箱?
Java语言支持的8中基本数据类型是:
- byte
- short
- int
- long
- float
- double
- boolean
- char
自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。比如:把int转化成Integer,double转化成double,等等。反之就是自动拆箱。
6.Java中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思?
Java中的方法重载发生在同一个类里面两个或者是多个方法的方法名相同但是参数不同的情况。与此相对,方法覆盖是说子类重新定义了父类的方法。方法覆盖必须有相同的方法名,参数列表和返回类型。覆盖者可能不会限制它所覆盖的方法的访问。
7.Java中,什么是构造函数?什么是构造函数重载?什么是复制构造函数?
当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一个默认的构造函数。
Java中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数必须有它自己唯一的参数列表。
Java不支持像C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java不会创建默认的复制构造函数。
8.Java支持多继承么?
不支持,Java不支持多继承。每个类都只能继承一个类,但是可以实现多个接口。
9.接口和抽象类的区别是什么?
Java提供和支持创建抽象类和接口。它们的实现有共同点,不同点在于:
- 接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。
- 类可以实现很多个接口,但是只能继承一个抽象类
- 类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
- 抽象类可以在不提供接口方法实现的情况下实现接口。
- Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。
- Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。
- 接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。
也可以参考 JDK8中抽象类和接口的区别
10.什么是值传递和引用传递?
对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响源对象的值。
对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象所做的改变会反映到所有的对象上。
Java线程
11.进程和线程的区别是什么?
进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。
12.创建线程有几种不同的方式?你喜欢哪一种?为什么?
有三种方式可以用来创建线程:
- 继承Thread类
- 实现Runnable接口
- 应用程序可以使用Executor框架来创建线程池
实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别的对象的情况下,这需要多继承(而Java不支持多继承),只能实现接口。同时,线程池也是非常高效的,很容易实现和使用。
13.概括的解释下线程的几种可用状态。
线程在执行过程中,可以处于下面几种状态:
- 就绪(Runnable):线程准备运行,不一定立马就能开始执行。
- 运行中(Running):进程正在执行线程的代码。
- 等待中(Waiting):线程处于阻塞的状态,等待外部的处理结束。
- 睡眠中(Sleeping):线程被强制睡眠。
- I/O阻塞(Blocked on I/O):等待I/O操作完成。
- 同步阻塞(Blocked on Synchronization):等待获取锁。
- 死亡(Dead):线程完成了执行。
14.同步方法和同步代码块的区别是什么?
在Java语言中,每一个对象有一把锁。线程可以使用synchronized关键字来获取对象上的锁。synchronized关键字可应用在方法级别(粗粒度锁)或者是代码块级别(细粒度锁)。
15.在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步?
监视器和锁在Java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许执行同步代码。
16.什么是死锁(deadlock)?
两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程都陷入了无限的等待中。
17.如何确保N个线程可以访问N个资源同时又不导致死锁?
使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。
Java集合类
18.Java集合类框架的基本接口有哪些?
Java集合类提供了一套设计良好的支持对一组对象进行操作的接口和类。Java集合类里面最基本的接口有:
- Collection:代表一组对象,每一个对象都是它的子元素。
- Set:不包含重复元素的Collection。
- List:有顺序的collection,并且可以包含重复元素。
- Map:可以把键(key)映射到值(value)的对象,键不能重复。
19.为什么集合类没有实现Cloneable和Serializable接口?
集合类接口指定了一组叫做元素的对象。集合类接口的每一种具体的实现类都可以选择以它自己的方式对元素进行保存和排序。有的集合类允许重复的键,有些不允许。
20.什么是迭代器(Iterator)?
Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的 迭代方法。迭代器可以在迭代的过程中删除底层集合的元素。
克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。
21.Iterator和ListIterator的区别是什么?
下面列出了他们的区别:
- Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
- Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
- ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
22.快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?
Iterator的安全失败是基于对底层集合做拷贝,因此,它不受源集合上修改的影响。java.util包下面的所有的集合类都是快速失败的,而java.util.concurrent包下面的所有的类都是安全失败的。快速失败的迭代器会抛出ConcurrentModificationException异常,而安全失败的迭代器永远不会抛出这样的异常。
23.Java中的HashMap的工作原理是什么?
Java中的HashMap是以键值对(key-value)的形式存储元素的。HashMap需要一个hash函数,它使用hashCode()和equals()方法来向集合/从集合添加和检索元素。当调用put()方法的时候,HashMap会计算key的hash值,然后把键值对存储在集合中合适的索引上。如果key已经存在了,value会被更新成新值。HashMap的一些重要的特性是它的容量(capacity),负载因子(load factor)和扩容极限(threshold resizing)。
24.hashCode()和equals()方法的重要性体现在什么地方?
Java中的HashMap使用hashCode()和equals()方法来确定键值对的索引,当根据键获取值的时候也会用到这两个方法。如果没有正确的实现这两个方法,两个不同的键可能会有相同的hash值,因此,可能会被集合认为是相等的。而且,这两个方法也用来发现重复元素。所以这两个方法的实现对HashMap的精确性和正确性是至关重要的。
25.HashMap和Hashtable有什么区别?
- HashMap和Hashtable都实现了Map接口,因此很多特性非常相似。但是,他们有以下不同点:
- HashMap允许键和值是null,而Hashtable不允许键或者值是null。
- Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线程环境。
- HashMap提供了可供应用迭代的键的集合,因此,HashMap是快速失败的。另一方面,Hashtable提供了对键的列举(Enumeration)。
- 一般认为Hashtable是一个遗留的类。
26.数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用Array而不是ArrayList?
下面列出了Array和ArrayList的不同点:
- Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
- Array大小是固定的,ArrayList的大小是动态变化的。
- ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
- 对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。
27.ArrayList和LinkedList有什么区别?
ArrayList和LinkedList都实现了List接口,他们有以下的不同点:
- ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。
- 相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。
- LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。
也可以参考 ArrayList vs. LinkedList 。
28.Comparable和Comparator接口是干什么的?列出它们的区别。
Java提供了只包含一个compareTo()方法的Comparable接口。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。
Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序,返回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。equals()方法需要一个对象作为参数,它用来决定输入参数是否和comparator相等。只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时候,这个方法才返回true。
29.什么是Java优先级队列(Priority Queue)?
PriorityQueue是一个基于优先级堆的无界队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。
30.你了解大O符号(big-O notation)么?你能给出不同数据结构的例子么?
大O符号描述了当数据结构里面的元素增加的时候,算法的规模或者是性能在最坏的场景下有多么好。 大O符号也可用来描述其他的行为,比如:内存消耗。因为集合类实际上是数据结构,我们一般使用大O符号基于时间,内存和性能来选择最好的实现。大O符号可以对大量数据的性能给出一个很好的说明。
31.如何权衡是使用无序的数组还是有序的数组?
有序数组最大的好处在于查找的时间复杂度是O(log n),而无序数组是O(n)。有序数组的缺点是插入操作的时间复杂度是O(n),因为值大的元素需要往后移动来给新元素腾位置。相反,无序数组的插入时间复杂度是常量O(1)。
32.Java集合类框架的最佳实践有哪些?
- 根据应用的需要正确选择要使用的集合的类型对性能非常重要,比如:假如元素的大小是固定的,而且能事先知道,我们就应该用Array而不是ArrayList。
- 有些集合类允许指定初始容量。因此,如果我们能估计出存储的元素的数目,我们可以设置初始容量来避免重新计算hash值或者是扩容。
- 为了类型安全,可读性和健壮性的原因总是要使用泛型。同时,使用泛型还可以避免运行时的ClassCastException。
- 使用JDK提供的不变类(immutable class)作为Map的键可以避免为我们自己的类实现hashCode()和equals()方法。
- 编程的时候接口优于实现。
- 底层的集合实际上是空的情况下,返回长度是0的集合或者是数组,不要返回null。
33.Enumeration接口和Iterator接口的区别有哪些?
Enumeration速度是Iterator的2倍,同时占用更少的内存。但是,Iterator远远比Enumeration安全,因为其他线程不能够修改正在被iterator遍历的集合里面的对象。同时,Iterator允许调用者删除底层集合里面的元素,这对Enumeration来说是不可能的。
34.HashSet和TreeSet有什么区别?
HashSet是由一个hash表来实现的,因此,它的元素是无序的。add(),remove(),contains()方法的时间复杂度是O(1)。
另一方面,TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),remove(),contains()方法的时间复杂度是O(logn)。
垃圾收集器(Garbage Collectors)
35.Java中垃圾回收有什么目的?什么时候进行垃圾回收?
垃圾回收的目的是识别并且丢弃应用不再使用的对象来释放和重用资源。
36.System.gc()和Runtime.gc()会做什么事情?
这两个方法用来提示JVM要进行垃圾回收。但是,立即开始还是延迟进行垃圾回收是取决于JVM的。
37.finalize()方法什么时候被调用?析构函数(finalization)的目的是什么?
在释放对象占用的内存之前,垃圾收集器会调用对象的finalize()方法。一般建议在该方法中释放对象持有的资源。
38.如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?
不会,在下一个垃圾回收周期中,这个对象将是可被回收的。
39.Java堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)?
JVM的堆是运行时数据区,所有类的实例和数组都是在堆上分配内存。它在JVM启动的时候被创建。对象所占的堆内存是由自动内存管理系统也就是垃圾收集器回收。
堆内存是由存活和死亡的对象组成的。存活的对象是应用可以访问的,不会被垃圾回收。死亡的对象是应用不可访问尚且还没有被垃圾收集器回收掉的对象。一直到垃圾收集器把这些对象回收掉之前,他们会一直占据堆内存空间。
40.串行(serial)收集器和吞吐量(throughput)收集器的区别是什么?
吞吐量收集器使用并行版本的新生代垃圾收集器,它用于中等规模和大规模数据的应用程序。而串行收集器对大多数的小应用(在现代处理器上需要大概100M左右的内存)就足够了。
41.在Java中,对象什么时候可以被垃圾回收?
当对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收了。
42.JVM的永久代中会发生垃圾回收么?
垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免Full GC是非常重要的原因。请参考下 Java8:从永久代到元数据区 (译者注:Java8中已经移除了永久代,新加了一个叫做元数据区的native内存区)
异常处理
43.Java中的两种异常类型是什么?他们有什么区别?
Java中有两种异常:受检查的(checked)异常和不受检查的(unchecked)异常。不受检查的异常不需要在方法或者是构造函数上声明,就算方法或者是构造函数的执行可能会抛出这样的异常,并且不受检查的异常可以传播到方法或者是构造函数的外面。相反,受检查的异常必须要用throws语句在方法或者是构造函数上声明。这里有 Java异常处理 的一些小建议。
44.Java中Exception和Error有什么区别?
Exception和Error都是Throwable的子类。Exception用于用户程序可以捕获的异常情况。Error定义了不期望被用户程序捕获的异常。
45.throw和throws有什么区别?
throw关键字用来在程序中明确的抛出异常,相反,throws语句用来表明方法不能处理的异常。每一个方法都必须要指定哪些异常不能处理,所以方法的调用者才能够确保处理可能发生的异常,多个异常是用逗号分隔的。
45.异常处理的时候,finally代码块的重要性是什么?(译者注:作者标题的序号弄错了)
无论是否抛出异常,finally代码块总是会被执行。就算是没有catch语句同时又抛出异常的情况下,finally代码块仍然会被执行。最后要说的是,finally代码块主要用来释放资源,比如:I/O缓冲区,数据库连接。
46.异常处理完成以后,Exception对象会发生什么变化?
Exception对象会在下一个垃圾回收过程中被回收掉。
47.finally代码块和finalize()方法有什么区别?
无论是否抛出异常,finally代码块都会执行,它主要是用来释放应用占用的资源。finalize()方法是Object类的一个protected方法,它是在对象被垃圾回收之前由Java虚拟机来调用的。
Java小应用程序(Applet)
48.什么是Applet?
java applet是能够被包含在HTML页面中并且能被启用了java的客户端浏览器执行的程序。Applet主要用来创建动态交互的web应用程序。
49.解释一下Applet的生命周期
applet可以经历下面的状态:
- Init:每次被载入的时候都会被初始化。
- Start:开始执行applet。
- Stop:结束执行applet。
- Destroy:卸载applet之前,做最后的清理工作。
50.当applet被载入的时候会发生什么?
首先,创建applet控制类的实例,然后初始化applet,最后开始运行。
51.Applet和普通的Java应用程序有什么区别?
applet是运行在启用了java的浏览器中,Java应用程序是可以在浏览器之外运行的独立的Java程序。但是,它们都需要有Java虚拟机。
进一步来说,Java应用程序需要一个有特定方法签名的main函数来开始执行。Java applet不需要这样的函数来开始执行。
最后,Java applet一般会使用很严格的安全策略,Java应用一般使用比较宽松的安全策略。
52.Java applet有哪些限制条件?
主要是由于安全的原因,给applet施加了以下的限制:
- applet不能够载入类库或者定义本地方法。
- applet不能在宿主机上读写文件。
- applet不能读取特定的系统属性。
- applet不能发起网络连接,除非是跟宿主机。
- applet不能够开启宿主机上其他任何的程序。
53.什么是不受信任的applet?
不受信任的applet是不能访问或是执行本地系统文件的Java applet,默认情况下,所有下载的applet都是不受信任的。
54.从网络上加载的applet和从本地文件系统加载的applet有什么区别?
当applet是从网络上加载的时候,applet是由applet类加载器载入的,它受applet安全管理器的限制。
当applet是从客户端的本地磁盘载入的时候,applet是由文件系统加载器载入的。
从文件系统载入的applet允许在客户端读文件,写文件,加载类库,并且也允许执行其他程序,但是,却通不过字节码校验。
55.applet类加载器是什么?它会做哪些工作?
当applet是从网络上加载的时候,它是由applet类加载器载入的。类加载器有自己的java名称空间等级结构。类加载器会保证来自文件系统的类有唯一的名称空间,来自网络资源的类有唯一的名称空间。
当浏览器通过网络载入applet的时候,applet的类被放置于和applet的源相关联的私有的名称空间中。然后,那些被类加载器载入进来的类都是通过了验证器验证的。验证器会检查类文件格式是否遵守Java语言规范,确保不会出现堆栈溢出(stack overflow)或者下溢(underflow),传递给字节码指令的参数是正确的。
56.applet安全管理器是什么?它会做哪些工作?
applet安全管理器是给applet施加限制条件的一种机制。浏览器可以只有一个安全管理器。安全管理器在启动的时候被创建,之后不能被替换覆盖或者是扩展。
Swing
57.弹出式选择菜单(Choice)和列表(List)有什么区别
Choice是以一种紧凑的形式展示的,需要下拉才能看到所有的选项。Choice中一次只能选中一个选项。List同时可以有多个元素可见,支持选中一个或者多个元素。
58.什么是布局管理器?
布局管理器用来在容器中组织组件。
59.滚动条(Scrollbar)和滚动面板(JScrollPane)有什么区别?
Scrollbar是一个组件,不是容器。而ScrollPane是容器。ScrollPane自己处理滚动事件。
60.哪些Swing的方法是线程安全的?
只有3个线程安全的方法: repaint(), revalidate(), and invalidate()。
61.说出三种支持重绘(painting)的组件。
Canvas, Frame, Panel,和Applet支持重绘。
62.什么是裁剪(clipping)?
限制在一个给定的区域或者形状的绘图操作就做裁剪。
63.MenuItem和CheckboxMenuItem的区别是什么?
CheckboxMenuItem类继承自MenuItem类,支持菜单选项可以选中或者不选中。
64.边缘布局(BorderLayout)里面的元素是如何布局的?
BorderLayout里面的元素是按照容器的东西南北中进行布局的。
65.网格包布局(GridBagLayout)里面的元素是如何布局的?
GridBagLayout里面的元素是按照网格进行布局的。不同大小的元素可能会占据网格的多于1行或一列。因此,行数和列数可以有不同的大小。
66.Window和Frame有什么区别?
Frame类继承了Window类,它定义了一个可以有菜单栏的主应用窗口。
67.裁剪(clipping)和重绘(repainting)有什么联系?
当窗口被AWT重绘线程进行重绘的时候,它会把裁剪区域设置成需要重绘的窗口的区域。
68.事件监听器接口(event-listener interface)和事件适配器(event-adapter)有什么关系?
事件监听器接口定义了对特定的事件,事件处理器必须要实现的方法。事件适配器给事件监听器接口提供了默认的实现。
69.GUI组件如何来处理它自己的事件?
GUI组件可以处理它自己的事件,只要它实现相对应的事件监听器接口,并且把自己作为事件监听器。
70.Java的布局管理器比传统的窗口系统有哪些优势?
Java使用布局管理器以一种一致的方式在所有的窗口平台上摆放组件。因为布局管理器不会和组件的绝对大小和位置相绑定,所以他们能够适应跨窗口系统的特定平台的不同。
71.Java的Swing组件使用了哪种 设计模式 ? Java中的Swing组件使用了MVC(视图-模型-控制器)设计模式。
JDBC
72.什么是JDBC?
JDBC是允许用户在不同数据库之间做选择的一个抽象层。 JDBC允许开发者用JAVA写数据库应用程序 ,而不需要关心底层特定数据库的细节。
73.解释下驱动(Driver)在JDBC中的角色。
JDBC驱动提供了特定厂商对JDBC API接口类的实现,驱动必须要提供java.sql包下面这些类的实现: Connection , Statement , PreparedStatement , CallableStatement , ResultSet 和 Driver 。
74.Class.forName()方法有什么作用?
这个方法用来载入跟数据库建立连接的驱动。
75.PreparedStatement比Statement有什么优势?
PreparedStatements是预编译的,因此,性能会更好。同时,不同的查询参数值,PreparedStatement可以重用。
76.什么时候使用CallableStatement?用来准备CallableStatement的方法是什么?
CallableStatement用来执行存储过程。存储过程是由数据库存储和提供的。存储过程可以接受输入参数,也可以有返回结果。非常鼓励使用存储过程,因为它提供了安全性和模块化。准备一个CallableStatement的方法是:
CallableStament.prepareCall();
77.数据库连接池是什么意思?
像打开关闭数据库连接这种和数据库的交互可能是很费时的,尤其是当客户端数量增加的时候,会消耗大量的资源,成本是非常高的。可以在应用服务器启动的时候建立很多个数据库连接并维护在一个池中。连接请求由池中的连接提供。在连接使用完毕以后,把连接归还到池中,以用于满足将来更多的请求。
远程方法调用(RMI)
78.什么是RMI?
Java远程方法调用(Java RMI)是Java API对远程过程调用(RPC)提供的面向对象的等价形式,支持直接传输序列化的Java对象和分布式垃圾回收。远程方法调用可以看做是激活远程正在运行的对象上的方法的步骤。RMI对调用者是位置透明的,因为调用者感觉方法是执行在本地运行的对象上的。看下 RMI的一些注意事项 。
79.RMI体系结构的基本原则是什么?
RMI体系结构是基于一个非常重要的行为定义和行为实现相分离的原则。RMI允许定义行为的代码和实现行为的代码相分离,并且运行在不同的JVM上。
80.RMI体系结构分哪几层?
RMI体系结构分以下几层:
存根和骨架层(Stub and Skeleton layer):这一层对程序员是透明的,它主要负责拦截客户端发出的方法调用请求,然后把请求重定向给远程的RMI服务。
远程引用层(Remote Reference Layer):RMI体系结构的第二层用来解析客户端对服务端远程对象的引用。这一层解析并管理客户端对服务端远程对象的引用。连接是点到点的。
传输层(Transport layer):这一层负责连接参与服务的两个JVM。这一层是建立在网络上机器间的TCP/IP连接之上的。它提供了基本的连接服务,还有一些防火墙穿透策略。
81.RMI中的远程接口(Remote Interface)扮演了什么样的角色?
远程接口用来标识哪些方法是可以被非本地虚拟机调用的接口。远程对象必须要直接或者是间接实现远程接口。实现了远程接口的类应该声明被实现的远程接口,给每一个远程对象定义构造函数,给所有远程接口的方法提供实现。
82.java.rmi.Naming类扮演了什么样的角色?
java.rmi.Naming类用来存储和获取在远程对象注册表里面的远程对象的引用。Naming类的每一个方法接收一个URL格式的String对象作为它的参数。
83.RMI的绑定(Binding)是什么意思?
绑定是为了查询找远程对象而给远程对象关联或者是注册以后会用到的名称的过程。远程对象可以使用Naming类的bind()或者rebind()方法跟名称相关联。
84.Naming类的bind()和rebind()方法有什么区别?
bind()方法负责把指定名称绑定给远程对象,rebind()方法负责把指定名称重新绑定到一个新的远程对象。如果那个名称已经绑定过了,先前的绑定会被替换掉。
85.让RMI程序能正确运行有哪些步骤?
为了让RMI程序能正确运行必须要包含以下几个步骤:
- 编译所有的源文件。
- 使用rmic生成stub。
- 启动rmiregistry。
- 启动RMI服务器。
- 运行客户端程序。
86.RMI的stub扮演了什么样的角色?
远程对象的stub扮演了远程对象的代表或者代理的角色。调用者在本地stub上调用方法,它负责在远程对象上执行方法。当stub的方法被调用的时候,会经历以下几个步骤:
- 初始化到包含了远程对象的JVM的连接。
- 序列化参数到远程的JVM。
- 等待方法调用和执行的结果。
- 反序列化返回的值或者是方法没有执行成功情况下的异常。
- 把值返回给调用者。
87.什么是分布式垃圾回收(DGC)?它是如何工作的?
DGC叫做分布式垃圾回收。RMI使用DGC来做自动垃圾回收。因为RMI包含了跨虚拟机的远程对象的引用,垃圾回收是很困难的。DGC使用引用计数算法来给远程对象提供自动内存管理。
88.RMI中使用RMI安全管理器(RMISecurityManager)的目的是什么?
RMISecurityManager使用下载好的代码提供可被RMI应用程序使用的安全管理器。如果没有设置安全管理器,RMI的类加载器就不会从远程下载任何的类。
89.解释下Marshalling和demarshalling。
当应用程序希望把内存对象跨网络传递到另一台主机或者是持久化到存储的时候,就必须要把对象在内存里面的表示转化成合适的格式。这个过程就叫做Marshalling,反之就是demarshalling。
90.解释下Serialization和Deserialization。
Java提供了一种叫做对象序列化的机制,他把对象表示成一连串的字节,里面包含了对象的数据,对象的类型信息,对象内部的数据的类型信息等等。因此,序列化可以看成是为了把对象存储在磁盘上或者是从磁盘上读出来并重建对象而把对象扁平化的一种方式。反序列化是把对象从扁平状态转化成活动对象的相反的步骤。
Servlet
91.什么是Servlet?
Servlet是用来处理客户端请求并产生动态网页内容的Java类。Servlet主要是用来处理或者是存储HTML表单提交的数据,产生动态内容,在无状态的HTTP协议下管理状态信息。
92.说一下Servlet的体系结构。
所有的Servlet都必须要实现的核心的接口是javax.servlet.Servlet。每一个Servlet都必须要直接或者是间接实现这个接口,或者是继承javax.servlet.GenericServlet或者javax.servlet.http.HTTPServlet。最后,Servlet使用多线程可以并行的为多个请求服务。
93.Applet和Servlet有什么区别?
Applet是运行在客户端主机的浏览器上的客户端Java程序。而Servlet是运行在web服务器上的服务端的组件。applet可以使用用户界面类,而Servlet没有用户界面,相反,Servlet是等待客户端的HTTP请求,然后为请求产生响应。
94.GenericServlet和HttpServlet有什么区别?
GenericServlet是一个通用的协议无关的Servlet,它实现了Servlet和ServletConfig接口。继承自GenericServlet的Servlet应该要覆盖service()方法。最后,为了开发一个能用在网页上服务于使用HTTP协议请求的Servlet,你的Servlet必须要继承自HttpServlet。这里有 Servlet的例子 。
95.解释下Servlet的生命周期。
对每一个客户端的请求,Servlet引擎载入Servlet,调用它的init()方法,完成Servlet的初始化。然后,Servlet对象通过为每一个请求单独调用service()方法来处理所有随后来自客户端的请求,最后,调用Servlet(译者注:这里应该是Servlet而不是server)的destroy()方法把Servlet删除掉。
96.doGet()方法和doPost()方法有什么区别?
doGet:GET方法会把名值对追加在请求的URL后面。因为URL对字符数目有限制,进而限制了用在客户端请求的参数值的数目。并且请求中的参数值是可见的,因此,敏感信息不能用这种方式传递。
doPOST:POST方法通过把请求参数值放在请求体中来克服GET方法的限制,因此,可以发送的参数的数目是没有限制的。最后,通过POST请求传递的敏感信息对外部客户端是不可见的。
97.什么是Web应用程序?
Web应用程序是对Web或者是应用服务器的动态扩展。有两种类型的Web应用:面向表现的和面向服务的。面向表现的Web应用程序会产生包含了很多种标记语言和动态内容的交互的web页面作为对请求的响应。而面向服务的Web应用实现了Web服务的端点(endpoint)。一般来说,一个Web应用可以看成是一组安装在服务器URL名称空间的特定子集下面的Servlet的集合。
98.什么是服务端包含(Server Side Include)?
服务端包含(SSI)是一种简单的解释型服务端脚本语言,大多数时候仅用在Web上,用servlet标签嵌入进来。SSI最常用的场景把一个或多个文件包含到Web服务器的一个Web页面中。当浏览器访问Web页面的时候,Web服务器会用对应的servlet产生的文本来替换Web页面中的servlet标签。
99.什么是Servlet链(Servlet Chaining)?
Servlet链是把一个Servlet的输出发送给另一个Servlet的方法。第二个Servlet的输出可以发送给第三个Servlet,依次类推。链条上最后一个Servlet负责把响应发送给客户端。
100.如何知道是哪一个客户端的机器正在请求你的Servlet?
ServletRequest类可以找出客户端机器的IP地址或者是主机名。getRemoteAddr()方法获取客户端主机的IP地址,getRemoteHost()可以获取主机名。看下 这里 的例子。
101.HTTP响应的结构是怎么样的?
HTTP响应由三个部分组成:
状态码(Status Code):描述了响应的状态。可以用来检查是否成功的完成了请求。请求失败的情况下,状态码可用来找出失败的原因。如果Servlet没有返回状态码,默认会返回成功的状态码HttpServletResponse.SC_OK。
HTTP头部(HTTP Header):它们包含了更多关于响应的信息。比如:头部可以指定认为响应过期的过期日期,或者是指定用来给用户安全的传输实体内容的编码格式。如何在Serlet中检索HTTP的头部看 这里 。
主体(Body):它包含了响应的内容。它可以包含HTML代码,图片,等等。主体是由传输在HTTP消息中紧跟在头部后面的数据字节组成的。
102.什么是cookie?session和cookie有什么区别?
cookie是Web服务器发送给浏览器的一块信息。浏览器会在本地文件中给每一个Web服务器存储cookie。以后浏览器在给特定的Web服务器发请求的时候,同时会发送所有为该服务器存储的cookie。下面列出了session和cookie的区别:
- 无论客户端浏览器做怎么样的设置,session都应该能正常工作。客户端可以选择禁用cookie,但是,session仍然是能够工作的,因为客户端无法禁用服务端的session。
- 在存储的数据量方面session和cookies也是不一样的。session能够存储任意的Java对象,cookie只能存储String类型的对象。
103.浏览器和Servlet通信使用的是什么协议? 浏览器和Servlet通信使用的是HTTP协议。
104.什么是HTTP隧道?
HTTP隧道是一种利用HTTP或者是HTTPS把多种网络协议封装起来进行通信的技术。因此,HTTP协议扮演了一个打通用于通信的网络协议的管道的包装器的角色。把其他协议的请求掩盖成HTTP的请求就是HTTP隧道。
105.sendRedirect()和forward()方法有什么区别?
sendRedirect()方法会创建一个新的请求,而forward()方法只是把请求转发到一个新的目标上。重定向(redirect)以后,之前请求作用域范围以内的对象就失效了,因为会产生一个新的请求,而转发(forwarding)以后,之前请求作用域范围以内的对象还是能访问的。一般认为sendRedirect()比forward()要慢。
106.什么是URL编码和URL解码?
URL编码是负责把URL里面的空格和其他的特殊字符替换成对应的十六进制表示,反之就是解码。
JSP
107.什么是JSP页面?
JSP页面是一种包含了静态数据和JSP元素两种类型的文本的文本文档。静态数据可以用任何基于文本的格式来表示,比如:HTML或者XML。JSP是一种混合了静态内容和动态产生的内容的技术。这里看下 JSP的例子 。
108.JSP请求是如何被处理的?
浏览器首先要请求一个以.jsp扩展名结尾的页面,发起JSP请求,然后,Web服务器读取这个请求,使用JSP编译器把JSP页面转化成一个Servlet类。需要注意的是,只有当第一次请求页面或者是JSP文件发生改变的时候JSP文件才会被编译,然后服务器调用servlet类,处理浏览器的请求。一旦请求执行结束,servlet会把响应发送给客户端。这里看下 如何在JSP中获取请求参数 。
109.JSP有什么优点?
下面列出了使用JSP的优点:
- JSP页面是被动态编译成Servlet的,因此,开发者可以很容易的更新展现代码。
- JSP页面可以被预编译。
- JSP页面可以很容易的和静态模板结合,包括:HTML或者XML,也可以很容易的和产生动态内容的代码结合起来。
- 开发者可以提供让页面设计者以类XML格式来访问的自定义的JSP标签库。
- 开发者可以在组件层做逻辑上的改变,而不需要编辑单独使用了应用层逻辑的页面。
110.什么是JSP指令(Directive)?JSP中有哪些不同类型的指令?
Directive是当JSP页面被编译成Servlet的时候,JSP引擎要处理的指令。Directive用来设置页面级别的指令,从外部文件插入数据,指定自定义的标签库。Directive是定义在<%@ 和 %>之间的。下面列出了不同类型的Directive:
- 包含指令(Include directive):用来包含文件和合并文件内容到当前的页面。
- 页面指令(Page directive):用来定义JSP页面中特定的属性,比如错误页面和缓冲区。
- Taglib指令: 用来声明页面中使用的自定义的标签库。
111.什么是JSP动作(JSP action)?
JSP动作以XML语法的结构来控制Servlet引擎的行为。当JSP页面被请求的时候,JSP动作会被执行。它们可以被动态的插入到文件中,重用JavaBean组件,转发用户到其他的页面,或者是给Java插件产生HTML代码。下面列出了可用的动作:
- jsp:include-当JSP页面被请求的时候包含一个文件。
- jsp:useBean-找出或者是初始化Javabean。
- jsp:setProperty-设置JavaBean的属性。
- jsp:getProperty-获取JavaBean的属性。
- jsp:forward-把请求转发到新的页面。
- jsp:plugin-产生特定浏览器的代码。
112.什么是Scriptlets?
JSP技术中,scriptlet是嵌入在JSP页面中的一段Java代码。scriptlet是位于标签内部的所有的东西,在标签与标签之间,用户可以添加任意有效的scriplet。
113.声明(Decalaration)在哪里?
声明跟Java中的变量声明很相似,它用来声明随后要被表达式或者scriptlet使用的变量。添加的声明必须要用开始和结束标签包起来。
114.什么是表达式(Expression)?
【列表很长,可以分上、中、下发布】
JSP表达式是Web服务器把脚本语言表达式的值转化成一个String对象,插入到返回给客户端的数据流中。表达式是在<%=和%>这两个标签之间定义的。
115.隐含对象是什么意思?有哪些隐含对象?
JSP隐含对象是页面中的一些Java对象,JSP容器让这些Java对象可以为开发者所使用。开发者不用明确的声明就可以直接使用他们。JSP隐含对象也叫做预定义变量。下面列出了JSP页面中的隐含对象:
- application
- page
- request
- response
- session
- exception
- out
- config
- pageContext
1.面向对象和面向过程的区别 面向过程 优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。 缺点:没有面向对象易维护、易复用、易扩展
面向对象 优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护 缺点:性能比面向过程低
2.Java的四个基本特性(抽象、封装、继承,多态) 抽象:就是把现实生活中的某一类东西提取出来,用程序代码表示,我们通常叫做类或者接口。抽象包括两个方面:一个是数据抽象,一个是过程抽象。数据抽象也就是对象的属性。过程抽象是对象的行为特征。 封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行封装隐藏。封装分为属性的封装和方法的封装。 继承:是对有着共同特性的多类事物,进行再抽象成一个类。这个类就是多类事物的父类。父类的意义在于抽取多类事物的共性。 多态:允许不同类的对象对同一消息做出响应。方法的重载、类的覆盖正体现了多态。
3.重载和重写的区别 重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。 重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类;如果父类方法访问修饰符为private则子类中就不是重写。
4.构造器Constructor是否可被override 构造器不能被重写,不能用static修饰构造器,只能用 public private protected这三个权限修饰符,且不能有返回语句。
5.访问控制符public,protected,private,以及默认的区别 private只有在本类中才能访问; public在任何地方都能访问; protected在同包内的类及包外的子类能访问; 默认不写在同包内能访问。
6.是否可以继承String类 String类是final类故不可以继承,一切由final修饰过的都不能继承
7.String和StringBuffer、StringBuilder的区别 可变性: String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。 StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[] value,这两种对象都是可变的。 线程安全性: String中的对象是不可变的,也就可以理解为常量,线程安全。 AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。 性能: 每次对String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
8.hashCode和equals方法的关系 equals相等,hashcode必相等;hashcode相等,equals可能不相等。
9.抽象类和接口的区别 语法层次: 抽象类和接口分别给出了不同的语法定义 设计层次: 抽象层次不同,抽象类是对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。 跨域不同,抽象类所体现的是一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在”is-a” 关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上是一致的,仅仅是实现了接口定义的契约而已,”like-a”的关系。。 设计层次不同,抽象类是自底向上抽象而来的,接口是自顶向下设计出来的。
10.自动装箱与拆箱 装箱:将基本类型用它们对应的引用类型包装起来; 拆箱:将包装类型转换为基本数据类型; Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率,由编译器来完成,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。
11.什么是泛型、为什么要使用以及泛型擦除 泛型,即“参数化类型”。 创建集合时就指定集合元素的类型,该集合只能保存其指定类型的元素,避免使用强制类型转换。 Java编译器生成的字节码是不包涵泛型信息的,泛型类型信息将在编译处理是被擦除,这个过程即类型擦除。 泛型擦除可以简单的理解为将泛型java代码转换为普通java代码,只不过编译器更直接点,将泛型java代码直接转换成普通java字节码。 类型擦除的主要过程如下: 一.将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。 二.移除所有的类型参数。
12.Java中的集合类及关系图 List和Set继承自Collection接口。 Set无序不允许元素重复。HashSet和TreeSet是两个主要的实现类。 List有序且允许元素重复。ArrayList、LinkedList和Vector是三个主要的实现类。 Map也属于集合系统,但和Collection接口没关系。Map是key对value的映射集合,其中key列就是一个集合。key不能重复,但是value可以重复。 HashMap、TreeMap和Hashtable是三个主要的实现类。 SortedSet和SortedMap接口对元素按指定规则排序,SortedMap是对key列进行排序。
13.HashMap实现原理 具体原理一句两句也说不清楚,网络文章: http://zhangshixi.iteye.com/blog/672697 http://www.admin10000.com/document/3322.html
14.HashTable实现原理 具体原理一句两句也说不清楚,网络文章: http://www.cnblogs.com/skywang12345/p/3310887.htmlhttp://blog.csdn.net/chdjj/article/details/38581035
15.HashMap和HashTable区别 一.HashTable的方法前面都有synchronized来同步,是线程安全的;HashMap未经同步,是非线程安全的。 二.HashTable不允许null值(key和value都不可以) ;HashMap允许null值(key和value都可以)。 三.HashTable有一个contains(Object value)功能和containsValue(Object value)功能一样。 四.HashTable使用Enumeration进行遍历;HashMap使用Iterator进行遍历。 五.HashTable中hash数组默认大小是11,增加的方式是 old*2+1;HashMap中hash数组的默认大小是16,而且一定是2的指数。 六.哈希值的使用不同,HashTable直接使用对象的hashCode; HashMap重新计算hash值,而且用与代替求模。
16.ArrayList和vector区别 ArrayList和 Vector都实现了List接口, 都是通过数组实现的。 Vector是线程安全的,而ArrayList是非线程安全的。 List第一次创建的时候,会有一个初始大小,随着不断向List中增加元素,当 List 认为容量不够的时候就会进行扩容。Vector缺省情况下自动增长原来一倍的数组长度,ArrayList增长原来的50%。
17.ArrayList和LinkedList区别及使用场景 ArrayList底层是用数组实现的,可以认为ArrayList是一个可改变大小的数组。随着越来越多的元素被添加到ArrayList中,其规模是动态增加的。 LinkedList底层是通过双向链表实现的, LinkedList和ArrayList相比,增删的速度较快。但是查询和修改值的速度较慢。同时,LinkedList还实现了Queue接口,所以他还提供了offer(), peek(), poll()等方法。 LinkedList更适合从中间插入或者删除(链表的特性)。 ArrayList更适合检索和在末尾插入或删除(数组的特性)。
18.Collection和Collections的区别 java.util.Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。 java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
19.Concurrenthashmap实现原理 具体原理一句两句也说不清楚,网络文章: http://www.cnblogs.com/ITtangtang/p/3948786.html http://ifeve.com/concurrenthashmap/
20.Error、Exception区别 Error类和Exception类的父类都是throwable类,他们的区别是: Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。 Exception类表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。
21.Unchecked Exception和Checked Exception,各列举几个 Unchecked Exception: a. 指的是程序的瑕疵或逻辑错误,并且在运行时无法恢复。 b. 包括Error与RuntimeException及其子类,如:OutOfMemoryError, UndeclaredThrowableException, IllegalArgumentException, IllegalMonitorStateException, NullPointerException, IllegalStateException, IndexOutOfBoundsException等。 c. 语法上不需要声明抛出异常。
Checked Exception: a. 代表程序不能直接控制的无效外界情况(如用户输入,数据库问题,网络异常,文件丢失等) b. 除了Error和RuntimeException及其子类之外,如:ClassNotFoundException, NamingException, ServletException, SQLException, IOException等。 c. 需要try catch处理或throws声明抛出异常。
22.Java中如何实现代理机制(JDK、CGLIB) JDK动态代理:代理类和目标类实现了共同的接口,用到InvocationHandler接口。 CGLIB动态代理:代理类是目标类的子类, 用到MethodInterceptor接口
23.多线程的实现方式 继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。
24.线程的状态转换
25.如何停止一个线程 这个问题简单总结不一定说的清,看一篇网络文章: http://www.cnblogs.com/greta/p/5624839.html
26.什么是线程安全 线程安全就是多线程访问同一代码,不会产生不确定的结果。
27.如何保证线程安全 对非安全的代码进行加锁控制; 使用线程安全的类; 多线程并发情况下,线程共享的变量改为方法级的局部变量。
28.Synchronized如何使用 synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 一. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; 二. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 三. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象; 四. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
29.synchronized和Lock的区别 主要相同点:Lock能完成synchronized所实现的所有功能 主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。Lock的锁定是通过代码实现的,而synchronized是在JVM层面上实现的,synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。Lock锁的范围有局限性,块范围,而synchronized可以锁住块、对象、类。
30.多线程如何进行信息交互 void notify() 唤醒在此对象监视器上等待的单个线程。 void notifyAll() 唤醒在此对象监视器上等待的所有线程。 void wait() 导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法。 void wait(long timeout) 导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者超过指定的时间量。 void wait(long timeout, int nanos) 导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。
31.sleep和wait的区别(考察的方向是是否会释放锁) sleep()方法是Thread类中方法,而wait()方法是Object类中的方法。 sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态,在调用sleep()方法的过程中,线程不会释放对象锁。而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备
32.多线程与死锁 死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 产生死锁的原因: 一.因为系统资源不足。 二.进程运行推进的顺序不合适。 三.资源分配不当。
33.如何才能产生死锁 产生死锁的四个必要条件: 一.互斥条件:所谓互斥就是进程在某一时间内独占资源。 二.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 三.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。 四.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
34.死锁的预防 打破产生死锁的四个必要条件中的一个或几个,保证系统不会进入死锁状态。 一.打破互斥条件。即允许进程同时访问某些资源。但是,有的资源是不允许被同时访问的,像打印机等等,这是由资源本身的属性所决定的。所以,这种办法并无实用价值。 二.打破不可抢占条件。即允许进程强行从占有者那里夺取某些资源。就是说,当一个进程已占有了某些资源,它又申请新的资源,但不能立即被满足时,它必须释放所占有的全部资源,以后再重新申请。它所释放的资源可以分配给其它进程。这就相当于该进程占有的资源被隐蔽地强占了。这种预防死锁的方法实现起来困难,会降低系统性能。 三.打破占有且申请条件。可以实行资源预先分配策略。即进程在运行前一次性地向系统申请它所需要的全部资源。如果某个进程所需的全部资源得不到满足,则不分配任何资源,此进程暂不运行。只有当系统能够满足当前进程的全部资源需求时,才一次性地将所申请的资源全部分配给该进程。由于运行的进程已占有了它所需的全部资源,所以不会发生占有资源又申请资源的现象,因此不会发生死锁。 四.打破循环等待条件,实行资源有序分配策略。采用这种策略,即把资源事先分类编号,按号分配,使进程在申请,占用资源时不会形成环路。所有进程对资源的请求必须严格按资源序号递增的顺序提出。进程占用了小号资源,才能申请大号资源,就不会产生环路,从而预防了死锁。
35.什么叫守护线程,用什么方法实现守护线程 守护线程是为其他线程的运行提供服务的线程。 setDaemon(boolean on)方法可以方便的设置线程的Daemon模式,true为守护模式,false为用户模式。
36.Java线程池技术及原理 这个有点长,还是看一篇文章吧: http://www.importnew.com/19011.html http://www.cnblogs.com/dolphin0520/p/3932921.html
37.java并发包concurrent及常用的类 这个内容有点多,需要仔细看: 并发包诸类概览: http://www.raychase.net/1912 线程池: http://www.cnblogs.com/dolphin0520/p/3932921.html 锁: http://www.cnblogs.com/dolphin0520/p/3923167.html 集合: http://www.cnblogs.com/huangfox/archive/2012/08/16/2642666.html
38.volatile关键字 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操作。 Java语言中的volatile变量可以被看作是一种 “程度较轻的 synchronized”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是synchronized的一部分。锁提供了两种主要特性:互斥(mutual exclusion)和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的,如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。Volatile变量具有synchronized的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。 要使volatile变量提供理想的线程安全,必须同时满足下面两个条件:对变量的写操作不依赖于当前值;该变量没有包含在具有其他变量的不变式中。 第一个条件的限制使volatile变量不能用作线程安全计数器。虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作,必须以原子方式执行,而volatile不能提供必须的原子特性。实现正确的操作需要使 x 的值在操作期间保持不变,而 volatile 变量无法实现这点。 每一个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。
read and load 从主存复制变量到当前工作内存 use and assign 执行代码,改变共享变量值 store and write 用工作内存数据刷新主存相关内容 其中use and assign 可以多次出现,但是这一些操作并不是原子性,也就是 在read load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果会和预期不一样。
39.Java中的NIO,BIO,AIO分别是什么
BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。 NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。 AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理.AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。
40.IO和NIO区别 一.IO是面向流的,NIO是面向缓冲区的。 二.IO的各种流是阻塞的,NIO是非阻塞模式。 三.Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
41.序列化与反序列化 把对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为对象的过程称为对象的反序列化。 对象的序列化主要有两种用途: 一.把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中; 二.在网络上传送对象的字节序列。 当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
42.常见的序列化协议有哪些 Protobuf, Thrift, Hessian, Kryo
43.内存溢出和内存泄漏的区别 内存溢出是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory。 内存泄漏是指分配出去的内存不再使用,但是无法回收。
44.Java内存模型及各个区域的OOM,如何重现OOM 这部分内容很重要,详细阅读《深入理解Java虚拟机》,也可以详细阅读这篇网络文章 http://hllvm.group.iteye.com/group/wiki/2857-JVM
45.出现OOM如何解决 一. 可通过命令定期抓取heap dump或者启动参数OOM时自动抓取heap dump文件。 二. 通过对比多个heap dump,以及heap dump的内容,分析代码找出内存占用最多的地方。 三. 分析占用的内存对象,是否是因为错误导致的内存未及时释放,或者数据过多导致的内存溢出。
46.用什么工具可以查出内存泄漏 一. Memory Analyzer-是一款开源的JAVA内存分析软件,查找内存泄漏,能容易找到大块内存并验证谁在一直占用它,它是基于Eclipse RCP(Rich Client Platform),可以下载RCP的独立版本或者Eclipse的插件。 二. JProbe-分析Java的内存泄漏。 三. JProfiler-一个全功能的Java剖析工具,专用于分析J2SE和J2EE应用程序。它把CPU、执行绪和内存的剖析组合在一个强大的应用中,GUI可以找到效能瓶颈、抓出内存泄漏、并解决执行绪的问题。 四. JRockit-用来诊断Java内存泄漏并指出根本原因,专门针对Intel平台并得到优化,能在Intel硬件上获得最高的性能。 五. YourKit .NET & Java Profiling业界领先的Java和.NET程序性能分析工具。 六. AutomatedQA -AutomatedQA的获奖产品performance profiling和memory debugging工具集的下一代替换产品,支持Microsoft, Borland, Intel, Compaq 和 GNU编译器。可以为.NET和Windows程序生成全面细致的报告,从而帮助您轻松隔离并排除代码中含有的性能问题和内存/资源泄露问题。支持.Net 1.0,1.1,2.0,3.0和Windows 32/64位应用程序。 七. Compuware DevPartner Java Edition-包含Java内存检测,代码覆盖率测试,代码性能测试,线程死锁,分布式应用等几大功能模块
47.Java内存管理及回收算法 阅读这篇文章: http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html
48.Java类加载器及如何加载类(双亲委派) 阅读文章: https://www.ibm.com/developerworks/cn/java/j-lo-classloader/ (推荐) 或 http://blog.csdn.net/zhoudaxia/article/details/35824249
49.xml解析方式 一.DOM(JAXP Crimson解析器) 二.SAX 三.JDOM 四.DOM4J 区别: 一.DOM4J性能最好,连Sun的JAXM也在用DOM4J。目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J. 二.JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。在小文档情况下还值得考虑使用DOM和JDOM。虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。 三.SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。
50.Statement和PreparedStatement之间的区别 一.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程 二.使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement 对象的开销比Statement大,对于一次性操作并不会带来额外的好处。 三.statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译得, preparedstatement支持批处理 四.代码片段1: String updateString = “UPDATE COFFEES SET SALES = 75 ” + “WHERE COF_NAME LIKE ′Colombian′”; stmt.executeUpdate(updateString); 代码片段2: PreparedStatement updateSales = con.prepareStatement(“UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? “); updateSales.setInt(1, 75); updateSales.setString(2, “Colombian”); updateSales.executeUpdate(); 片断2和片断1的区别在于,后者使用了PreparedStatement对象,而前者是普通的Statement对象。PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。 这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需更改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。如果仅仅执行了一次的话,它应该和普通的对象毫无差异,体现不出它预编译的优越性。 五.执行许多SQL语句的JDBC程序产生大量的Statement和PreparedStatement对象。通常认为PreparedStatement对象比Statement对象更有效,特别是如果带有不同参数的同一SQL语句被多次执行的时候。PreparedStatement对象允许数据库预编译SQL语句,这样在随后的运行中可以节省时间并增加代码的可读性。 然而,在Oracle环境中,开发人员实际上有更大的灵活性。当使用Statement或PreparedStatement对象时,Oracle数据库会缓存SQL语句以便以后使用。在一些情况下,由于驱动器自身需要额外的处理和在Java应用程序和Oracle服务器间增加的网络活动,执行PreparedStatement对象实际上会花更长的时间。 然而,除了缓冲的问题之外,至少还有一个更好的原因使我们在企业应用程序中更喜欢使用PreparedStatement对象,那就是安全性。传递给PreparedStatement对象的参数可以被强制进行类型转换,使开发人员可以确保在插入或查询数据时与底层的数据库格式匹配。 当处理公共Web站点上的用户传来的数据的时候,安全性的问题就变得极为重要。传递给PreparedStatement的字符串参数会自动被驱动器忽略。最简单的情况下,这就意味着当你的程序试着将字符串“D’Angelo”插入到VARCHAR2中时,该语句将不会识别第一个“,”,从而导致悲惨的失败。几乎很少有必要创建你自己的字符串忽略代码。 在Web环境中,有恶意的用户会利用那些设计不完善的、不能正确处理字符串的应用程序。特别是在公共Web站点上,在没有首先通过PreparedStatement对象处理的情况下,所有的用户输入都不应该传递给SQL语句。此外,在用户有机会修改SQL语句的地方,如HTML的隐藏区域或一个查询字符串上,SQL语句都不应该被显示出来。