面试笔记

一、java基础

1. java类初始化顺序

  • clinit 方法由静态类变量显示赋值代码和静态代码块组成
  • 类变量显示赋值代码和静态代码块代码从上到下执行
  • clinit 方法只调用一次

父类静态属性(成员变量)>父类静态代码块>子类静态属性>子类静态代码块

2. java实例初始化属性

  • init () 方法可能重载有多个,有几个构造器就有几个 init() 方法
  • init() 方法由非静态实例变量显示赋值代码和非静态代码块,对应构造器代码组成
  • 非静态实例变量显示赋值代码和非静态代码块从上到下顺序执行,而对应构造器的代码最后执行
  • 每次创建实例对象,调用对应构造器,执行的就是对应的 ini方法
  • init 方法的首行是super()和super(实参列表) ,即对应父类的 init 方法

父类非静态属性>父类非静态代码块>父类构造器>子类非静态属性>子类非静态代码块>子类构造器

整个步骤

父类静态属性(成员变量)>父类静态代码块>子类静态属性>子类静态代码块>父类非静态属性>父类非静态代码块>父类构造器>子类非静态属性>子类非静态代码块>子类构造器

3. 重载和重写

① 哪些方法不可以被重写

  • final方法
  • 静态方法
  • private等子类中不可见方法

②对象的多态性

  • 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码
  • 非静态方法默认的调用对象是this
  • this对象在构造器或者说方法中就是正在创建的对象

示例代码:
Father.java

package com.atguigu.classLoader;

/**
 * 父类初始化<clinit>
 * 1、j = method()
 * 2、 父类的静态代码块
 *
 * 父类实例化方法:
 * 1、super()(最前)
 * 2、i = test() (9)
 * 3、子类的非静态代码块 (3)
 * 4、子类的无参构造(最后)(2)
 *
 *
 * 非静态方法前面其实有一个默认的对象this
 * this在构造器或<init> 他表示的是正在创建的对象,因为咱们这里是正在创建Son对象,所以
 * test()执行的就是子类重写的代码(面向对象多态)
 *
 * 这里i=test() 执行的就是子类重写的test()方法
 * @author gcq
 * @Create 2020-09-25
 */
public class Father {
    private int i = test();
    private static int j = method();

    static{
        System.out.println("(1)");
    }
    Father() {
        System.out.println("(2)");
    }
    {
        System.out.println("(3)");
    }
    public int test(){
        System.out.println("(4)");
        return 1;
    }
    public static int method() {
        System.out.println("(5)");
        return 1;
    }
}

Son.java

package com.atguigu.classLoader;

/**
 * 子类的初始化<clinit>
 * 1、j = method()
 * 2、子类的静态代码块
 *
 * 先初始化父类 (5)(1)
 * 初始化子类 (10) (6)
 *
 * 子类实例化方法:
 * 1、super()(最前
 * 2、i = test() (9)
 * 3、子类的非静态代码块 (8)
 * 4、子类的无参构造(最后)(7)
 * @author gcq
 * @Create 2020-09-25
 */
public class Son extends Father {
    private int i = test();
    private static int j = method();
    static {
        System.out.println("(6)");
    }
    Son() {
        super();
        System.out.println("(7)");
    }
    {
        System.out.println("(8)");
    }
    public int test(){
        System.out.println("(9)");
        return 1;
    }
    public static int method() {
        System.out.println("(10)");
        return 1;
    }

    public static void main(String[] args) {
        Son son = new Son();
        System.out.println();
        Son son1 = new Son();
    }
}

执行结果

(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)

(9)(3)(2)(9)(8)(7)

4. 方法参数传递机制

package com.atguigu.methodParam;

import java.util.Arrays;

/**
 * @author gcq
 * @Create 2020-09-28
 */
public class Exam4 {
    public static void main(String[] args) {
        int i = 1;
        String str = "hello";
        Integer num = 200;
        int[] arr = {1,2,3,4,5};
        MyData my = new MyData();
		//arr和my变了
        change(i,str,num,arr,my);

        System.out.println("i= " + i);
        System.out.println("str= " + str);
        System.out.println("num= " + num);
        System.out.println("arr= " + Arrays.toString(arr));
        System.out.println("my.a= " + my.a);

    }
    public static void change(int j, String s, Integer n, int[] a, MyData m) {
        j += 1;
        s += "world";
        n += 1;
        a[0] += 1;
        m.a += 1;
    }
}
class MyData {
    int a = 10;

}

结果

i= 1
str= hello
num= 200
arr= [2, 2, 3, 4, 5]
my.a= 11

考点?
方法的参数传递机制

String、包装类等对象的不可变性
在这里插入图片描述

方法的参数传递机制
1、形参是基本数据类型

  • 传递数据值
    2、实参是引用数据类型​
  • 传递地址值

特殊的类型:String、包装类等对象的不可变性

5. 成员变量与局部变量

在这里插入图片描述
​ 局部变量:栈

​ 实例变量:堆

​ 类变量:方法区
在这里插入图片描述
堆(Heap) ,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。

