2020年3月java面试汇总

文章目录

一. Java

1. 基本数据类型

byte,short,int,long,float,double,char,boolean

2. jdk,jre,jvm之间的关系

jdk是java开发工具包,如果开发java程序必须先安装jdk,包括jre和开发工具
jre是java运行环境,包括jvm
jvm是java虚拟机,不能单独安装

3. 面向对象三大特性

封装、继承、多态

4. 面向对象开发的六大原则

  • 单一职责原则:一个类永远只有一个职责。如果一个类有多个职责,这些职责就耦合在了一起。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起会影响复用性。
  • 开闭原则:当一个系统或软件完成开发时,如果需要添加业务逻辑,我们选择对添加业务逻辑开发,对原代码修改关闭
  • 里氏替换原则:继承必须确保超类的性质在子类中仍然成立。
    里氏替换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏替换原则是对实现抽象化的具体步骤的规范。
  • 迪米特法则(最少知道原则):一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。简单的理解就是高内聚,低耦合,一个类尽量减少对其他对象的依赖。
  • 接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。接口最小化,过于臃肿的接口依据功能,可以将其拆分为多个接口
  • 依赖置换原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。简单的说就是尽量面向接口编程.

5. 什么是面向对象?什么是面向过程?什么时候分别使用它们?

  • 面向对象:看名字它是注重对象的。当解决一个问题的时候,面向对象会把事物抽象成对象的概念,就是说这个问题里面有哪些对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法,问题得到解决。
    这里强调的是问题里的对象,在对象的角度解决问题。

  • 面向过程:看名字它是注重过程的。当解决一个问题的时候,面向过程会把事情拆分成: 一个个函数和数据(用于方法的参数) 。然后按照一定的顺序,执行完这些方法(每个方法看作一个个过程),等方法执行完了,事情就搞定了。
    这里强调的是问题的步骤,按照什么执行步骤解决问题,和对象无关

6. 说一下继承与实现?接口的常量与方法是什么修饰的?

继承就是子类继承父类,子类拥有父类非私有化的性质,包括变量、方法、代码块等。
实现就是对类功能的扩展,是类实现一系列的功能,也可以说是这个类实现某个(某几个)接口,遵守某个(某些)规范。
接口的常量修饰符是:public static final 常量类型 常量名
接口的方法修饰符是:public abstract 返回值类型 方法名

7. String为什么是不可变的?底层使用什么实现的?

String底层是通过char数组实现的,char数组和String这个类都是通过final修饰的,所以不可变。

8. Int和Integer的区别,在使用时有什么区别?数据库中的数据是int,什么情况下int和Integer接收值是不一样的?

区别:

  1. int 是基本数据类型,Integer是引用数据类型,是int的包装类
  2. int 的默认值是0,Integer 的默认值是null
  3. Integer变量必须实例化后才能使用,而int变量不需要
  4. Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值

关于接收值不一样,可以从默认值解释

9. == 与equals的区别?

==表示的是两个数值是否相等,当引用数据类型的引用变量存的是地址值,使用 ==进行比较比较的是地址值是否相等,比较引用对象的值是否相等要使用equals 进行比较
补充:因为equals方法是属于Object类的,其方法内部是使用的==实现的,类对象进行比较时要确保这个类重写了equals方法,否则还是使用了==进行比较

10. 重写与重载的区别?

重写是发生在继承上,子类重写父类的方法,当子类需要对父类的方法进行扩展时,进行重写这个方法。重写要求与父类方法的返回值类型,方法名,参数列表完全一致。子类不能重写父类final方法,必须重写abstract方法
重载:在一个类中,方法名相同,参数列表不同(参数列表包括参数个数,参数类型)

11. 两个String类型比较用 == 还是equals

equals,String是引用数据类型,比较值使用equals

12. 截取字符串的方法?怎么用的?

使用substring方法,第一个参数表示开始截取的索引位置,第二个参数表示截止的位置,字符串索引从0开始,遵守左闭右开的原则。第二个参数不写表示从起始位置截取到字符串最后。
也可以使用split方法,参数表示使用正则表达式,根据正则表达式截取的字符串会返回一个字符数组。
substring(int beginIndex,int endIndex);
substring(int beginIndex);
split(String regex);

