当前位置: 代码迷 >> 综合 >> Java 第二阶段 (面向对象) 面试题整理
  详细解决方案

Java 第二阶段 (面向对象) 面试题整理

热度:16   发布时间:2024-03-08 12:55:44.0

第二阶段

2.1 简短说一下对JDBC 的理解

  • JDBC 全称是 Java database connection(java 数据库连接), 数据库管理系统(mysql oracle 等) ,每个数据库系统支持的命令是不一样的.

2.2 JDBC 访问数据库的基本步骤是什么?

  1. 加载驱动
  2. 通过DriverManager 对象获取连接对象Connection
  3. 通过连接对象获取会话
  4. 通过会话进行数据的增删改查, 封装对象
  5. 关闭资源

2.3 数据库连接池的原理, 为什么要使用连接池?

  1. 数据库连接是一件费时的操作, 连接池可以使多个操作共享一个连接.
  2. 数据库连接池的基本思想就是为数据库建立一个"缓冲池" . 预先在缓冲池中放入一定数量的连接, 但需要简历数据库连接的时候, 只需从"缓冲池"中取出一个, 使用完毕之后再放回去. 我们可以通过设定连接池的最大连接数来防止系统无尽的与数据库连接. 更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量, 使用情况, 为系统开发, 测试及性能调整提供依据.
  3. 使用连接池是为了提高对数据库连接资源的管理.

2.4 什么是事务?

  • 就是被绑定在一起作为一个逻辑工作单元的SQL 语句分组, 如果任何一个语句操作失败那么整个操作就被失败, 以后操作就会回滚到操作前的状态, 或者是有上个节点. 为了确保要么执行, 要么不执行, 就可以使用事务.

2.5 事物的四大特征是什么?

  • 数据库事务 transanction 正确执行的四个基本要素. ACID,原子性(Atomicity), 一致性(Correspondence), 隔离性(Isolation),持久性(Durability).
    1. 原子性: 整个事务中的所有操作, 要么全部完成, 要么全部不完成, 不可能停滞在中间某个环节. 事务在执行过程中发生错误, 就会被回滚(Rollback) 到事务开始前的状态, 就像整个事务从来没有被执行过一样.
    2. 一致性: 在事务开始之前和事务结束之后,数据库的完整性约束没有被破坏.
    3. 隔离性: 隔离状态执行事务, 使他们好像是系统在给定时间内执行的唯一操作. 如果有两个事务, 运行在相同的时间内, 执行相同的功能, 四五的隔离性将确保没一件事务在系统中认为只有该事务在使用系统. 这种属性有时成为串行化, 为了防止事务操作间的混淆, 必须串行化或序列化请求, 使得在同一时间仅有一个请求用于同一数据.
    4. 持久性: 在事务完成之后, 该事务所对数据库所做的更改半持久的保存在数据库之中, 并不会被回滚.

2.6 说说你对 Java 中反射机制的理解

  • Java 中的反射机制首先是能获取到 Java 中要反射类的字节码, 获取字节码有三种方法:
    1. Class.forName(className)
    2. 类名.class
    3. this.getClass()
  • 然后将字节码中的方法, 变量, 构造函数等映射成相应的 Method, Field, Constructor 等类, 这些类提供了丰富的方法可以被我们所使用.

2.7 在Mybatis 中,#{}和&{} 的区别是什么?

  1. #{} 是预编译处理, ${} 是字符串替换;
  2. Mybatis 在处理#{}时,会将sql 中的#{} 替换为 ? 号, 调用PreparedStatement 的 set 方法来赋值;
  3. Mybatis 在处理时就是把{} 时就是把{} 替换成变量的值.
  4. 使用#{} 可以有效的防止 SQL 注入, 提高系统安全性.

