Java实用面试题五十道

本文列举了50道Java面试题,涵盖了持久化、对象关系映射、MyBatis缓存、动态SQL、Spring特性、事务管理等多个方面。通过对这些问题的解答,深入探讨了Java开发中的关键概念和技术,帮助读者准备Java面试并提升技术水平。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、举例说明什么是持久化。

答案:

持久化是将程序数据在持久状态和瞬时状态间转换的机制。JDBC 就是一种持久化机制,文件 IO 也是一种持久化机制。

 

2、举例说明什么是对象关系映射。

答案:

持久状态的数据一般保存在数据库中,是一种关系模型,如,用户数据保存在 user 表里,userName 字段保存用户的名称,birthday 字段保存用户的出生日期。一条数据库记录对应一个用户。瞬时的数据一般以面向对象的方式被组织,并保存在内存中,如,对应于 user 表,有 User 类,User 类有 userName 属性和 birthday 属性,对应 user 表的 userName 字段和birthday 字段。关系型数据和对象数据间存在着天然的映射关系,这种映射关系称为“对象—关系映射”,又称为 ORM。

 

3、谈谈 resultType 和 resultMap 的区别和具体的应用场景。

答案:

resultType:将查询结果按照 sql 列名 pojo 属性名一致性映射到 pojo 中。场景:查询用户信息。

resultMap:使用 association 和 collection 完成一对一和一对多高级映射(对结果有特殊的映射要求)。场景:查询订单及关联用户信息,查询用户权限范围模块及模块下的菜单。

 

4、谈谈 Mybatis 一级缓存和二级缓存的区别。

答案:

一级缓存是 SqlSession 级别的缓存。在操作数据库时需要构造 sqlSession 对象,在对象中有一个数据结构用于存储缓存数据。不同的 sqlSession 之间的缓存数据区域是互相不影响的。也就是只能作用在同一个 sqlSession 中,不同的 sqlSession 中的缓存是互相不能读取的。二级缓存是 mapper 级别的缓存,多个 SqlSession 去操作同一个 Mapper 的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。Mapper 有一个二级缓存区域(按 namespace 分),其它 mapper 也有自己的二级缓存区域(按 namespace 分)。每一个namespace 的 mapper 都有一个二级缓存区域,两个 mapper 的 namespace 如果相同,这两个 mapper 执行 sql 查询到数据将存在相同的二级缓存区域中。

 

5、说明如何使用 foreach、来完成复杂查询以及它的应用场景。

答案:

对于一些 SQL 语句中含有 in 条件,需要迭代条件集合来生成,MyBatis 入参为数组类型或者 List、Map,使用 foreach 标签来实现 SQL 条件的迭代。使用 foreach 可指定一个集合,并指定开始和结束的字符,也可加入一个分隔符到迭代器中,并能够智能处理该分隔符,不会出现多余的分隔符。

 

6、说明 Mybatis 集合参数入参如何处理。

答案:无论 MyBatis 的入参是哪种参数类型,MyBatis 都会将参数放在一个 Map 中:

若入参为 List:默认“list”作为 key,该 List 即为 value

若入参为数组:默认“array”作为 key,该数组即为 value

若入参为 Map:键值不变通过 foreach 标签去实现 SQL 条件的迭代。

 

7、说出 3 个动态 SQL 的组合及其作用。

答案:

if+set:完成按条件更新操作

if+where:完成多条件查询

if+trim:完成多条件查询或更新操作,可替代 if+set 或 if+where

choose+when+otherwise:完成条件查询(多条件下,选择其一)

foreach:完成复杂查询,主要用于 in 条件查询中,迭代集合。

 

8、谈谈控制反转和依赖注入的区别和原理。

答案:

控制反转:创建对象实例的控制权从代码控制剥离到 IOC 容器控制。

依赖注入:创建对象实例时,为这个对象注入属性值或其它对象实例。

原理:以文件流读取配置文件,再通过反射创建对象并赋值。

 

9、什么是 AOP,以及 AOP 涉及的设计模式。

答案:

AOP(面向切面编程),简单地说就是在不改变原程序的基础上为代码段增加新的功能,对代码进行增强处理。它的设计思想来源于代理设计模式中的动态代理。

 

10、请简述在数据库事务中什么是脏读,并举例说明。

答案:

脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。

例如 A 开启事务-->B 开启事务-->B 修改数据且未提交事务-->A 查询数据

 

11、请简述在数据库事务中什么是不可重复读,并举例说明。

答案:

不可重复读,是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。

例如 A 开启事务-->A 首次查询数据-->B 开启事务-->B 修改数据并提交事务-->A 二次查询数据

 

12、请简述在数据库事务中什么是幻读,并举例说明。

答案:

幻读:是指当事务不是独立执行时发生的一种现象,当一个事务对一个表中的数据进行了修改,这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样。