13. 格式化日期用的是什么?

SimpleDateFormate
这个类对象的format方法是格式化日期,parse方法是字符串转换为日期
示例:

//日期转换为指定格式的字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String text = sdf.format(date);
//把字符串转换为日期
text = "2068年5月12日 8:28:58";
SimpleDateFormat anotherSdf = new SimpleDateFormat("yyyy年M月dd日 H:mm:ss");
date2 = anotherSdf.parse(text);

二. 集合

1. Java的Collection集合,你都用过哪些?

ArrayList,LinkList,HashSet

2. List,set,map区别

List

存储特点:有序,可重复。存储顺序与添加顺序一致,可以存储重复的数据

  1. ArrayList
  • 底层数据结构是数组,访问快,添加,删除慢
  • 初始化容量:10
  • 扩容:1.5倍
  1. Vector
  • 底层数据结构是数组,它是线程安全的,ArrayList不是线程安全的
  • 初始化容量:10
  • 扩容:2倍
  1. LinkedList
  • 底层是双向链表,访问慢,添加和删除效率高

Set集合

存储特点:无序,不可重复。存储顺序与添加顺序可能不一样;不能存储重复(通过equals()方法来判断)的数据

  1. HashSet
  • 底层是HashMap
    向HashSet添加元素就是把元素作为键添加到底层的HashMap中
  1. TreeSet
    TreeSet实现了SortedSet接口,可以根据元素自然排序,要求集合中的元素必须是可比较的(Comparator与Comparable)
    TreeSet底层是TreeMap
    向TreeSet添加元素就是把元素作为键添加到底层的TreeMap中

Map

Map是按<键,值>对的形式存储数据,Map的key不允许重复

  1. HashMap
    底层是数组+链表,键与值都可以为null,线程不安全
    JDK8中,当链表长度超过 8 时,链表转换为红黑树;插入时,新增的结点插入到链表的尾部
    初始化容量为16
    加载因子:0.75,当键值对的数量 > 容量*加载因子时,按2倍大小扩容
    在创建时可以指定初始化容量,HashMap会把初始化容量自动调整为2的幂次方
  2. CurrentHashMap
    底层采用数组+链表+红黑树,利用CAS+Synchronized来保证线程安全

HashMap和CurrentHashMap整理

3. ArrayList和LinkList的区别

  1. ArrayList
  • 底层数据结构是数组,访问快,添加,删除慢
  • 初始化容量:10
  • 扩容:1.5倍
  1. LinkedList
  • 底层是双向链表,访问慢,添加和删除效率高

4.ArrayList底层用数组实现的,容量10,一直add,当容量满了,又add,这时会发生什么?什么情况下扩容?如何扩容?

容量满时,再add会进行扩容。当容量满时进行扩容。底层是数组,先将原数组复制到一个内存空间更大的数组中,在将新添加的元素添加到新数组中,这个内存空间更大的数组,它的大小是原数组的1.5倍。它的底层扩容方法是grow方法,最关键的一句是 int newCapacity = oldCapacity + (oldCapacity >> 1);,其中oldCapacity >> 1表示原来长度的一半,这个等式就是新数组长度是原数组长度的1.5 倍。

5. 说一下你了解的HashMap

  • HashMap底层是哈希表,哈希表就是数组,数组元素是链表,它结合了数组和链表的优点。
  • 添加键值对时,先根据键的哈希码,通过哈希函数计算哈希值,通过哈希值计算数组下标。找到数组下标位置,如果这个位置元素为null,那么就创建节点保存到元素中;如果不为null,则遍历这个节点,如果有某个节点的key与当前键equals相等,则用新值覆盖旧值,如果节点中的key都不匹配,则创建一个新的节点插入到链表尾部。
  • HashMap初始化容量是16,在创建时也可以自动指定初始化容量,HashMap会自动将初始化容量自动调整为2的幂次方,为了方便计算数组下标
  • 当链表节点数量超过8个是,会转化成红黑树结构
  • HashMap的加载因子是0.75,当键值对的数量 > 容量 * 加载因子 时,扩容,按照2倍大小扩容