通常所说的栈(Stack) ,是指虚拟机栈。虚拟机栈用于存储局部变量表等。局部变量
表存放了编译期可知长度的各种基本数据类型(boolean、byte、 char、short、 int、 float、long、double) 、对象引用(reference 类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完, 自动释放。
方法区(Method Area)用于存储已被虛拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

二、SSM面试题

1. spring

1. 事物的传播行为

事务的传播行为
当事务方法被另一个事务方法调用时,必须指定事务应该如何传播,列如方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行,事务传播的行为有传播属性指定,Spring定义了7中类传播行为

传播属性描述
REQUIRED如果有事务在运行,当前的方法就在这个事务内运行,否则就启动一个新的事务,并在自己的事务内运行
REQUIRED_NEW当前方法必须启动事务,并在它自己的事务内运行,如果有事务正在运行,应该将他挂起
SUPPORTS如果有事务在运行,REQUIRED_NEW当前的方法就在这个事务内运行,否则他可以不运行在事务中
NOT_SUPPORTS当前的方法不应该运行在事务中,如果有运行的事务,将他挂起
MANDATORY当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常
NEVER当前方法不应该运行在事务中,如果有运行的事务,就抛出异常
NESTED如果有事务在运行,当前的方法就应该在这个事物的嵌套事务内运行,否则,就启动一个新的事务,并在它自己的事务内运行

事务传播属性可以在@Transactional注解的propagation属性中定义

2. 事物的隔离级别

2.1 数据库事务并发问题

假设现在有两个事务:Transaction01和Transaction02并发执行。

1) 脏读

①Transaction01将某条记录的AGE值从20修改为30。

②Transaction02读取了Transaction01更新后的值:30。

③Transaction01回滚,AGE值恢复到了20。

④Transaction02读取到的30就是一个无效的值。

2) 不可重复读

①Transaction01读取了AGE值为20。

②Transaction02将AGE值修改为30。

③Transaction01再次读取AGE值为30,和第一次读取不一致。

3) 幻读

①Transaction01读取了STUDENT表中的一部分数据。

②Transaction02向STUDENT表中插入了新的行。

③Transaction01读取了STUDENT表时,多出了一些行。

2.2 隔离级别

数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。

  1. 读未提交:READ UNCOMMITTED

允许Transaction01读取Transaction02未提交的修改。

  1. 读已提交:READ COMMITTED

要求Transaction01只能读取Transaction02已提交的修改。

  1. 可重复读:REPEATABLE READ

确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。

  1. 串行化:SERIALIZABLE

确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。

  1. 各个隔离级别解决并发问题的能力见下表

在这里插入图片描述

SpringMvc

整体流程

SpringMVC框架是一个基于请求驱动的Web框架,并且使用了‘前端控制器’模型来进行设计,再根据‘请求映射规则’分发给相应的页面控制器进行处理。在这里插入图片描述
具体步骤:

1、 首先用户发送请求到前端控制器,前端控制器根据请求信息(如 URL)来决定选择哪一个页面控制器进行处理并把请求委托给它,即以前的控制器的控制逻辑部分;图中的 1、2 步骤;

2、 页面控制器接收到请求后,进行功能处理,首先需要收集和绑定请求参数到一个对象,这个对象在 Spring Web MVC 中叫命令对象,并进行验证,然后将命令对象委托给业务对象进行处理;处理完毕后返回一个 ModelAndView(模型数据和逻辑视图名);图中的 3、4、5 步骤;

3、 前端控制器收回控制权,然后根据返回的逻辑视图名,选择相应的视图进行渲染,并把模型数据传入以便视图渲染;图中的步骤 6、7;

4、 前端控制器再次收回控制权,将响应返回给用户,图中的步骤 8;至此整个结束。
在这里插入图片描述
具体步骤:

第一步:发起请求到前端控制器(DispatcherServlet)

第二步:前端控制器请求HandlerMapping查找 Handler (可以根据xml配置、注解进行查找)

第三步:处理器映射器HandlerMapping向前端控制器返回Handler,HandlerMapping会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象,多个HandlerInterceptor拦截器对象),通过这种策略模式,很容易添加新的映射策略

第四步:前端控制器调用处理器适配器去执行Handler

第五步:处理器适配器HandlerAdapter将会根据适配的结果去执行Handler

第六步:Handler执行完成给适配器返回ModelAndView

第七步:处理器适配器向前端控制器返回ModelAndView (ModelAndView是springmvc框架的一个底层对象,包括 Model和view)

第八步:前端控制器请求视图解析器去进行视图解析 (根据逻辑视图名解析成真正的视图(jsp)),通过这种策略很容易更换其他视图技术,只需要更改视图解析器即可

第九步:视图解析器向前端控制器返回View

第十步:前端控制器进行视图渲染 (视图渲染将模型数据(在ModelAndView对象中)填充到request域)

第十一步:前端控制器向用户响应结果

总结核心开发步骤
1、 DispatcherServlet 在 web.xml 中的部署描述,从而拦截请求到 Spring Web MVC

2、 HandlerMapping 的配置,从而将请求映射到处理器

3、 HandlerAdapter 的配置,从而支持多种类型的处理器

注:处理器映射求和适配器使用纾解的话包含在了注解驱动中,不需要在单独配置

4、 ViewResolver 的配置,从而将逻辑视图名解析为具体视图技术

5、 处理器(页面控制器)的配置,从而进行功能处理

View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)
在这里插入图片描述

Mybatis

实体类中的属性名和表中的字段不一样,怎么办
解决方案:

1、写 SQL 语句的时候 写别名

2、在MyBatis的全局配置文件中开启驼峰命名规则

<!-- 开启驼峰命名规则,可以将数据库中下划线映射为驼峰命名
	列如 last_name 可以映射为 lastName
-->
<setting name="mapUnderscoreToCameLCase" value="true" />
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值