例如 A 开启事务-->A 更新所有数据-->B 开启事务-->B 插入数据并提交事务-->A 提交事务-->A 查询数据

 

13、谈谈 Spring 通过配置文件自动装配的优缺点。

答案:

优点是大大简化了维护 Bean 注入的配置。缺点是降低了依赖关系的清晰性和透明性。依赖关系的装配依赖于源文件的属性名,导致 Bean 与 Bean 之间的耦合降低到代码层次,不利于高层次解耦。

 

14、请简述 Spring 配置文件的两种拆分策略。

答案:

如果每个开发人员负责一个模块时,我们采用公用配置(包含数据源、事务等)+ 每个系统模块(包含 dao、service 及 action)一个单独配置文件的形式。

如果开发是按照分层进行的分工,我们采用公用配置(包含数据源、事务等)+ DAO Bean配置 + 业务逻辑 Bean 配置 + Action Bean 配置的形式。

 

15、请简述 MVC 模式中各模块的作用。

答案:

视图(View):负责格式化数据并把它们呈现给用户,包括数据展示、用户交互、数据验证、界面设计等功能。

控制器(Controller) :负责接收并转发请求,对请求进行处理后指派视图并将响应结果发送给客户端。

模型(Model):模型对象拥有最多的处理任务,是应用程序的主体部分,它负责数据逻辑(业务规则)的处理和实现数据操作(在数据库中存取数据)。

 

16、请简述什么是单例模式及其特点。

答案:

单例模式就是系统运行期间,有且仅有一个实例。

特点:一个类只有一个实例,为了保证运行期间的实例唯一性,它必须自行创建这个实例并必须自行向整个系统提供这个实例的访问接口。

 

17、请简述什么是延迟加载,Mybatis 如何实现延迟加载。

答案:

延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出 sql语句进行查询。配置 resultMap 时, 在 association 或 collection 配置 select 属性指定 statementId,配置colum 指定传递的关联 id

 

18、SpringMVC 设定重定向和转发的两种方法。

答案:

方法 1:以 Servlet API 入参,实现转发和重定向

方法 2:在返回值前面加"forward:"实现转发,在返回值前面加"redirect:"实现重定向。

 

19、Mybatis 中#和$的区别。

答案:#相当于对数据加上双引号,$相当于直接显示数据。

1、#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号如:order by #id,如果传入的值是 111,那么解析成 sql 时的值为 order by "111"。

2、$将传入的数据直接显示生成在 sql 中。如:order by $id,如果传入的值是 111,那么解析成 sql 时的值为 order by 111。

3、#方式能够很大程度防止 sql 注入,$方式无法防止 sql 注入,一般能用#的就别用$。

 

20、使用 MyBatis 的 mapper 接口调用时有哪些要求。

答案:

1、Mapper 接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同

2、Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的parameterType的类型相同

3、Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同

4、Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径

 

21. 垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收

对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。

可以。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

 

22. 抽象方法

1).抽象类的声明:        abstract class 类名 目的是根据其格式来创建和修改新的类

2).抽象方法的声明:    abstract int mt_fa();

3).抽象类不一定有抽象方法,但是,有抽象方法的类一定是抽象类。

4).如果用非抽象类继承抽象类,那么这个非抽象类必须覆盖自己父类的所有方法.不然会报错.

5)abstract不能与private、static、final、native并列修饰同一个方法。

 

23. JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?

JSP在本质上就是SERVLET

Servlet完全是JAVA程序代码构成,擅长于流程控制和事务处理,通过Servlet来生成动态网页很不直观.

JSP由HTML代码和JSP标签构成,可以方便地编写动态网页.

因此在实际应用中采用Servlet来控制业务流程,而采用JSP来生成动态网页.

在struts框架中,JSP位于MVC设计模式的视图层,而Servlet位于控制层.

JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。

JSP编译后是“类servlet”。

Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP是Java和HTML组合成一个扩展名为.jsp的文件。

JSP侧重于视图,Servlet主要用于控制逻辑。

JSP中嵌入JAVA代码,而Servlet中嵌入HTML代码。

 

24.说出Servlet的生命周期,并说出Servlet和CGI的区别

Servlet被服务器实例化后

容器运行其init方法

请求到达时运行其service方法service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。

与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,

服务完成后就销毁,所以效率上低于servlet。

 

25.请解释&和&&、|和||的区别?

&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。

&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,例如,对于if(str != null && !str.equals(“”))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException如果将&&改为&,则会抛出NullPointerException异常。If(x==33 & ++y>0) y会增长,If(x==33 && ++y>0)不会增长

&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如,0x31 & 0x0f的结果为0x01。

 

26.数组有没有length()方法?String有没有length()方法?

答:数组没有length()方法,有length 的属性。String 有length()方法。JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆

 

