各部分运行顺序?
JVM虚拟机启动会仅加载一次所有static变量,之后仅加载一次static代码块,在之后是main函数。每当有类实例化都会运行构造代码块,再执行构造函数。
即顺序为
- static静态变量
- static静态代码块
- main函数
- 构造代码块{}
- 构造函数
- 普通方法
- main函数结束
继承时运行顺序?
- 父类静态块
- 子类静态块
- 父类构造块{}
- 父类构造函数
- 子类构造块{}
- 子类构造函数
- 子类方法
CAS?
CAS全称 Compare And Swap,是一种无锁算法。在不使用锁(没有线程被阻塞)的情况下实现多线程之间的变量同步。
- 需要读写的内存值 V
- 进行比较的值 A
- 要写入的新值 B
当且仅当 V 的值等于 A 时,CAS通过原子方式用新值B来更新V的值(“比较+更新”整体是一个原子操作),否则不会执行任何操作。一般情况下,“更新”是一个不断重试的操作。
锁?
https://tech.meituan.com/2018/11/15/java-lock.html
悲观锁:认为在使用数据的时候一定有别的线程来修改数据,synchronized关键字和Lock的实现类。【适合写操作多的场景】
乐观锁:认为自己在使用数据时不会有别的线程修改数据,所以不添加锁,只在更新数据的时候去判断之前有没有别的线程更新了这个数据,如果没有被更新则成功写入,如果已经被更新,根据不同的实现方式执行不同的操作(例如报错或者自动重试),最常用CAS算法。【适合读操作多的场景】
锁的升级?
- 无锁
- 偏向锁
- 轻量级锁
- 重量级锁
线程间通信方式?
- 消息队列
- 全局变量(volatile)
- 使用事件
线程池的主要参数?
- corePoolSize(线程池基本大小)
- maximumPoolSize(线程池最大大小)
- keepAliveTime(线程存活保持时间)
- workQueue(任务队列)
- threadFactory(线程工厂)
- handler(线程饱和策略)
mysql事务?
一个或一组sql语句组成的一个执行单元,这个执行单元要么全部执行,要么全部不执行。
继承的作用?
- 提现相关类的层次结构
- 提供了复用,减少冗余,增加重用性
- 多态的前提
Java容器?
- Map
- HashMap
- Hashtable
- TreeMap
- Collection
- List
- ArrayList
- LinkedList
- Vector
- Stack
- Set
- HashSet
- LinkedHashSet
- TreeSet
- HashSet
- Queue
- List
为什么要重写equals()和hashcode()?
我们知道 == 用于比较两个对象的内存地址,Object的equal()方法实际上也是比较两个对象的内存地址是否相等。String类的equals()方法之所以是比较了内容,是因为对equals()方法进行了重写,使其比较的是字符的序列。
equals()方法需要满足:
- 自反:x.equals(x)
- 对称:x.equals(y) y.equals(x)
- 一致:x.equals(y) 多次调用结果不变
- 传递:x.equals(y) 且 y.equals(z) => x.equals(z)
- null返回false:x.equals(null) 返回false
在向Hash结构中添加元素时,首先调用hashCode()方法,若没有其他元素则直接保存,若已经有元素存在,则调用equals()方法来判断两个元素是否相同,相同则不储存,不同则链到后面(链地址法)。
Java约定:
- 如果两个对象根据equals方法比较是相等的,那么调用这两个对象的任意一个hashcode方法都必须产生相同的结果。
- 两个对象的hashCode相同,它们的equals()方法不一定相同。
而如果不重写hashCode()方法,就会出现两个对象equals()返回true,但hashCode值不相同的情况。
以下为示例代码:
import java.util.*; class Employee{ String name; int age; Employee(){ name = "null"; age = 0; } Employee(String name,int age){ this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if(this == obj) return true; if(obj == null) return false; if(getClass() != obj.getClass()) return false; var other = (Employee)obj; return Objects.equals(name,other.name) && age == other.age; } @Override public int hashCode() { return Objects.hash(name,age); } } public class Test { public static void main(String[] args) { Employee a = new Employee("aname",5); Employee aCopy = a; Employee b= new Employee("aname",5); System.out.println("a == aCopy: "+(a == aCopy)); System.out.println("a == b: "+(a == b)); System.out.println("aCopy == b: "+(aCopy == b)); System.out.println("==============="); System.out.println("a equals aCopy: "+a.equals(aCopy)); System.out.println("a equals b: "+(a.equals(b))); System.out.println("aCopy equals b: "+(aCopy.equals(b))); System.out.println("==============="); System.out.println(a.hashCode()); System.out.println(aCopy.hashCode()); System.out.println(b.hashCode()); } }
数据库范式相关
这里直接搬《数据库系统概论》(第五版)第六章中的内容。