2.8 Mybatis 是否支持延迟加载? 如果支持, 他的实现原理是什么?

  • Mybatis 仅支持 association 关联对象和collection 关联集合就是一对多查询. 在Mybatis配置文件中, 可以配置是否使用延迟加载 lazyLoadingEnabled=true|false .
  • 它的原理是, 使用CGLIB 创建目标对象的代理对象, 当调用目标方法时, 进入拦截器方法, 比如调用a.getB().getName(), 拦截器 invoke() 方法发现a.getB() 是null值, 那么就会单独发送事先保存好的查询关联B对象的sql, 把B 查询上来,然后调用a.setB(b), 于是a 的对象b 的属性就有值了, 接着完成a.getB().getName()方法的调用. 这就是延迟加载的基本原理.

JSP 和 Servlet 是什么关系?

  • Servlet 是一个特殊的Java程序, 它运行于服务器的JVM中, 能够依靠服务器的支持向浏览器提供显示内容. JSP本质上是Servlet 的一种简易形式, JSP 会被服务器处理成一个类似于ServletJava 程序, 可以简化页面内容的生成. ServletJSP最主要的不同点在于, Servlet 的应用逻辑是在Java 文件中, 并且完全聪表示层中的HTML分离开来. 而JSP 的情况是Java 和 HTML可以组合成一个扩展名为**.jsp** 的文件.

什么情况下调用doGet() 和 doPost() ?

  • 默认情况下是调用doGet() , JSP页面中的Form表单的method属性设置为post 的时候,调用的为doPost()方法; 为get的时候, 调用doGet() 方法.

2.11 get 和 post 请求的区别

  1. GET 请求只能URL 编码,而 POST 支持多种编码方式.
  2. GET 请求只接受 ASCII 字符的参数,而POST则没有限制.
  3. GET 请求的参数通过URL 传递, 而 POST 放在Request Body
  4. GET 相对于 POST 更不安全,因为参数直接暴露在 URL
  5. GET 请求会被浏览器主动缓存,而 POST 不会(除非是自己手动设置的)
  6. GET 请求在 URL 传参有长度限制,而 POST 则没有限制
  7. GET 产生的 URL 地址可以被收藏, 而 POST 不可以
  8. GET 请求的参数会被完整的保留在浏览器的历史记录里面,而 POST 的参数不会
  9. GET 在浏览器回退时是无害的, 而 POST 会再次提交请求.

2.12 转发是服务器行为, 重定向是客户端行为

  • 从地址栏写显示来说 :
    forward 是服务器请求资源, 服务器直接访问目标地址的URL, 把那个URL的响应内容读取过来,然后把这些内容再发给浏览器, 浏览器根本不知道服务器的内容从哪里来的,所以它的地址栏还是原来的地址, redirect 是服务段根据逻辑, 发送一个状态码, 高速浏览器重新去请求去请求那个地址, 所以地址栏显示的是新来的URL.

  • 从数据共享来说 :

    1. forward : 转发页面和转发到页面可以共享request 里面的数据,
    2. redirect : 不能共享数据
  • 从运用地方来说 :

    forward : 一般用于用户登录的时候, 根据角色转发到相应的模块, redirect : 一般用于用户注销登录时返回主页面和跳转到其他的网站等…

  • 从效率来说 :
    forward: 效率高, redirect: 效率低

2.13 Cookie 和 session的区别

  1. session 在服务器端, cookie 在客户端(浏览器)
  2. session 默认被存储在服务器的一个文件中(不是内存)
  3. session 的运行依赖 session_id, 而session_id 是存在 cookie 中的, 也就是说, 如果浏览器禁用了 cookie , 同时 session 也会失效(但是可以通过其他方式实现, 比如在 url 中传递 session_id)
  4. session 可以放在 文件, 数据库或内存中都可以
  5. 用户验证这种场合一般会使用 session

2.14 JSP有哪些内置对象? 作用分别是什么?

