中级Java软件开发面试题以及答案

1、谈谈对面向对象的理解;以及三大特征;

       面向对象是基于万物皆对象这个观点. 把一个对象抽象成类,具体上就是把一个对象的静态特征和动态特征抽象成属性和方法,也就是把一类事物的算法和数据结构封装在一个类之中,程序就是多个对象和互相之间的通信组成的。

比如把一个人看成一个对象,这个人就会有他的属性和行为;他有手、脚、嘴巴等就是他的属性,或者他会说话、会走路、会吃饭就是行为,同理我们也可以把这些都看成对象,所以一个对象是可以由多个对象组成的。

       面向对象具有封装性、继承性、多态性。封装就是隐蔽了对象内部不需要暴露的细节,使得内部细节的变动跟外界脱离,只依靠接口进行通信;即不用管这个方法是怎么实现的,只要知道他可以实现这个功能。封装性降低了编程的复杂性. 通过继承使得新建一个类变得容易,一个类继承了父类,则父类所有的非私有的方法和公用属性可以被这个类所调用。 而继承和实现接口所产生的多态,使得不同的类所产生的对象能够对相同的消息作出不同的反应,即在实现接口的情况下,同一个方法里的行为不同,极大地提高了代码的通用性.。

       总之,面向对象的特性提高了大型程序的重用性和可维护性。

2、String、StringBuffer、StringBuilder的区别;

1. String对象是不可改变的。 
2. 如果要修改字符串而不创建新的对象,则可以使用 StringBuilder 类。例如,当在一个循环中将许多字符串连接在一起时,使用 StringBuilder 类可以提升性能。 
3. 由于 String 的值一旦创建就不能再修改,所以称它是恒定的。看似能修改 String 的方法实际上只是返回一个包含修改内容的新 String。

4. StringBuffer可改变的Unicode字符序列,允许并发操作,是线程安全的。
5.  StringBuilder:可改变的Unicode字符序列操作同StringBuffer,只是不支持并发操作,非线程安全的 。
6. 不考虑线程安全前提下,StringBuilder性能最高,StringBuffer次之,String比较差。  为什么StringBuffer的性能比String高?主要原因在于String类是不可变类,任何对String引用指向的字符串作出的修改都会导致生成新的字符串(对象),而对StringBuffer的修改则不会导致新对象的产生。
那么为什么StringBuilder的性能比StringBuffer的高呢?这则与线程安全有关。StringBuilder是线程非安全的。

3、HashMap、LinkedHashMap、TreeMap的区别;

HashMap,LinkedHashMap,TreeMap都属于Map

Map 主要用于存储键(key)值(value)对,根据键得到值,因此键不允许键重复,但允许值重复。

HashMap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null;允许多条记录的值为Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力。
LinkedHashMap 也是一个HashMap,但是内部维持了一个双向链表,可以保持顺序;
TreeMap 不仅可以保持顺序,而且可以用于排序;
详细操作看文章……

4、ArrayList、LinkedList、vector 的区别;

一、同步性 
ArrayList,LinkedList是不同步的,而Vestor是同步的。所以如果不要求线程安全的话,可以使用ArrayList或LinkedList,可以节省为同步而耗费的开销。但在多线程的情况下,就得使用Vector。当然,也可以通过一些办法包装ArrayList,LinkedList,使他们也达到同步,但效率可能会有所降低。 
二、数据增长 
从内部实现机制来讲ArrayList和Vector都是使用Object的数组形式来存储的。

当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度;

ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以要在集合中保存大量的数据那么使用Vector有一些优势。

三、检索、插入、删除对象的效率 
ArrayList和Vector中,是用下标来检索一个对象,或在集合的末尾插入、删除一个对象的时间是一样的。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长。 
LinkedList中,在插入、删除集合中任何位置的元素所花费的时间都是一样的,但它在查询一个元素的时候比较慢。 
一般大家都知道ArrayList和LinkedList的大致区别: 
      1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 
      2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 
     3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

5、抽象类与接口(interface)的区别;

1.abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。

  2.在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员),所有的成员方法都是abstract的。

  3.abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。 

  4.实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法。接口中则不能有实现方法。

  5.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。

  6.抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。 

  7.接口中的方法默认都是 public,abstract 类型的。 


7、多线程是什么?用什么实现?

多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。如:火车是一个进程,而车厢就是线程,车厢脱离了火车是不能开动的,同理可以由多个车厢,则一个进程是有多个线程来提高效率的。