6. Hashmap遍历怎么遍历?平时什么情况下使用HashMap?

  1. 可以通过keySet、entrySet进行遍历。
  2. 访问服务使用的参数时,可以通过传递键值对的方式。实体类中有类对象,传参使用。
  3. 读取系统参数也可以使用

7. HashMap的扩容机制?链表和红黑树是怎么转换的?

HashMap的加载因子是0.75,当键值对的数量 > 容量 * 加载因子 时,扩容,按照2倍大小扩容
当链表容量大于8时,自动转换成红黑树

8. 简单说一下哈希碰撞?HashMap怎么解决的?

哈希碰撞就是两个值同时存放到哈希表的同一个位置,这时产生冲突,这就是哈希碰撞。
通过使用链址法。
哈希表本身是一个数组,将数组元素采用链表。当两个元素存放到哈希表的同一位置时,先遍历链表中的节点,如果有节点的key与当前键equals相等,就用新的值覆盖旧的值;如果没有相等的节点,则新创建一个节点插入到链表的尾部。

9. 解决哈希碰撞的方法有哪些?

链址法,开放定址法,再散列法

10. HashMap是线程安全的吗?你知道的线程安全的类有哪些?说一下CurrentHashMap。

不是。HashTable,Properties(继承自HashTable),CurrentHashMap。

11.递归了解吗?

方法自己调自己。在方法内部添加判断条件,满足则停止,不满足继续调用自己。

三. 线程

1. volatile底层是怎么实现的?与synchronized有什么区别?

首先被volatile修饰的变量有两个特性:

  1. 可见性
  2. 禁止指令重排序

可见性就是在多线程环境中,共享变量的操作对每个线程都是内存可见的,每个线程都可以获取到volatile修饰变量的最新值,每个线程修改volatile修饰的变量会被直接刷新到主存中。

禁止指令重排序:

  1. java指令会有两次优化,编译器优化,执行器优化,每次优化就是对指令的一次重排序。
  2. java指令重排序要求不影响单线程执行结果的前提下,优化执行性能,但在多线程下会造成指令执行顺序的不可控,影响多线程的执行结果
  3. volatile底层是通过lock前缀、内存屏障来实现的。使用volatile与不使用volatile在字节码层面没有什么不同,在汇编层面使用volatile的变量会有lock前缀,这个前缀保证了原子操作,这个操作一旦开始,一直运行到结束。lock前缀相当于内存屏障,内存屏障就是CPU指令,规定了指令执行顺序,先与它的先执行,后与它的后执行,从而实现禁止指令重排序。

volatile底层实现详解

2. 多线程平时用到了吗?用在哪些方面?

在P2P项目中,比如在用户投资到期后需要给用户回款,此处我们使用了多线程,加快整个回款的速度,我们先从数据库获取所有待回款的数据,然后创建一个线程池,每个回款是一个线程,将这些回款线程提交到线程池中执行,从而充分利用服务器的CPU资源快速为用户回款;

3. 线程池参数知道干啥得吗?

(前三个要记住)
corePoolSize:核心线程数
queueCapacity:任务队列容量
maxPoolSize:最大线程数
keepAliveTime:线程空闲时间
allowCoreThreadTimeout:允许核心线程超时
rejectedExecutionHandler:任务拒绝处理器

线程池按以下行为执行任务:

  1. 当线程数小于核心线程数,创建线程
  2. 当线程数大于等于核心线程数,且任务队列未满,将任务放入任务队列
  3. 当线程数大于等于核心线程数,且任务队列已满
    1. 若线程数小于最大线程数,创建线程
    2. 若线程数等于最大线程数,抛出异常,拒绝任务

4. 创建线程有哪些方法?

四种
继承thread类,重写run方法;
实现runable接口,重写run方法;
callable接口,重写call方法;
使用线程池(有返回值)

5. Runnable和callable接口有什么不同,区别?

(1)Runnable接口无返回值,callable有返回值
(2)Runnable不能抛出异常,callable可以抛出异常
(3)Runnable重写run方法,callable重写call方法