JSP 一共有9个内置对象:
  • request : 负责得到客户端请求的信息, 对应类型: javax.servlet.http.HttpServletRequest
  • response : 负责向客户端发出响应, 对应类型: javax.servlet.http.HttpServletResponse
  • session : 负责保存同一客户端一次会话过程中的一些信息, 对应类型 : java.servlet.http.httpsession
  • out : 负责管理对客户端输出,对应类型 : javax.servlet.jsp.jspwriter
  • application : 表示整个应用环境的信息, 对应类型 : javax.servlet.servletcontext
  • config : 表示ServletConfig, 对应类型: javax.servlet.servletconfig
  • exception : 表示页面中发生的异常, 可以通过他获取页面异常信息, 对应类型 : java. lang. exception
  • pagecontext : 表示这个JSP页面上下文, 对应类型: javax.servlet.jsp.pagecontext
  • page : 表示这个JSP页面本身.

2.15 JSP 的四种范围

  1. page 是代表一个页面相关对象和属性. 一个页面有一个编译好的 java.servlet类(可以带有inculde指令, 但是不可以有include动作) 表示. 这既包括 servelt 又包括版已成servlet 的 jsp 页面.
  2. request 是代表与web 客户机发出的一个用户体验相关的对象和属性. 一个请求可能跨过多个页面, 涉及多个web 组件(由于forware 指令和include 动作的关系)
  3. session 是代表与用于某个 web 客户机的一个用户体验相关的对象和属性. 一个 web 会话也可以经常跨越多个客户机请求.
  4. application 是代表与整个web应用程序相关的对象和属性. 这实质上是跨越整个web 应用程序, 包括多个页面, 请求和会话的一个全局作用域.

2.16 如何避免JSP页面自动生成session对象? 为什么要这么做?

  • 在默认情况下,在对一个JSP页面发出请求的时, 如果session 还没有建立,那么JSP 页面会自动为请求创建一个session对象, 但是 session 是比较消耗资源的, 如果没有必要保持和使用session, 就不应该创建session, 例如一些只用来宣传产品的页面, 往往没有必要使用session来保存信息, 可以在JSP 中使用page指令进行设置, 避免JSP页面为每个请求都自动创建session. 实例代码:
<%@page session="false"%>

2.17 如何防止单表重复提交?

  • 使用 session 技术 :
    1. regist.jsp页面中生成一个随机值, 将其保存到 session 中,同时将其保存为表单的隐藏域的值.
    2. 在处理注册的请求时, 获取 session 中的随机值, 获取请求参数的值, 比较二者是否相同, 如果相同说明不是重复提交, 请求同时删除 session 中保存的值, 如果不相同则是重复提交, 不能通过.

2.18 sesion 和 application的区别?

  1. 两者的作用范围不同 :

    • session 是用户级别的,application 是 web 应用程序级别的, 是一个全局作用域.
    • 一个用户一个session, 每个用户的session不同, 用户所访问的网站多个页面共享一个 session.
    • 一个 web 应用程序一个 application 对象, 每个web 应用程序的 application 对象不同, 但是一个web 应用程序的多个用户之间共享一个application.
  2. 声明周期不同 :

    • session: 用户首次在网站中发出请求创建 session, 用户注销, 离开网站或者关闭浏览器消亡.
    • application: 启动 web 服务器创建, 关闭 服务器销毁.

2.19 过滤器有哪些作用?

  1. 可以验证客户是否来自可信的网络
  2. 可以对客户提交的数据进行重写编码
  3. 可以从系统里获得配置的信息
  4. 可以过滤掉系统中某些不应爱出现的词汇
  5. 验证客户是否登录
  6. 验证客户的浏览器是否支持当前的应用
  7. 可以纪录系统的日志

2.20 什么是web容器?

  • 给处于其中的应用程序组件 ( JSP, Servlet ) 提供一个环境, 是JSP, Servlet 直接跟容器中的变量交互, 不必关注其他系统问题, 主要有 web 服务器来实现. 例如: tomcat, weblogic, sphere,JBoss 等. 该容器提供的接口严格遵守 J2EE 规范中的 web application 标准. 我们把遵守以上标准的 web 服务器叫做 J2EE的web容器.

2.21 设计模式

