第一题 --(SE)
/**
* @ Author wuyimin
* @ Date 2021/9/5-14:46
* @ Description 如下代码的运行结果
*/
public class first01 {
public static void main(String[] args) {
int i=1;
i=i++;//step 1
int j=i++;//step 2
int k=i+++i*i++;//step 3
System.out.println(i);//4
System.out.println(j);//1
System.out.println(k);//11
}
}
自增在变量,运算在栈中,栈中运算完,赋值变量中
Step 1:
Step 2:
Step 3:
小结:
- 赋值=,最后计算
- =右边的从左到右加载值依次压入操作数栈
- 实际先算哪个,看运算符的优先级
- 自增,自减操作都是直接修改变量的值,不经过操作数栈
- 最后的赋值之前,临时结果也是储存在操作数栈中的
第二题-单例设计模式
/**
* @ Author wuyimin
* @ Date 2021/9/5-15:24
* @ Description 饿汉式 如果要释放资源的话就不能加final
*/
public class Singleton1 {
private final static Singleton1 instance=new Singleton1();//也可以在静态代码块加载
private Singleton1(){}
public static Singleton1 getInstance(){
return instance;
}
}
/**
* @ Author wuyimin
* @ Date 2021/9/5-15:27
* @ Description 懒汉式效率低
*/
public class Singleton2 {
private static Singleton2 instance;
private Singleton2(){}
//效率低下,也可以直接在方法上使用
public static Singleton2 getInstance(){
synchronized (Singleton2.class){
if(instance==null){
instance=new Singleton2();
}
return instance;
}
}
}
/**
* @ Author wuyimin
* @ Date 2021/9/5-15:38
* @ Description 懒汉式之双重检查锁模式
*/
public class Singleton3 {
private volatile static Singleton3 instance;//防止指令重排,保证可见性
private Singleton3(){}
public static Singleton3 getInstance(){
if(instance==null){
synchronized (Singleton3.class){
if(instance==null){
instance=new Singleton3();
}
}
}
return instance;
}
}
/**
* @ Author wuyimin
* @ Date 2021/9/5-15:43
* @ Description 静态内部类懒加载,相当于进阶版本的饿汉式
*/
public class Singleton4 {
private Singleton4(){}
private static class SubSingleton{
private static Singleton4 instance=new Singleton4();
}
public static Singleton4 getInstance(){
return SubSingleton.instance;
}
}
public enum Singleton5 {
type1("1",1),
type2("2",2);
Singleton5(String name,int age) {
this.age=age;
this.name=name;
}
private String name;
private int age;
}
第三题-类初始化和实例初始化
类初始化过程:
1.main方法所在的类需要先加载和初始化
2.一个子类要初始化需要先初始化父类
3.一个类初始化就是执行<clinit>)()方法--编译器生成
- 此方法由静态类变量显示赋值代码和静态代码块组成
- 类变量显示赋值代码和静态代码块从上到下顺序执行,并且只执行一次
实例初始化过程:
- 非静态实例变量显示赋值代码和非静态代码块从上到下顺序执行,而对应构造器的代码最后执行
- 每次创建实例对象,调用对应构造器,子类构造器中一定会先调用父类构造器,父类构造器调用的时候会先调用父类的非静态代码块
方法的重写:子类如果重写了父类的方法,子类在实例化的时候会调用super(),但是super()里执行的方法却是子类的方法,子类重写的方法其实执行了两遍。final,static,private方法不可重写
先初始化父类:5 1 再初始化子类 10 6
子类实例化方法:
调用super() 9 3 2
i=test() 9 子类的非静态代码块 8 子类无参构造 7
/**
* @ Author wuyimin
* @ Date 2021/9/5-15:55
* @ Description 父类
*/
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;
}
}
/**
* @ Author wuyimin
* @ Date 2021/9/5-15:58
* @ Description 子类
*/
public class Son extends Father {
private int i=test();
private static int j=method();
static{
System.out.println(6);
}
Son(){
System.out.println(7);
}
{
System.out.println(8);
}
@Override
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();//5 1 10 6 9 3 2 9 8 7
System.out.println();
Son son1 = new Son();//9 3 2 9 8 7
}
}
第四题-参数传递机制
/**
* @ Author wuyimin
* @ Date 2021/9/5-17:42
* @ Description String 和包装类等对象拥有不可变性
*/
public class first04 {
public static void main(String[] args) {
int i = 1;
String str = "hello";
Integer num = 2;
int[] arr = {1, 2, 3, 4, 5};
MyData my = new MyData();
change(i, str, num, arr, my);
System.out.println(i);//1
System.out.println(str);//hello
System.out.println(num);//2
System.out.println(Arrays.toString(arr));//[2,2..]
System.out.println(my.a);//[11]
}
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;
}
String不可变体现在本来str对应常量池里的hello,但是修改后并不是直接修改hello,而是会出现一个新的helloworld把它赋给我们的新变量s,所以str还是一样的
第五题:递归与迭代
package first;
/**
* @ Author wuyimin
* @ Date 2021/9/5-17:59
* @ Description
* 有n步台阶,一次只能上1步或者两步,一共有多少种走法
*/
public class first05 {
private static int loop(int n) {
if(n<1){
throw new IllegalArgumentException(n+"不能小于1");
}
if(n==1)return 1;
if(n==2)return 2;
int oneStep=1;//去第一阶台阶只有一种(这里表示较小值)
int twoStep=2;//去第二节台阶只有两种(这里表示较大值)
int sum =0;
for (int i = 3; i <=n; i++) {
sum=oneStep+twoStep;
oneStep=twoStep;//替换较小值
twoStep=sum;//替换较大值
}
return sum;
}
//递归方法
//三阶台阶等于两阶台阶+一阶台阶的数量
public static int step( int n){
if(n<1){
throw new IllegalArgumentException(n+"不能小于1");
}
if(n==1)return 1;
if(n==2)return 2;
int res=step(n-1)+step(n-2);
return res;
}
//优化递归
public static int step2(int n){
if(n<1) throw new IllegalArgumentException(n+"不能小于1");
if(n<=2)return n;
int[] memo = new int[n+1];
for (int i = 0; i <= n; i++) {
memo[i]=-1;
}
return record(n,memo);
}
//记录
public static int record(int n,int [] memo){
if(memo[n]!=-1)return memo[n];
if(n<=2) memo[n]=n;
else memo[n]=record(n-1,memo)+record(n-2,memo);
return memo[n];
}
public static void main(String[] args) {
long l = System.currentTimeMillis();
System.out.println("递归结果"+step(45));//时间2146
long l1 = System.currentTimeMillis();
System.out.println(l1-l);
System.out.println("迭代结果"+loop(45));//时间0
long l2 = System.currentTimeMillis();
System.out.println(l2-l1);
long l3=System.currentTimeMillis();
System.out.println("递归优化结果"+step2(45));//0
System.out.println(l3-l2);
}
}
第六题--成员变量和局部变量
package first;
/**
* @ Author wuyimin
* @ Date 2021/9/6-14:38
* @ Description
*/
public class first06 {
static int s;
int i;
int j;
//非静态代码块每次创建实例对象都会执行
{
int i=1;
i++;
j++;
s++;
}
public void test(int j){
j++;
i++;
s++;
}
public static void main(String[] args){
first06 obj1 = new first06();// 0 1 1
first06 obj2 = new first06();//0 1 2
obj1.test(10);//1 1 3
obj1.test(20);//2 1 4--》后变为2 1 5
obj2.test(30);//1 1 5
System.out.println(obj1.i+","+obj1.j+","+first06.s);//2 1 5
System.out.println(obj2.i+","+obj2.j+","+first06.s);//1 1 5
}
}
第六题--Spring Bean的作用域之间有什么区别(ssm框架)
可以通过scope属性来指定bean的作用域
- -singleton:默认值。单例
- -prototype:原型的。当IOC容器一创建不再实话该bean,每次调用getBean方法都会获得一个新的实例
- -request:每次HTTP请求都会创建一个新的bean,仅仅适用于WebApplicationContext环境
- -session:在一次会话中共享一个bean,仅仅适用于WebApplicationContext环境
第七题--简单介绍Spring支持的常用数据库事务传播属性和事务隔离级别
事务的传播行为:通过propagation设置
一个事务方法被另一个事务方法调用的时候,当前方法时使用原来的事务还是开启一个新的事务
- -Propagation.Required:默认值,使用原来的事务
- -Propagation.Requires_new:开启一个新的事务
事务的隔离级别:读未提交,读已提交,可重复读,序列化。MySql默认是可重复读
后面三个级别分别解决脏读(事务1将某条记录值从10改到了20,事务2读取了更新后的值20,此时事务1出错回滚,数据值回到了10,那么事务2的行为就称之为脏读)
不可重复读(事务1读取了数据为10,事务2修改数据为20,事务1再次读取发现和第一次读取不一致,一个事务范围内多次查询数据得到的结果不一致(违反一致性))
幻读(事务1读取了表中的一部分数据,事务二插入了一部分数据,事务1在读取表的时候发现多出了一些行)
第八题--SpringMVC中如何解决post请求中文乱码问题
注册一个filter让他拦截所有请求
如果是get请求找到Connector属性添加utf-8
第九题-谈谈springMVC的工作流程
第十题-mybatis中实体类和表字段名不匹配怎么办
三种解决方案
1.写sql语句的时候起别名
2.在mybatis的全局文件中开启驼峰命名规则
3. 在Mapper映射文件中使用resultMap来自定义映射
第十一题--Linux常用服务类相关命令
七个运行级别
设置自启动命令(centos6)
chkconfig --level 运行级别 服务名 on
centos7查看防火墙状态
systemctl list-unit-files |grep firewalld
关闭防火墙
systemctl disable firewalld
第十三题-Git分支相关命令
第十四题-redis持久化
RDB:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是SnapShot快照,它恢复的时候是将快照文件直接读到内存里。Redis会单独fork一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再使用临时文件替换上次持久化好的文件。整个过程中,主线程是不进行任何io操作的,这就确保了极高的性能,如果需要进行大规模的数据恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加高效,RDB的缺点是在最后一次持久化的数据可能会丢失。
AOF: 以日志的形式记录每一个写操作,将redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可用改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
第十五题--MySql什么时候适合建立索引
索引--帮助mysql高效获取数据的数据结构
索引的优势:提高数据检索的效率,降低数据库的io成本,通过索引列对数据进行排序,降低数据排序的成本,降低cpu的消耗
索引的劣势:虽然索引大大提高了查询速度,同时却会降低更新表的速度,insert,update,delete等性能都会下降,mysql不仅要保存数据,还需要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。实际上索引也是一张表,该表保存了主键和索引字段,并指向实体表的记录,所以索引列也是要占用空间的
需要建立索引的情况
- 主键自动建立唯一索引
- 频繁作为查询条件的字段应该创建索引
- 查询中与其他表关联的字段,外键关系建立索引
- 单键/组合索引的选择问题:组合索引性价比更高
- 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
- 查询中统计或者分组字段
不适合建立索引的情况
- 表记录很少
- 经常增删改的字段和表
- where条件里用不到的字段
- 过滤性不好的--比如性别字段,过滤性好的字段比如身份证号
第十六题--JVM垃圾回收机制
第十七题--Redis在项目中的使用场景(javaEE)
第十八题--ElasticSearch和solr的区别
第十九题--单点登录实现过程
第二十题--购物车实现流程
和购物车有关的操作有哪些
1.添加购物车
将数据保存到什么地方?
当用户未登录时:将数据保存在redis中(使用哈希储存(key,field,value))
在用户登录时:将数据持久化到mysql里(保证安全性)
2.展示购物车
未登录状态展示:直接从redis中取得数据展示即可
登录状态:用户一旦登录必须显示数据库的数据+redis中的数据
第二十一题--消息队列在项目中的使用
同步和异步
排队和并行
消息队列在电商中的使用场景