6. 核心线程是5,队列满的话,什么时候会用到其他线程?就是什么时候会用到最大线程?

  1. 当线程数小于核心线程数,创建线程
  2. 当线程数大于等于核心线程数,且任务队列未满,将任务放入任务队列
  3. 当线程数大于等于核心线程数,且任务队列已满
    1. 若线程数小于最大线程数,创建线程
    2. 若线程数等于最大线程数,抛出异常,拒绝任务

7. 怎么理解线程安全的?

就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

8. 阻塞队列有几种?拒绝策略知道吗?有四种是哪四种?

3种阻塞对列:

  1. 基于数组的先进先出队列,有界;
  2. 基于链表的先进先出队列,无界;
  3. 无缓冲的等待队列,无界
BlockingQueue<Runnable> workQueue = null;
workQueue = new ArrayBlockingQueue<>(5);//基于数组的先进先出队列,有界
workQueue = new LinkedBlockingQueue<>();//基于链表的先进先出队列,无界
workQueue = new SynchronousQueue<>();//无缓冲的等待队列,无界

4种拒绝策略

  1. 默认,队列满了丢任务抛出异常
  2. 队列满了丢任务不异常
  3. 将最早进入队列的任务删,之后再尝试加入队列
  4. 如果添加到线程池失败,那么主线程会自己去执行该任务
RejectedExecutionHandler rejected = null;
rejected = new ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常
rejected = new ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常
rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列
rejected = new ThreadPoolExecutor.CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行该任务

5种线程池

ExecutorService threadPool = null;
threadPool = Executors.newCachedThreadPool();//有缓冲的线程池,线程数 JVM 控制
threadPool = Executors.newFixedThreadPool(3);//固定大小的线程池
threadPool = Executors.newScheduledThreadPool(2);//一个能实现定时、周期性任务的线程池
threadPool = Executors.newSingleThreadExecutor();//单线程的线程池,只有一个线程在工作
threadPool = new ThreadPoolExecutor();//默认线程池,可控制参数比较多   

9. 高内聚低耦合,你是怎么理解的?“耦合”你怎么理解的?

高内聚就是说相关度比较高的部分尽可能的集中,不要分散
低耦合就是说两个相关的模块尽可以能把依赖的部分降低到最小,不要让两个系统产生强依赖

耦合是两个事物(对象之间,模块之间)之间的相互作用、相互影响的程度,也是两者之间的依赖关系。
耦合强度,依赖于以下几个因素:
1、一个模块对另一个模块的调用;
2、一个模块向另一个模块传递的数据量;
3、一个模块施加到另一个模块的控制的多少;
4、模块之间接口的复杂程度。

四. MySQL

1. Mysql优化

  1. 优化查询指令,避免全表扫描,可以注意以下几点:
    • 在where和Orderby设计的列上面建立索引
    • 尽量避免在where子句对null进行判断
    • 避免在where子句使用不等于(!= 或者 <>),否则引擎会放弃使用索引进行全表扫描
    • 任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段
    • 复合索必须指定索引中第一个字段作为检索条件,否则不使用索引
    • n 和 not in 也要慎用,否则会导致全表扫描。对于连续的数值,能用 between 就不要用 in 了。
    • 模糊查询时,以"%"开头,会导致全表扫描
  2. 数据库集群部署,降低服务器压力

2. Mysql事务的隔离级别有哪些,脏读发生在哪种隔离级别下?什么是脏读?什么是幻读?

隔离级别四种:读未提交,读已提交,可重复读,串行化

事务隔离级别说明脏读读已提交(不可重复读)幻读
读未提交(read-uncommitted)读取数据的事务对象,可以读取到另一个事务对象尚未提交的数据
读已提交(read-committed)读取数据的事务对象,只能读取另一个事务对象提交过后的数据
可重复读(repeatable-read)(默认)读取数据的事务对象,在另一个事务对象提交前后读取的内容要保持一致
串行化(serializable)串行读取