2.21.1 全部设计模式

  • Java 中一般认为有 23 种设计模式, 我们不需要所有的都掌握, 但是其中常用的几种设计模式应该去掌握. 下面列出了所有的设计模式. 掌握的越多越好.
  • 总体来说设计模式分为三大类:
  1. 创建型模式, 共五种: 工厂方法模式, 抽象工厂模式, 单例模式, 建造者模式, 原型模式
  2. 结构型模式, 共七种: 适配器模式, 装饰器模式, 代理模式, 外观模式, 桥接模式, 组合模式,享元模式.
  3. 行为性模式, 共十一种: 策略模式, 模版方法模式, 观察者模式, 迭代子模式, 责任链模式, 命令模式, 备忘录模式, 状态模式, 访问者模式, 中介者模式, 解释器模式.

2.21.2 单例设计模式

  • 最好理解的一种设计模式,分为懒汉式和饿汉式

  • 饿汉式:

public class Singleton {
    //直接创建对象public static Singleton instance = new Singleton();//私有化构造器private Singleton(){
    }// 返回对象实例public static Singleton getInstance(){
    return instance;}
}
  • 懒汉式:
public class Singleton{
    //声明变量private static volatile Singleton singleton = null;//私有化构造函数private Singleton(){
    }//提供对外方法public static Singleton getInstance(){
    if(singleton == null){
    synchronized(Singleton.class){
    if(singleton == null){
    singleton == new Singleton();}}}return singleton;}
}

2.21.3 工厂设计模式

  • 工厂设计模式分为功能工厂方法模式和抽象工厂模式.

  • 工厂方法模式

    1. 工厂方法模式分为三种: 普通工厂模式,就是建立一个工厂类, 对实现了统一接口的一些类进行实例的创建.
    2. 多个工厂方法模式, 是对普通工厂模式的改进, 在普通工厂模式中, 如果传递的字符串出错,则不能正确的创建对象, 而多个工厂方法模式是提供多个工厂方法, 分别创建对象.
    3. 静态工厂方法模式, 将上面的多个工厂模式里的方法置为静态的, 不需要创建实例, 直接调用即可.
  • 普通工厂模式

public interface Sender{
    public void Send();
}public class MailSender implements Sender{
    @Overridepublic void Send(){
    System.out.print("this is mail sender!");}
}public class SmsSender implements Sender{
    @Overridepublic void Send(){
    System.out.println("this is sms sender!");}
}public class SendFactory{
    public Sender produce(String type){
    if("mail".equals(type)){
    return new MailSender();	}else if("sms".equals(type)){
    return new SmsSender();}else{
    System.out.println("请输入正确的类型!");return null;	}}
}
  • 多个工厂方法模式
    该模式是对普通工厂模式的改进, 在普通工厂方法模式中, 如果传递的字符串出错, 则不能创建对象, 而多个工厂方法模式是提供多个工厂方法, 分别创建对象.
public class SendFactory{
    public Sender produceMail(){
    return new MailSender();}public Sender produceSms(){
    return new SmsSender();}
}public class FactoryTest{
    public static void main(String[] args){
    SendFactory factory = new  SendFactory();Sender sender = new factory.produceMail();sender,send();}
}
  • 静态工厂方法模式
    将上面的多个工厂方法模式里面的方法置为静态的, 不需要创建实例, 直接调用即可.
public class SendFactory{
    public static Sender produceMail(){
    return new MailSender();	}public static Sender produceSms(){
    return new SmsSender();	}
}public class FactoryTest{
    public static void mian(String[] args){
    Sender sender = SendFactory.produceMail();sender.send();}
}
  • 抽象工厂模式

    工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决? 就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