函数依赖:R(U)是属性集U上的关系模式,X,Y是U的子集。若对于R(U)的任意一个可能的关系r,r中不可能存在两个元组在X上的属性值相等,而在Y上的属性值不等,则称X函数确定Y或Y函数依赖于X,记X→Y。
R(U)中,如果X→Y,并且对于X的任何一个真子集X‘,都有X’不能函数确定Y(或Y不函数依赖于X‘),则称Y对X完全函数依赖。如果X→Y,但Y不完全函数依赖于X,则称Y对于X部分函数依赖。
决定因素:若X→Y,则X称为这个函数依赖的决定属性组,也成为决定因素。
U={Sno, Sdept, Mname, Cno, Grade}中
F={Sno→Sdept, Sdept→Mname, (Sno,Cno)→Grade}
例如(Sno,Cno)→Grade是完全函数依赖,(Sno,Cno)→Sdept是部分函数依赖(因为Sno即可函数确定Sdept)。
1NF:每一个分量必须是不可分的数据项。
2NF:在1NF的前提上,每一个非主属性完全函数依赖于任何一个候选码。(可以成为主码,即U完全函数依赖于候选码)
3NF:每一个非主属性不传递依赖于码,也不部分依赖于码。(2NF条件基础上限制传递依赖)
备注:3NF的不彻底表现在可能存在主属性对码的部分依赖和传递依赖。
BCNF:关系模式R<U,F>∈1NF,若X→Y且Y⊈X时X必含有码。(在3NF基础上每一个决定因素都包含码)。详细来讲:
- 所有非主属性对每一个码都是完全函数依赖(2NF条件)
- 所有主属性对每一个不包含它的码也是完全函数依赖
- 没有任何属性完全函数依赖于非码的任何一组属性
例子:关系模式STJ(S,T,J),S表示学生,T表示老师,J表示课程。老师只教一门课,每门课有若干老师,某一学生选定某门课固定一个老师。则:
(S,J)→T,(S,T)→J,T→J
(S,J)和(S,T)是候选码,因此S,J,T都是主属性。满足3NF,但是主属性内出现了部分依赖。不满足BCNF,BCNF在3NF的基础上要求每一个决定因素都包含码,这里T并不包含码。
多值依赖:设R(U)是属性集U上的一个关系模式。X,Y,Z是U的子集,且Z=U-X-Y。关系模式R(U)中多值依赖X→→Y成立,当且仅当对R(U)的任一关系r,给定的一对(x,z)值,有一组Y的值,这组值仅仅决定于x值而与z值无关。
若X→→Y,而Z=Ø,则称X→→Y为平凡的多值依赖。
4NF:限制关系模式属性之间不允许有非平凡且非函数依赖的多值依赖。根据定义,对于每一个非平凡的多值依赖X→→Y,X都含有候选码,于是就有X→Y,所以4NF所允许的非平凡的多值依赖实际上是函数依赖。
volatile关键字的作用(华为技术面)
- 受限原子性(不保证)
- 可见性
- 有序性(没答出来)
有序性关系到指令重排序的问题。重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。