脏读:事务A读取事务B更新的数据但未提交的数据,事务B回滚,事务A读取的是脏数据
幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
不可重复读:事务A多次重复读取一条数据,事务B在事务A读取过程中对数据进行更新提交,导致事务A多次读取的同一数据时,结果不一样,

总结:不可重复读和幻读容易混淆,不可重复读侧重修改,幻读侧重新增和删除;解决不可重复读只需要锁住满足条件的行,解决幻读需要锁住表。

3. Mysql的执行计划(explane)

通过执行计划查看查询语句是否使用了索引
explane sql语句

4. MySQL的存储引擎,有什么区别?

  • MyIsam:
  1. 使用三个文件表示每个表:
    - 格式文件 — 存储表的结构(mytable.frm)
    - 数据文件 — 存储表的数据(mytable.MYD)
    - 索引文件 — 存储表的索引(mytable.MYI)
    - 对表文件中数据行查询提速,有很大帮助。
  2. 灵活的AUTO_INCREMENT字段处理
  3. 可被转换为压缩、只读表来节省空间
  4. 但是MyIsam不支持事务,因此在进行数据行添加,修改,删除时,无法保证数据安全性
  • INNODB:MySQL数据库的默认引擎;
  1. 每个InnoDB表在数据库目录中以.frm格式文件表示
  2. InnoDB表空间tablespace被用于存储表的内容
  3. 提供一组用来记录事务性活动的日志文件
  4. 支持事务处理
  5. 提供全ACID兼容
  6. 在MySQL服务器崩溃后提供自动恢复
  7. 多版本(MVCC)和行级锁定
  8. 支持外键及引用的完整性,包括级联更新和删除
  • MEMORY:其数据存储在内存中,且行的长度固定,这两个特点使得MEMORY存储引擎非常快;
  1. 在数据库目录内,每个表均以.frm格式文件表示;
  2. 表数据及索引被存储在内存中;
  3. 表级锁机制;
  4. 不能包含TEXT或BLOB字段

5. Innodb有哪些特性?

  • 插入缓冲
  • 二次写
  • 自适应哈希
  • 预读

innodb引擎的4大特性

6. Innodb的事务锁有哪些?

行级锁:

  • 共享锁:允许事务读取一行数据
  • 排它锁:允许事务更新删除一行数据

表级锁:

  • 意向共享锁:允许事务获取一张表的几行共享锁
  • 意向排它锁:允许事务获取一张表的几行排它锁

由于Innodb引擎支持的均为行锁,所以意向锁其实不会阻塞除全表扫描之外的任何请求

7. 你了解存储过程和function吗?

  • 存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合,减少数据在数据库和应用服务之间的传输,对于提高数据处理的效率是有好处的。

  • 存储过程和函数允许包含DDL语句,也允许使用事务,还可以调用其他的存储过程和函数,但不允许执行 Load Data Infile 语句

  • 存储过程和函数的区别在于 函数必须有返回值,而存储过程没有,存储过程的参数可以使用IN、OUT、INOUT类型,而函数的参数只能是IN类型的。如果有函数从其他类型的数据库迁移到MySQL,可能需要将函数改造成存储过程。

8. 使用什么工具创建表?

使用Power Designer来创建表

9. 表结构是怎么设计的?是你设计的吗?

  1. 首先,表结构的设计尽量要满足数据库三范式
  2. 但是还是根据实际需求进行取舍,有时可能会拿冗余换速度,最终用目的要满足客户需求。
第一范式:要求有主键,数据库中不会出现重复记录,每个字段是原子性不可再分
第二范式:在第一范式的基础上,非主键字段完全依赖主键字段,没有部分依赖
第三范式:在第二范式的基础上,非主键字段不产生传递依赖

10. 数据库集群是怎么同步的?