public interface Provider {
    public Sender produce();
}
--------------------------------
public interface Sender {
    public void send();
}
--------------------------------
public class MailSender implements Sender {
    @Overridepublic void send() {
    System.out.println("this is mail sender!");}
}
----------------------------------
public class SmsSender implements Sender {
    @Overridepublic void send() {
    System.out.println("this is sms sender!");}
}
---------------------------------
public class SendSmsFactory implements Provider {
    @Overridepublic Sender produce() {
    return new SmsSender();}
}
---------------------------------
public class SendMailFactory implements Provider {
    @Overridepublic Sender produce(){
    return new MailSender();}
}
---------------------------------
public class Test {
    public static void main(String[] args) {
    Provider provider = new SendMailFactory();Sender sender = provider.produce();sender.send();}
}

2.22 MyBatis 映射文件中的 namespace 有什么用?

  • 在 mybatis 中,映射文件的namespace 是用于绑定 Mapper接口的, 也就是说 namespace 的值对应着一个接口类. 当你的namespace 绑定接口后, 你可以不用写接口实现类, mybatis 会通过该绑定自动帮你找到对应要执行的 SQL 语句.

2.23 Xml 映射文件中,除了常见 select|insert|update|delete标签之外, 还有哪些标签?

  • 还有很多其他的标签: < resultMap >、< sql >、< include >、加上动态 sql 的 9 个标签, trim|where|set|foreach|if|choose|when|otherwise|bind 等,其中为 sql 片段标签,通过标 签引入 sql 片段。

2.24 Mybatis动态sql 是做什么的? 都有哪些动态sql? 能简述一下动态sql的执行原理吗?

  • Mybatis 动态sql 可以让我们在Xml映射文件内, 以标签的形式编写动态 sql ,完成逻辑判断和动态拼接 sql 的功能,Mybatis提供了 9 种动态 sql 标签trim|where|set|foreach|if|choose|when|otherwise|bind。
  • 其执行原理为, 使用 OGNL 从sql参数对象中计算表达式的值, 根据表达式的值得动态拼接 sql , 以此来完成动态 sql 的功能.

2.25 mybatis 的Xml映射文件中,不同的 Xml映射文件, id 是否可以重复?

  • 不同的 Xml 映射文件, 如果配置了 namespace, 那么 id 可以重复: 如果没有配置 namespace,那么 id 不能重复; 毕竟 namespace 不是必须的,只是最佳实践而已.
  • 原因就是 namespace+id 是作为 Map<String, MappedStatement> 的 key 使用的, 如果没有 namespace,就剩下 id, 那么, id 重复会导致数据相互覆盖. 有个 namespace, 自然 id 就可以重复, namespace 不同,namespace+id 自然也就不同.

2.26 当实体类中的属性名和表名的字段名不一样, 怎么办?

  1. 通过在查询的 sql 语句中定义字段名和别名, 让字段名的别名和实体类的属性名一致
  2. 通过来映射字段名和实体类属性名的一一对应关系

2.27 讲下 Mybatis 的缓存

  • Mybatis 的缓存分为一级缓存和二级缓存, 一级缓存放在 session 里面, 默认就有, 二级缓存放在他的命名空间, 默认是打开的, 使用二级缓存属性类需要实现Serializable 序列化接口(可用来保存对象的状态),可在他的映射文件中配置< cache />.

2.28 Mybatis(IBatis)的好处是什么?

  • ibatissql 语句从 java 源程序中独立出来,放在单独的 xml 文件中编写, 给程序的维护带来了很大的遍历. ibatis 封装了底层 JDBC API 的调用细节, 并能自动将结果集转换成 Java Bean 对象, 大大简化了 Java 数据库编程的重复工作. 因为 Ibatis 需要程序员自己去编写 sql 语句, 程序员可以结合数据库自身的特点灵活控制 sql 语句,因此能够实现比 hiberbate 更全自动 orm 框架跟高的查询效率, 能完成复杂查询.

2.29Mybatis的编程步骤(重点)

  1. 创建 SqlSessionFactory
  2. 通过 SqlsessionFactory 创建 SqlSession
  3. **通过 sqlsession 执行数据库操作 **
  4. 调用 session.commit() 提交事务
  5. 调用 session.close() 关闭会话
  相关解决方案