在JAVA中,要开始一个线程,有两种方式。一是直接调用Thread实例的start()方法,继承Thread类;二是实现Runnable接口,将Runable实例传给一个Thread实例然后调用它的start()方法。

实现同步也有两种,一种是用同步方法,一种是用同步块, 同步方法就是在方法返回类型后面加上synchronized, 比如:public void synchronized add(){...}同步块就是直接写:synchronized (这里写需要同步的对象){...}

8、概述一下SpringMVC的工作原理。

1、客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet.

2、DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器(Handler)。

3-4、DispatcherServlet根据HandlerMapping找到对应的Handler,将处理权交给Handler(Handler将具体的处理进行封装),再由具体的HandlerAdapter对Handler进行具体的调用。

5、Handler对数据处理完成以后将返回一个ModelAndView()对象给DispatcherServlet。

6、Handler返回的ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet通过ViewResolver将逻辑视图转化为真正的视图View。

7、Dispatcher通过model解析出ModelAndView()中的参数进行解析最终展现出完整的view并返回给客户端。


9、关于Spring,IOC和AOP的概念;

spring 的优点?
1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 
2.可以使用容易提供的众多服务,如事务管理,消息服务等 
3.容器提供单例模式支持 
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能 
5.容器提供了众多的辅助类,能加快应用的开发 
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等 
7.spring属于低侵入式设计,代码的污染极低 
8.独立于各种应用服务器 
9.spring的DI机制降低了业务对象替换的复杂性 
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring的部分或全部 

什么是DI机制? 
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色 
需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中 
创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者 
因此也称为依赖注入。 
spring以动态灵活的方式来管理对象 , 注入的两种方式,设置注入和构造注入。 
设置注入的优点:直观,自然 
构造注入的优点:可以在构造器中决定依赖关系的顺序。 

什么是AOP? 
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面 
1.面向切面编程提供声明式事务管理 
2.spring支持用户自定义的切面 

面向切面编程(aop)是对面向对象编程(oop)的补充, 
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。 
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象, 
是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。 

aop框架具有的两个特征: 
1.各个步骤之间的良好隔离性 
2.源代码无关性 

10、spring事务怎么配置的。

第一种方式:每个Bean都有一个代理;

 第二种方式:所有Bean共享一个代理基类;

第三种方式:使用拦截器;

第四种方式:使用tx标签配置的拦截器;

第五种方式:全注解;

详细见文章……

11、Mybatis与hibernate的区别。

1. hibernate是全自动,而mybatis是半自动。

hibernate完全可以通过对象关系模型实现对数据库的操作,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql。而mybatis仅有基本的字段映射,对象数据以及对象实际关系仍然需要通过手写sql来实现和管理。

2. hibernate数据库移植性远大于mybatis。

hibernate通过它强大的映射结构和hql语言,大大降低了对象与数据库(oracle、mysql等)的耦合性,而mybatis由于需要手写sql,因此与数据库的耦合性直接取决于程序员写sql的方法,如果sql不具通用性而用了很多某数据库特性的sql语句的话,移植性也会随之降低很多,成本很高。

3. hibernate拥有完整的日志系统,mybatis则欠缺一些。

hibernate日志系统非常健全,涉及广泛,包括:sql记录、关系异常、优化警告、缓存提示、脏数据警告等;而mybatis则除了基本记录功能外,功能薄弱很多。

4. mybatis相比hibernate需要关心很多细节

hibernate配置要比mybatis复杂的多,学习成本也比mybatis高。但也正因为mybatis使用简单,才导致它要比hibernate关心很多技术细节。mybatis由于不用考虑很多细节,开发模式上与传统jdbc区别很小,因此很容易上手并开发项目,但忽略细节会导致项目前期bug较多,因而开发出相对稳定的软件很慢,而开发出软件却很快。hibernate则正好与之相反。但是如果使用hibernate很熟练的话,实际上开发效率丝毫不差于甚至超越mybatis。

5. sql直接优化上,mybatis要比hibernate方便很多

由于mybatis的sql都是写在xml里,因此优化sql比hibernate方便很多。而hibernate的sql很多都是自动生成的,无法直接维护sql;虽有hql,但功能还是不及sql强大,见到报表等变态需求时,hql也歇菜,也就是说hql是有局限的;hibernate虽然也支持原生sql,但开发模式上却与orm不同,需要转换思维,因此使用上不是非常方便。总之写sql的灵活度上hibernate不及mybatis。