27.构造器(constructor)是否可被重写(override)

构造器不能被继承,因此不能被重写,但可以被重载。

 

28. 如何实现对象克隆?

答:有两种方式:

  1). 实现Cloneable接口并重写Object类中的clone()方法; 

  2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,

 

29.阐述静态变量和实例变量的区别。

答:静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。

 

30.是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?

答:不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。

 

31.接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?

答:接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。

 

32一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制? 

答:可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致。

 

33.Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口? 

答:可以继承其他类或实现其他接口,在Swing编程和Android开发中常用此方式来实现事件监听和回调。

 

34.内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制? 

答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。

 

35.Java 中的final关键字有哪些用法? 

答:(1)修饰类:表示该类不能被继承;

(2)修饰方法:表示方法不能被重写;

(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)

 

36.子父类加载顺序;

创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器

 

37.数据类型之间的转换: 如何将字符串转换为基本数据类型? 如何将基本数据类型转换为字符串?

答: 调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;

 一种方法是将基本数据类型与空字符串("")连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf()方法返回相应字符串

 

38.什么时候用断言(assert)?

答:断言在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。一般来说,断言用于保证程序最基本、关键的正确性。断言检查通常在开发和测试时开启。为了保证程序的执行效率,在软件发布后断言检查通常是关闭的。断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true;如果表达式的值为false,那么系统会报告一个AssertionError。

 

39.List、Set、Map是否继承自Collection接口?

答:List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。

 

40.Collection和Collections的区别?

答:Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。

 

41.什么是线程池(thread pool)?

答:在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这就是”池化资源”技术产生的原因。线程池顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。

 

42.使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?

答:要提升读取数据的性能,可以指定通过结果集(ResultSet)对象的setFetchSize()方法指定每次抓取的记录数(典型的空间换时间策略);要提升更新数据的性能可以使用PreparedStatement语句构建批处理,将若干SQL语句置于一个批处理中执行

 

43.JDBC中如何进行事务处理?

答:Connection提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务;当事务完成后用commit()显式提交事务;如果在事务处理过程中发生异常则通过rollback()进行事务回滚。除此之外,从JDBC 3.0中还引入了Savepoint(保存点)的概念,允许通过代码设置保存点并让事务回滚到指定的保存点。

 

44.简述正则表达式及其用途。 

答:在编写处理字符串的程序时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

 

45. 简述一下你了解的设计模式。 

答:所谓设计模式,就是一套被反复使用的代码设计经验的总结(情境中一个问题经过证实的一个解决方案)。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使人们可以更加简单方便的复用成功的设计和体系结构。将已证实的技术表述成设计模式也会使新系统开发者更加容易理解其设计思路。

总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

 

46.你可以说出几个在JDK库中使用的设计模式吗?

装饰器设计模式(Decorator design pattern)被用于多个Java IO类中。单例模式(Singleton pattern)用于Runtime,Calendar和其他的一些类中。工厂模式(Factory pattern)被用于各种不可变的类如Boolean,像Boolean.valueOf,观察者模式(Observer pattern)被用于Swing和很多的事件监听中。

 

47.讲解JSP中的四种作用域。

答:JSP中的四种作用域包括page、request、session和application,具体来说:

- page代表与一个页面相关的对象和属性。

- request代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;需要在页面显示的临时数据可以置于此作用域。

- session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中。

- application代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。

 

48.Servlet中如何获取用户提交的查询参数或表单数据?

答:可以通过请求对象(HttpServletRequest)的getParameter()方法通过参数名获得参数值。如果有包含多个值的参数(例如复选框),可以通过请求对象的getParameterValues()方法获得。当然也可以通过请求对象的getParameterMap()获得一个参数名和参数值的映射(Map)。

 

49.如何设置请求的编码以及响应内容的类型?

答:通过请求对象(ServletRequest)的setCharacterEncoding(String)方法可以设置请求的编码,其实要彻底解决乱码问题就应该让页面、服务器、请求和响应、Java程序都使用统一的编码,最好的选择当然是UTF-8;通过响应对象(ServletResponse)的setContentType(String)方法可以设置响应内容的类型,当然也可以通过HttpServletResponsed对象的setHeader(String, String)方法来设置。

 

50.谈一下你对继承映射的理解。

答:继承关系的映射策略有三种:

① 每个继承结构一张表(table per class hierarchy),不管多少个子类都用一张表。

② 每个子类一张表(table per subclass),公共信息放一张表,特有信息放单独的表。

③ 每个具体类一张表(table per concrete class),有多少个子类就有多少张表。

第一种方式属于单表策略,其优点在于查询子类对象的时候无需表连接,查询速度快,适合多态查询;缺点是可能导致表很大。后两种方式属于多表策略,其优点在于数据存储紧凑,其缺点是需要进行连接查询,不适合多态查询。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值