在这里插入图片描述

  1. 当 master 主服务器上的数据发生改变时,则将其改变写入二进制事件日志文件中
  2. salve 从服务器会在一定时间间隔内对 master 主服务器上的二进制日志进行探测,探测其是否发生过改变,如果探测到 master 主服务器的二进制事件日志发生了改变,则开始一个 I/O Thread 请求 master 二进制事件日志
  3. 同时 master 主服务器为每个 I/O Thread 启动一个dump Thread,用于向其发送二进制事件日志
  4. slave 从服务器将接收到的二进制事件日志保存至自己本地的中继日志文件中
  5. salve 从服务器将启动 SQL Thread 从中继日志中读取二进制日志,在本地重放,使得其数据和主服务器保持一致
  6. 最后 I/O Thread 和 SQL Thread 将进入睡眠状态,等待下一次被唤醒

五. Spring

1. Spring说下你知道的。(IOC,AOP介绍)

IoC 就是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到 Spring 容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI 依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖 IoC 容器来动态注入对象需要的外部资源。

AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为 “切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理。AOP 实现的关键在于 代理模式

2. AOP中涉及的名词?

  1. 切面(Aspect):被抽取的公共模块(类),可能会横切多个对象。例如银行系统,先检测是否安全,再执行核心(业务)层,再记录日志,再清空缓存记录,除了核心层都是切面
  2. 连接点(Join point):指方法(可以被切面织入的具体方法),通常业务接口中的方法均为连接点。例如上面的银行系统中,核心类(目标业务方法)就是连接点
  3. 通知(Advice):Advice也叫增强。切面为类,而切面里的方法叫通知。有前置通知,后置通知,环绕通知等等。
  4. 切入点(Pointcut):切入点就是一个或多个连接点的集合。通过切入点表达式,来获取满足条件的连接点的集合。
  5. 目标对象(Target Object): 目标对象指被增强了的对象(包含主业务逻辑的类的对象),即被一个或者多个切面所通知的对象。这个对象永远是一个被代理(proxied) 对象。
  6. 织入(Weaving):指把增强应用到目标对象来创建新的代理对象的过程(将通知与连接点连接起来的过程)。

3. Spring…IOC的实现方式

spring框架使用的di这种技术,实现ioc的功能。 spring底层创建对象,赋值属性使用的是jdk中的反射机制

4. Ioc和Aop有什么作用?

  • IoC 这个指的就是我们获取对象的方式进行反转了。不使用IoC时,对象是需要手动new出来的,是我们主动获取的。使用IoC之后,是将这个获取的过程交给spring来管理,我们只需要告诉spring你需要什么就行了,它就会把东西给你。
  • Aop 就是用来增强功能,在执行主业务的时可以顺带执行其他业务。

Sring 的AOP和IoC都是为了解决系统代码耦合度过高的问题。使代码重用度高、易于维护。

5. AspectJ的aop和Spring的Aop有什么区别?

  1. Spring AOP采用的是动态织入(运行时织入),而Aspectj是静态织入(编译时期就织入),通过修改代码来实现。
  2. AspectJ由于是在编译时期就织入,故性能更优。
  3. Spring AOP的通知是基于该对象是SpringBean对象才可以,而AspectJ可以在任何Java对象上应用通知。
  4. Spring AOP仅支持方法切入点,而AspectJ支持所有切入点

6. 什么是正向代理?什么是反向代理?

  • 正向代理类似一个跳板机,代理访问外部资源。比如:我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器,它能访问那个我不能访问的网站,于是我先连上代理服务器,告诉它我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。

  • 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器;

综上所述:正向代理代理对象是客户端,反向代理代理对象是服务端。

7. 什么是动态代理?什么是静态代理?

动态代理与静态代理

六. SpringMVC

1.SpringMVC,一个请求,到数据完全响应,springMVC都经历了什么?SpringMVC执行流程?

在这里插入图片描述

  1. 浏览器提交请求到中央调度器
  2. 中央调度器直接将请求转给处理器映射器。
  3. 处理器映射器会根据请求,找到处理该请求的处理器,并将其封装为处理器执行链后返回给中央调度器。
  4. 中央调度器根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器。
  5. 处理器适配器调用执行处理器。
  6. 处理器将处理结果及要跳转的视图封装到一个对象 ModelAndView 中,并将其返回给处理器适配器。
  7. 处理器适配器直接将结果返回给中央调度器。
  8. 中央调度器调用视图解析器,将 ModelAndView中的视图名称封装为视图对象。
  9. 视图解析器将封装了的视图对象返回给中央调度器
  10. 中央调度器调用视图对象,让其自己进行渲染,即进行数据填充,成响应对象。
  11. 中央调度器响应浏览器。