12、Mybatis中怎么调用存储过程。

1.在数据库中创建以下的存储过程:

 

java代码:
  1. create or replace procedure pro_hello(p_user_name in varchar2,p_result out varchar2) is  
  2. begin  
  3.   p_result := 'hello,' || p_user_name;  
  4. end;  

2.编写SQL映射文件mapper.xml:

 

java代码:
  1. <select id="proHello" statementType="CALLABLE">  
  2. <![CDATA[  
  3.     {call pro_hello (#{p_user_name,mode=IN,jdbcType=VARCHAR},#{result,mode=OUT,jdbcType=VARCHAR})}  
  4. ]]>  
  5. </select>  

3.编写JAVA代码调用存储过程

 

java代码:
  1. public class ProcedureTest {  
  2.           
  3.          public static void main(String[] args) throws IOException {  
  4.             String resource = "mybatis.cfg.xml";  
  5.             Reader reader = Resources.getResourceAsReader(resource);  
  6.             SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);  
  7.          
  8.             SqlSession session = ssf.openSession();  
  9.          
  10.            try {  
  11.                  Map<String, String> param = new HashMap<String, String>();  
  12.                  param.put("p_user_name""zhangsan");  
  13.                  String returnValue = (String) session.selectOne("User.proHello", param);  
  14.                  System.out.println("message=" + param.get("p_user_name"));  
  15.                  System.out.println("result=" + param.get("result"));  
  16.                  System.out.println("returnValue=" + returnValue);  
  17.    
  18.            } catch (Exception e) {  
  19.                 e.printStackTrace();  
  20.            } finally {  
  21.               session.close();  
  22.           }  
  23.        }  
  24. }  

13、存储过程与函数的区别。

A:函数必须有返回值,而过程没有. 
B:函数可以单独执行.而过程必须通过execute执行. 
C:函数可以嵌入到SQL语句中执行.而过程不行. 
其实我们可以将比较复杂的查询写成函数.然后到存储过程中去调用这些函数. 
Oracle中的函数与存储过程的特点: 
A. 一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。 
B.对于存储过程来说可以返回参数,而函数只能返回值或者表对象。 
C.存储过程一般是作为一个独立的部分来执行,而函数可以作为查询语句的一个部分来调用,由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面


14、数据库的三大范式。

1 第一范式(1NF)
在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。
所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一范式(1NF)中表的每一行只包含一个实例的信息。例如,对于图3-2 中的员工信息表,不能将员工信息都放在一列中显示,也不能将其中的两列或多列在一列中显示;员工信息表的每一行只表示一个员工的信息,一个员工的信息在表中只出现一次。简而言之,第一范式就是无重复的列。

2 第二范式(2NF)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。如图3-2 员工信息表中加上了员工编号(emp_id)列,因为每个员工的员工编号是惟一的,因此每个员工可以被惟一区分。这个惟一属性列被称为主关键字或主键、主码。
第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。简而言之,第二范式就是非主属性非部分依赖于主关键字。

3 第三范式(3NF)
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在图3-2的员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性。


15、sql优化有哪些?分别起了什么作用?

1、IN 操作符

推荐方案:在业务密集的SQL当中尽量不采用IN操作符,用EXISTS 方案代替。

2、NOT IN操作符

此操作是强列不推荐使用的,因为它不能应用表的索引。推荐方案:用NOT EXISTS 方案代替

3、IS NULL 或 IS NOT NULL操作(判断字段是否为空)

判断字段是否为空一般是不会应用索引的,因为索引是不索引空值的。

推荐方案:用其它相同功能的操作运算代替,如:a is not null 改为 a>0 或a>’’等。不允许字段为空,而用一个缺省值代替空值,如申请中状态字段不允许为空,缺省为申请。

4、LIKE操作符

LIKE操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,如LIKE ‘%5400%’ 这种查询不会引用索引,而LIKE ‘X5400%’则会引用范围索引。

一个实际例子:用YW_YHJBQK表中营业编号后面的户标识号可来查询营业编号 YY_BH LIKE ‘%5400%’ 这个条件会产生全表扫描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 则会利用YY_BH的索引进行两个范围的查询,性能肯定大大提高。

5、UNION操作符

UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。如:
select * from gc_dfys
union
select * from ls_jg_dfys
这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。

6、尽量将多条sql语句写成一条sql语句来查询

7、多表查询用别名查询

8、用索引提高效率


  • 11
    点赞
  • 122
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值