2.SpringMVC最核心的类?

DispatchServlet

3.@ResponseBody与@RequestBody有什么用?

  • @ResponseBody:作用在方法上,表示该方法的返回结果直接写入响应体中,如果不使用@ResponseBody,则返回值会解析为跳转路径。
  • @RequestBody:作用在形参列表上,用于将前台发送过来固定格式的数据【xml 格式或者 json等】封装为对应的 JavaBean 对象,封装时使用到的一个对象是系统默认配置的 HttpMessageConverter进行解析,然后封装到形参上。

4.RequestParam和PathVariable是怎么用的?

  • @RequestParam:将请求参数绑定到控制器的方法参数上,同时可以给参数一些限定,比如说指定参数的默认值,是否允许参数为空等等。
  • @PathVariable:是将Rest风格的请求中{}中的值取出来

七. Mybatis

1.#{}和${}都用过吗?有什么区别?PreperStatement和Statement。

  • #:占位符,告诉 mybatis 使用实际的参数值代替。并使用 PreparedStatement 对象执行 sql 语句, #{…}代替sql 语句的“?”。 可以避免SQL注入,这样做更安全,更迅速,通常也是首选做法。

  • $:字符串替换, 告诉 mybatis 使用 包 含 的 “ 字 符 串 ” 替 换 所 在 位 置 。 使 用 S t a t e m e n t 把 s q l 语 句 和 包含的“字符串”替换所在位置。使用 Statement 把 sql 语句和 使Statementsql{…}的内容连接起来(相当于是String字符串中的+号),有SQL注入的风险。主要用在替换表名,列名,不同列排序等操作。

2.什么时候使用${}?

下拉框查询,用户不可更改的数据时可以使用,像下拉框选择

3.模糊查询怎么使用?

<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
    select * from student where name like "%" #{name} "%"
</select>

4.动态查询的sql怎么写?

If,where,foreach标签
Mybatis之动态SQL

5.If中And开头,选择了第二个,没选择第一个,怎么处理的第一个and?

自动移除没有选择的and

八. SpringBoot

1.项目是springboot是怎么向spring中注入

配置文件,有个配置类,简化配置文件,@bean标识方法,那么类用什么标识?@Configuration

2.为什么在springboot中写@Configuration注解就可以使用了呢?

@SpringbootApplication入口类会自动扫描自包。
通过@SpringBootApplication中的子注解@SpringBootConfiguration扫描加载

3.如果改变template文件夹,为template2,怎么找到?

将前缀修改成:spring.thymeleaf.prefix=classpath:/template2/

4.SpringBoot配置文件加载顺序

相同目录下,application.properties文件的优先级大于application.yml。
不同目录下的配置文件优先级从高到低顺序:(高优先级配置会覆盖低优先级配置,多个配置文件互补)

  1. file:./config/ - 优先级最高(项目根路径下的config)
  2. file:./ - 优先级第二 -(项目根路径下)
  3. classpath:/config/ - 优先级第三(项目resources/config下)
  4. classpath:/ - 优先级第四(项目resources根目录)

5.springboot最重要的注解,和它的子注解?

@SpringBootApplication
子注解:
@SpringBootConfiguration:加载配置
@EnableAutoConfiguration:启动配置
@ComponentScan:扫描组件

九. Redis

1.用过redis吗?它有哪几种类型?分别说一下。在使用的过程中有哪些需要注意的地方?使用场景

string,set,zset,list,map

String:简单的键值对存储,存储短信验证码,配置信息等
哈希:结构化对象,比如存一个对象;一般key存ID或者唯一值,它的value就存放详情信息,比如:商品详情,新闻详情、个人信息详情等
list:列表类型的数据结构,比如粉丝列表、文章评论列表。根据时间排序,存储一些有序且数据相对固定的数据,比如字典表、省市区表等。
zset:去重但可以排序,用于排行榜
set:并集、交集、差集的操作,比如将两人的粉丝列表合并成交集,查找两人的共同好友

2.验证码存redis,5分钟过期,怎么写?命令是什么?

java:

redisTemplate.opsForValue().set(String key,value,int timer,TimeUnit.SECONDS);

redis 命令:

set key value time seconds

3.Redis的持久化

持久化就是将内存中的数据写入到磁盘中去,防止服务宕机造成数据丢失
redis提供了两种解决范式RDB(默认)和AOF
RDB:就是将一定时间内的内存数据以快照形式保存到硬盘中,生成对应的文件dump.rdb,通过配置文件中的save参数来规定快照的周期
AOF:就是将每一条写指令写入到一个日志文件中,重启redis时会重新加载这个日志文件来恢复数据。这个文件默认叫appendonly.aof
两者比较:
RDB加载速度快,会有数据丢失,适用于数据要求不严谨时
AOF加载速度慢,不会有数据丢失。

4.了解redis吗?用来做什么?

了解,redis是非关系型数据库,用来缓存数据,减轻数据库压力,常用于存储数据库中不可变数据或者临时数据。

5. redis的过期策略有哪些?

redis同时使用的定期过期和惰性过期

  • 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
  • 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
    (expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)

附赠:redis面试汇总

十. MQ

1.消息队列(MQ)用过那个?用来处理什么业务的?

RabbitMQ

  1. 异步通信
  2. 削峰
  3. 解耦
    消息队列使用场景详解

十一. Linux

1. Linux用的怎么样?常用的命令有哪些?

cd cp ps -ef | grep … unzip vim gcc instal mkdir kill

2. (Linux)什么是管道?

管道就是用“|”连接两个命令,将前面一个命令的输出作为后面命令的输入,用于把管道左边的输出作为右边的输入

3. Linux中查看cpu,内存这些数据的指令是什么?

top -bn 1 -i -c

4. Linux中强行杀死线程命令?kill -1到-9?

kill -9 进程号

5. 查找java线程

ps -ef | grep java

十二. 其他

1. Nginx中location匹配规则

location匹配规则介绍

2. 排序算法哪些比较熟?时间复杂度?哪些是稳定的?

在这里插入图片描述

3. maven配置文件有哪些主要的元素?

  1. 如果maven项目有继承关系(Spring Boot),用<parent>标签指明父项目gav坐标。
  2. 当前项目的gav坐标(<groupId>/<artifactId>/<version>
  3. 当前项目产生的构件类型(<packaging>
  4. 自定义一些变量,通过${}来引用(<properties>
  5. 依赖(<dependencies>
  6. 资源路径列表(<resources>
  7. 插件(<plugins>

maven 配置文件pom文件属性详解

4. 简单说一下http请求四次挥手的过程?

http三次握手四次挥手详解

5. 了解docker吗?

什么是docker
docker的使用

6. gc机制

java垃圾回收机制

7. 1.8之后的java新特性

  1. 接口在JDK8中可以定义static方法与default方法
  2. 数组增加了并行方法,paralleSort()
  3. 新增了线程安全的日期API,java.time包
  4. 对部分集合进行了增强
    List增加了sort()排序
    HashMap性能进行了提升: 新增结点插入链表尾部,链表数量超过8会转换为红黑树,
    ConcurrentHashMap原来采用分段锁协议,在JDK8中改为CAS(Compare And Swap)
  5. 新增了Lambda表达式(重磅)
  6. 新增了对Stream流的支持

8. 自己的代码风格

代码有注解,驼峰命名法

9. fastDFS的两个组件?

  • 跟踪器(tracker)主要做调度工作,在内存中记录集群中存储节点storage的状态信息,是前端Client和后端存储节点storage的枢纽。因为相关信息全部在内存中,Tracker server的性能非常高
  • 存储节点(storage)用于存储文件,包括文件和文件属性(meta data)都保存到存储服务器磁盘上,完成文件管理的所有功能:文件存储、文件同步和提供文件访问等

10. jstl常用的标签

<c:foreach>
<c:if>
<c:set>
<c:where>
jstl常用标签详解

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值