附加题:

1、&和&&区别

1
2
3
&和&&都可以用作逻辑与运算符,表示逻辑与(and)。当运算符两边的表达式的结果都为true时,整个运算结果才为true。否则,只要有一方为false。则结果为false
&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式
&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作

2、jdk和jre区别

1
2
jdk是java开发工具包,里面包含jre和java开发工具,比如:java.exe(java运行工具)  javac.exe(java编译工具) jar.exe(打包工具)
jre是java程序运行环境 包含jvm和核心类库

3、switch支持的数据类型

1
byte、short、int、char、String、枚举 以上基本数据类型对应的包装类

4、JVM内存划分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
栈内存:
存储方法内部声明的局部变量
方法声明的参数和大括号{}内部声明的变量都属于局部变量
堆内存:
存储所有new出来的数据
堆内存的数据都有内存地址 内存地址用十六进制表示 eg:0x1234
堆内存的数据都有默认值
byte short int long 默认值为0
float double 默认值为0.0
boolean 默认值为false
char '\u0000' 空字符
引用数据类型 默认值为null
方法区 存储.class文件相关信息 比如 类名 方法声明等等
本地方法栈 系统相关
寄存器 cpu相关

5、值传递和引用传递的区别

1
2
3
4
值传递:
基本数据类型做的是值传递,将当前变量的值复制一份存入其他变量,对其他变量的值进行修改时,当前变量的值没有影响
引用传递(内存地址的传递):
引用数据类型做的是引用传递,将当前引用变量的内存地址存入其他引用变量,通过其他引用变量对堆中的值修改时,当前引用变量获取的是堆中修改以后的值

6、成员变量和局部变量的区别:

1
2
3
4
5
6
7
8
9
10
11
作用域不同:
局部变量的作用域仅限于定义它的方法
成员变量的作用域在整个类内部都是可见的
初始值不同:
java会给成员变量一个初始值
java不会给局部变量赋予初始值
注意:
在同一个方法中,不允许有同名局部变量
在不同的方法中,可以有同名局部变量

在同一个类中,成员变量和局部变量同名时,局部变量具有更高级的优先级

7、构造方法注意事项

1
2
3
4
5
6
7
注意:
1、构造方法声明不能写返回值,连void都不能写
2、构造方法一定与类名一致
3、如果类里面没有手写构造方法,默认提供无参构造方法
4、如果类里面写了构造方法,默认的无参构造方法不再提供
推荐:
一定先写无参构造 再写带参构造

8、 static修饰变量 方法和代码块

1
2
3
4
5
6
7
8
9
10
static修饰的变量叫静态变量(类变量) 只和类相关 通过类名.静态变量名访问
静态变量存在方法区内存,只保存一份

static修饰的方法叫静态方法(类方法),只和类相关 通过类名.静态方法名调动
注意事项:
1、静态方法只能直接访问静态变量和静态方法
2、静态方法不能直接访问成员变量和成员方法
static修饰的代码块叫静态代码块,当第一次使用类时,静态代码块执行一次,后面不再执行

成员方法可以访问成员变量和成员方法,还有静态变量和静态方法

9、Object的toString()

1
默认返回的可以理解为对象的内存地址

10、abstract抽象

1
2
3
4
5
6
7
8
abstract修饰的类叫抽象类
抽象类不能创建对象
abstract修饰的方法叫抽象方法,抽象方法没有方法体 以;号结束
1、子类继承父类 子类必须重写父类中所有抽象方法
除非子类也是抽象类 抽象子类可以重写或者不重写
2、抽象方法所在的类必须是抽象类

如果抽象子类没有重写父类抽象方法,相当于继承了这些抽象方法

11、多态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
同一种事物的不同种表现形式

多态: 父类类名 引用变量 = new 子类类名(); 自动类型转换 向上转型
父类变量调用的一定是子类重写的方法

父类变量无法调用子类独有的方法,需要将父类强制转换子类

引用变量 instanceof 类名
包含对象的类型和对象的直接父类或间接父类
如果instanceof后面的类型是 对象类型 或者是对象的直接父类或者间接父类 都是返回true

父类变量能调用:
1、父类中声明的方法
2、父类中声明过,然后子类重写的方法

12、访问修饰符

1
2
3
4
5
private 修饰的属性和方法  只能在本类中访问
默认 修饰的属性和方法 本类和同包下的其他java类可以访问
protected 修饰的属性和方法 本类和同包下的其他java类可以访问 如果是不同包下的子类,子类可以访问
public 修饰的属性和方法 任何位置可以访问

13、内部类

1
2
3
4
5
6
7
8
9
10
11
12
成员内部类
1 在外部类要使用内部类,需要创建内部类对象访问
2 内部类可以直接外部类的成员
1、在外部类的成员方法里面使用 创建内部类对象
2、外部类名.内部类名 引用变量 = new 外部类名().new 内部类名();
局部内部类(包含了匿名内部类):
//只要是匿名内部类访问的局部变量,必须是final的,只能进行一次赋值
局部内部类地位等同于局部变量 前面不能加访问修饰符
局部内部类是可以直接访问所在方法的final的局部变量的
有一个前提 局部变量必须是final的常量
jdk1.7之前final必须加,jdk1.8开始给变量赋值以后final可以省略
匿名内部类属于局部内部类的,在方法内部声明,也在方法内部使用

14、10个异常名字

1
2
3
4
5
6
7
8
9
10
11
12
运行时异常
NullPointerException 空指针异常
ArrayIndexOutOfBoundsException 数组下标越界异常
IndexOutOfBoundsException 下标越界异常
ClassCastException 类型转换异常
NumberFormatException 数字格式化异常
检查异常(编译异常)
IOException
FileNotFoundException 文件找不到
ClassNotFoundException 类找不到,类加载
EOFException
SQLException

15、throws和throw的区别

1
2
3
1、throws用在方法声明的位置,throw用在方法体内
2、throws是可能出现异常 throw是一定出现异常
3、throws后面跟异常类名 throw后面跟异常对象

JAVA语言如何进行异常处理,关键字:throws, throw,try, catch, finally分别代表什么意义?在try块中可以抛出异常吗?

1
2
3
4
5
6
Try用来指定一块预防所有异常的程序
Catch子句紧跟在try块后面,用来指定你想要捕捉的异常的类型
Throw语句用来明确地抛出一个异常
Throws用来标明一个成员函数可能抛出的各种异常
Finally为确保一段代码不管发生什么异常都被执行一段代码
在try块中是可以抛出异常的。

16、Error和Exception的区别

1
2
3
4
5
6
7
8
Exception:非严重错误,程序员可以解决,异常分为运行时异常和检查异常,再说下两个异常概念
1.可以是可被控制(checked) 或不可控制的(unchecked)。
2.表示一个由程序员导致的错误。
3.应该在应用程序级被处理。
Error: 严重错误,程序员无法解决的,例如,内存溢出
1.总是不可控制的(unchecked)。
2.经常用来用于表示系统错误或底层资源的错误。
3.如果可能的话,应该在系统级被捕捉。

17、异常分为运行时异常和检查异常(编译异常):

1
2
3
4
5
运行时异常:
所有RuntimeException类及其子类都属于运行时异常, 程序对运行时异常,可以选择处理或者不处理
检查异常:
除了RuntimeException类及其子类都属于检查异常,程序要求对检查异常必须处理,否则编译不通过

18、调用者针对方法声明的异常有2种处理方法

1
2
3
1、try catch  立即捕获异常处理异常
2、继续在当前方法throws声明异常,将异常抛给下一个调用者
注意:main声明的异常交给java虚拟机处理,java虚拟机的处理方式就是不处理,程序在异常位置立即结束

19、单例 懒汉式饿汉式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
确保在程序运行时,一个类的实例有且仅有一个
目的: 节省内存
懒汉式单例
//懒汉式
public class User {
//1 构造方法私有化
private User(){};
//2 声明当前类数据类型的私有的静态变量
private static User user;
//3 声明一个获取当前类对象的静态方法
public static synchronized User getUser(){
if (user == null){
user = new User();
}
return user;
}
}

饿汉式单例
//饿汉式
public class Person {
//1 构造方法私有化
private Person(){}
//2 声明当前类数据类型的静态变量,同时初始化 饿汉式
private static Person person = new Person();
//3 公共的获取当前类对象的静态方法
public static Person getPerson(){
return person;
}
}

20、Collection和Collections的区别

1
2
3
4
5
6
7
Collection是集合的顶级接口 下面有List和Set2个子接口
Collections是一个集合的操作类,里面提供了一些静态方法
Collection:
是一个集合接口(集合类的一个顶级接口),它提供了对集合对象进行基本操作的通用接口方法。
Collection接口在java类库中有很多具体的实现,Collection接口的意义是为各种具体的集合提供了最大化的统一操作方法,其直接继承接口有List和Set
Collections:
是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等

21、泛型

1
2
3
4
将类名作为集合的参数 写在集合名的右边
1、限制当前集合只能存指定的Student类型的对象
2、集合中全是Student类型的对象,所以get()方法取出的就是Student对象,不需要强转
考点:如果不写泛型,有默认的泛型是Object

22、ArrayList特点 扩容机制

1
2
查询快,增删慢
数组集合初识长度为10,之后以1.5倍扩容

23、hashMap底层原理*********

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
如果Node数组长度>原始长度*加载因子  数组开始扩容
第一次扩容 13大于 12= 16*0.75

HashMap底层是哈希表数据结构
jdk1.8开始 哈希表=Node数组+链表(单向链表)+红黑树(二叉树的一种)
Node数组初始长度16 加载因子0.75 扩容到原数组的2倍
单向链表的节点个数>8 并且 数组长度>64 链表转红黑树
如果节点个数<6 红黑树转回链表

调用map.put(key,value)时,会调用key的hashcode方法计算出哈希值,
这个哈希值会经过再次运算得到最终的哈希值,根据哈希值计算出在Node数组的存储下标,
1、如果数组下标对应的空间没有值,key和value直接存入
2、如果数组下标对应的空间有值(存在一个单向链表),继续调用key的
equals方法和单向链表中每个节点的key比较,
如果返回true,后面的value覆盖前面的value
如果返回false,key和value存入

24、hashcode和equals的区别和联系

1
2
3
4
5
6
7
8
9
10
11
12
hashCode()基于对象的内存地址计算一个整形值(哈希值),并将整形值返回
equals()默认使用==比较2个对象的内存地址是否相等
关联1:
如果2个对象的equals相等,那么2个对象的hashcode一定相等
关联2:
如果2个对象的equals不相等,那么2个对象的hashcode可能相等
关联3:
如果2个对象的hashcode不相等,那么2个对象的equals一定不相等
//hashcode是可以在子类重写的
//jdk中String类重写了Object类的hashcode
//String类的hashCode()根据字符串内容计算整形值(哈希值)
//字符串内容一样,哈希值一样

25、ArrayList和LinkedList区别

1
2
ArrayList底层是数组 查询快 增删慢
LinkedList底层是双向链表 查询慢 增删快

list和set的区别

1
2
3
1、list可以允许重复对象,set不允许
2、list方法可以插入多个null,set只允许插入一个null
3、list是有序的,set是无序的

Collections类常用方法总结

1
2
3
4
5
6
sort(Collection)方法的使用(含义:对集合进行排序)。
reverse()方法的使用(含义:反转集合中元素的顺序)。
shuffle(Collection)方法的使用(含义:对集合进行随机排序)。
fill(List list,Object o)方法的使用(含义:用对象o替换集合list中的所有元素)
copy(List m,List n)方法的使用(含义:将集合n中的元素全部复制到m中,并且覆盖相应索引的元素)。
replaceAll(List list,Object old,Object new)方法的使用(含义:替换批定元素为某元素,若要替换的值存在刚返回true,反之返回false)。

Arrays数组操作

1
2
asList()   返回一个list集合
toString() 打印一个数组

Java集合类框架的基本接口有哪些?

1
2
3
4
5
6
7
8
9
10
11
12
Collection:单列集合的根接口
List:元素有序,可重复
ArrayList:类似一个长度可变的数组,适合查询,不适合增删
LinkedList:底层是双向循环链表,适合增删,不适合查询
Set:元素无序,不可重复
HashSet:根据对象的哈希值确定元素在集合中的位置
TreeSet:以二叉树的方式存储元素,实现了对集合中的元素排序
Map:双列集合的根接口,用于存储具有键、值映射关系的元素
HashMap:用于存储键值映射关系,不能出现重复的键key
TreeMap:用来存储键值映射关系,不能出现重复的键key,所有的键按照二叉树的方式排列

总共有两大接口:Collection 和Map ,一个元素集合,一个是键值对集合; 其中List和Set接口继承了Collection接口,一个是有序元素集合,一个是无序元素集合; 而ArrayList和 LinkedList 实现了List接口,HashSet实现了Set接口,这几个都比较常用; HashMap 和HashTable实现了Map接口,并且HashTable是线程安全的,但是HashMap性能更好;

26、ArrayList、hashmap、hashtable扩容机制

1
2
3
4
ArrayList数组初始长度10  扩容原来数组的1.5倍,等数组存满之后再存数据的时候开始扩容
hashmap数组初始长度16 加载因子0.75 扩容到原数组的2倍 如果Node数组长度>原始长度*加载因子 数组开始扩容
hashtable中的数组初始长度为11,扩容原数组的2倍+1

27、HashSet底层 照着HashMap底层回答

28、字符串常量池

1
2
3
4
5
jdk1.7之前 字符串常量池在方法区
jdk1.7开始 字符串常量池在堆中
""包含的数据直接存在字符串常量池
如果字符串常量池能找到字符串,直接返回字符串的内存地址,
如果字符串常量池找不到字符串,创建字符串,返回内存地址

29、Integer有一个常量池 缓存了-128到127之间的值

1
2
3
Integer k = 127;  ====  Integer k = Integer.valueOf(127);
相当于在常量池中找到了数字的内存地址存入变量中
new出来的Integer,范围在-128到127也是新的内存地址

30、枚举

1
2
3
4
5
6
7
public enum Gender {
//常量 所有字母大写
MAN,WOMAN

}
//枚举数据类型的变量只能存枚举里面声明的常量,通过枚举名.常量名访问
student.setGender(Gender.MAN);

31、线程同步的方式3种

1
2
3
1、同步代码块
2、同步方法
3、lock锁

32、sleep和wait区别

1
2
3
4
1 sleep是Thread类的方法 wait是Object类的方法
2 sleep不会释放对象锁 wait会释放对象锁的
3 sleep的休眠时间到达后会自动进入就绪状态
wait的线程必须由notify方法唤醒,唤醒后进入同步阻塞状态

33、面向对象的基本特征

1
2
3
封装:将类中所有成员变量私有化,提供公共的get和set
继承:子类继承父类非私有的属性和方法
多态:当父类类型的引用变量,保存不同的子类对象时,执行方法的结果是不一样的

34、深拷贝和浅拷贝

1
2
3
4
5
浅拷贝(shallowCopy)拷贝出一个新的对象,新对象中的基本数据类型的变量是复制了一份,引用类型和旧对象中的引用类型指向堆中同一个数据
深拷贝(deepCopy)会创造一个新的对象,修改新对象不会影响原对象的属性值
Object o1 = new Object();
Object o2 = new Object();
o2.setId(o1.getId);

35、如何退出多重循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//利用标签变量
// 标签名的命名方法是:java命名规则 和 半角冒号 比如: lableA:
public static void main(String[] args){
lableB:
for(int i=0;i<3;i++){
lableA:
for(int j=0;j<3;j++){
System.out.println(j);
if(j==1){
break lableB;
}
}
}
System.out.println("over!");
}

char型变量中能不能存贮一个中文汉字?为什么?

1
2
3
4
char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,
所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,
那么,这个char型变量中就不能存储这个特殊汉字。
补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节

说出一些常用的类,包,接口,请各举5个

1
2
3
4
5
6
常用的类:BufferedReader BufferedWriter FileReader FileWirter String Integer java.util.Date,System,Class,List,HashMap
常用的包:java.lang java.io java.util
java.sql ,javax.servlet,org.apache.strtuts.action,org.hibernate
常用的接口:Remote List Map Document
NodeList,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate)
Session(Hibernate),HttpSession

描述final, finally, finalize的区别?

1
2
3
final用于声明属性,方法和类,修饰的类不能被继承,例如String,修饰的方法不能被重写,修饰的属性为常量,一旦被赋值不能被修改
finally是异常处理语句结构的一部分,表示总是执行
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等,jvm不保证此方法总被调用

1、java有哪些基本数据类型 什么是自动装箱?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
byte  Byte 	1  -128~127
short Short 2 -32768~32767
int Integer 4 -21亿~21亿
long Long 8 19位
float Float 4 39位
double Double 8
char Character 2 0~65535
boolean Boolean 1
自动装箱 将基本数据类型自动转换对应的包装类
自动拆箱 将包装类自动转换对应的基本数据类型

int和Integer有什么区别?
1、Integer是int的包装类,int是基本数据类型
2、Integer变量必须实例化后才能使用,int变量不需要
3、Integer实际是对象的引用,指向此new的Integer对象,int是直接存储数据值
4、Integer的默认值是null,int的默认值是0

2、算法实现之在不引入其他变量的情况下让int变量a和int变量b互换

1
2
3
4
5
6
7
8
9
10
int a = 10;
int b = 20;
a = a + b;
b = a - b;
a = a - b;

temp = a;
a = b;
b = temp;

3、编写一个方法输出1-100之间的所有的素数,所谓素数:只能被1和本身整除的称为素数

1
2
3
4
5
6
7
8
9
10
11
12
for (int i = 2; i <=100 ; i++) {
boolean flag = true;
for (int j = 2; j < i ; j++) {
if (i%j == 0){
flag = false;
break;
}
}
if (flag){
System.out.println(i);
}
}

4、有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int count = 0;
for (int i = 1; i <= 4 ; i++) {
for (int j = 1; j <= 4 ; j++) {
if (j == i){
continue;
}
for (int k = 1; k <= 4 ; k++) {
if (k == i || k == j){
continue;
}
count++;
System.out.println(i*100 + j*10 + k;);
}
}
}
System.out.println("总个数为:" + count);

5、冒泡排序

1
2
3
4
5
6
7
8
9
10
int[] nums = { 20,2,15,1 };
for (int i = 0; i < nums.length-1; i++) {
for (int j = 0; j < nums.length - 1 - i; j++) {
if (nums[j] > nums[j+1]){
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}

6、一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在 第10次落地时,共经过多少米?第10次反弹多高?

1
2
3
4
5
6
7
8
9
double height = 100;
double len = 0;
int num = 10;
for (int i = 0; i < num; i++) {
len = len + height + height/2;
height /= 2;
}
System.out.println("第" + num + "次反弹了" + height + "米");
System.out.println("共经过了"+ (len-height) + "米");

7、静态变量和实例变量的区别?

1
2
3
1 静态变量只和类相关 通过类名调用
成员变量和对象相关 需要先创建对象 通过对象名调用
2 静态变量存在方法区内存 成员变量存在堆内存

8、说说final关键字的用法?

1
2
3
4
1 final修饰的类不允许有子类
2 final修饰的方法不能被子类重写
3 final修饰的变量是常量
常量一旦赋值,不允许修改

9、选择排序算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int[] nums = {10,30,5,20,50};
for (int i = 0; i < nums.length-1; i++) {
//每次循环将第一个值当做最小值,将最小值的下标存入min
int min = i;
for (int j = i+1; j < nums.length ; j++) {
if (nums[min]>nums[j]){
min = j;
}
}
if (min!=i){
int temp = nums[i];
nums[i] = nums[min];
nums[min] = temp;
}
}
System.out.println(Arrays.toString(nums));

10、== 和equals区别

1
2
3
4
5
6
==
如果2边是基本数据类型,做的是值的比较
如果2边是引用数据类型,做的是内存地址的比较
Object类的equals()
默认是使用==判断2个对象的内存地址是否相等
重写以后按照自定义规则比较2个对象

11、创建一个子类对象,请写出:父类静态代码块,父类构造方法,父类代码块,子类代码块,子类构造,子类静态代码块。这六个对象的执行顺序

1
2
3
4
5
6
1 父类静态代码块
2 子类静态代码块
3 父类实例代码块
4 父类构造方法
5 子类实例代码块
6 子类构造方法

12、抽象类和接口的区别

1
2
3
4
5
6
1、抽象类继承Object,接口不是 
2、抽象类有构造方法,接口没有
3、抽象类可以声明成员变量和静态常量,接口只能声明静态常量
4、抽象类可以声明成员方法,抽象方法,接口可以声明抽象方法和静态方法和默认方法(jdk1.8开始)
5、抽象类中可以有final修饰的方法,接口不能
6、抽象类是单继承多实现,但是接口只能继承多个其它接口

13、int和Integer有什么区别?

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

14、Hashtable和HashMap区别?

1
2
3
4
1 继承的父类不同
2 hashtable是线程安全的 hashmap是非线程安全的
3 hashtable key和value都不允许null值 hashmap key和value都允许null值
4 hashtable 数组初始长度11 扩容原数组的2倍+1 hashmap 数组初始长度是16 扩容原数组的2倍

15、什么是类?什么是对象?什么是接口?接口和类的继承有什么本质区别

1
2
3
4
对象:用来描述客观事物的一个实体,由一组属性和方法构成
类:具有相同属性和方法的一组对象的集合
接口: 包含一系列方法的声明,一个接口只有方法的特征没有方法的实现
一个类只能继承一个父类,可以实现多个接口

16、String s = new String(“xyz”);创建了几个字符串对象?

1
2个对象  堆内存一个   字符串常量池一个

17、Comparable接口的用途

1
Comparable接口里面有一个compareTo()方法。当一个类需要比较的时候,需自行实现Comparable接口的CompareTo方法。当调用集合排序方法的时候,就会调用对象的compareTo()方法来实现对象的比较。

ArrayList存储学生对象 如何排序

1
学生类实现Comparable接口 重写compareTo方法,当集合排序时,会调用当前对象的compareTo方法和其他对象进行比较

comparable和comparator接口的用途?列出他们的区别?

1
2
3
4
首先这两个接口一般都是用来实现集合内的排序,comparable也可以用于两个对象大小的比较。
Comparable接口在java.lang包下面。里面有一个compareTo(T)接口方法。当一个类需要比较的时候,需自行实现Comparable接口的CompareTo方法。当调用集合排序方法的时候,就会调用对象的compareTo()方法来实现对象的比较。
Comparator接口在java.util包下面。Comparator是一个比较器接口,一般单独定义一个比较器实现该接口中的比较方法compare();在集合sort方法中传入对应的比较器实现类。一般使用匿名内部类来实现比较器。
Comparator相对于Comparable来说更加的灵活,耦合度低。

18、Overload 和 Override 的区别,Overload方法是否可以改变返回值的类型?

1
2
3
4
5
6
7
8
9
10
11
方法重载
1 方法名相同
2 参数项不同(参数个数 参数数据类型 参数声明顺序)
与访问修饰符 返回值类型无关
方法重写
1 子类重写方法的访问修饰符不能严于父类
2 子类重写方法的返回值类型和父类一致
3 子类重写方法的方法名和父类一致
4 子类重写方法的参数列表和父类一致

Overload方法可以改变返回值的类型

19、二分查找法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static int getIndex(int[] nums,int value){
int min=0;
int max=nums.length-1;
while (true){
int mid=(min+max)/2;
if (nums[mid]==value){
return mid;
}else if(nums[mid]>value){
max=mid-1;
}else if(nums[mid]<value){
min=mid+1;
}

if(min>max){
return -1;
}
}
}

20、String StringBuffer StringBuilder区别

1
2
3
4
5
6
7
8
9
1 String是不可变的 对String类的任何改变都会返回一个新的String对象
StringBuffer是可变的,对StringBuffer的内容修改都是当前这个对象
2 String类重写了Object类的equals方法和hashcode方法
StringBuffer没有重写equals方法
3 String创建的字符串保存在字符串常量池,StringBuffer在堆中创建对象
4 StringBuffer是线程安全的 StringBuilder是非线程安全的
附加:
5、String底层是final修饰的字符数组
StringBuffer底层是普通的字符数组

String常用方法:

1
2
3
4
5
6
7
8
int length(); 得到字符串的字符个数
char charAt(值); 返回值为char类型 从字符串中取出指定位置的字符
char toCharArray(); 返回值为 char 数组类型。将字符串变成一个字符数组
int indexOf("字符") 找一个指定的字符串是否存在,返回的是字符串的位置,如果不存在,则返回-1 。
toUpperCase(); toLowerCase();字符串大小写的转换
String[] split("字符")根据给定的正则表达式的匹配来拆分此字符串。形成一个新的String数组。
boolean equals(Object anObject)比较两个字符串是否相等,返回布尔值
trim();  去掉字符串左右空格  replace(char oldChar,char newChar);新字符替换旧字符,

21、给定两个一维字符串数组a和b,要求除去a中包含b中元素的项,得到数组c。说明:a和b中都可能存在为null的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
例如给定的数组为:  
String a[] = new String[]{"a","b",null,"c",null,"d"};
String b[] = new String[]{"a","c",null};

那么得到的数组C应为:{"b","d"}
String a[] = new String[]{"a","b",null,"c",null,"d"};
String b[] = new String[]{"a","c",null};
ArrayList<String> list=new ArrayList<>();
for (String s1 : a) {
boolean flag=true;//默认s1是a数组独有的
for (String s2 : b) {
if (s1==s2){
//字符串常量池 "a"=="a" 比较内存地址 0x123==0x123 true
flag=false;
break;
}
}
if (flag){
list.add(s1);
}
}
System.out.println(list);

22、输入一个字符串 通过递归 返回逆序字符串

1
2
3
4
5
6
public static String daoXu(String s){
if(s.length()==1){
return s;
}
return daoXu(s.substring(1))+s.charAt(0);
}

23、输入一个字符串 比如 String s=”aabbbc” 求字符串中每个字符的出现次数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
String s="aabbbc";
Map<String,Integer> map=new HashMap<>();
char[] array = s.toCharArray();//
for (char c : array) {
if (map.get(c+"")==null){
map.put(c+"",1);
}else {
map.put(c+"",map.get(c+"")+1);
}
}

Set<String> keySet = map.keySet();
for (String key : keySet) {
System.out.println(key+"出现"+map.get(key)+"次。");
}

24、递归查找指定目录所有文件 输出文件名

1
2
3
4
5
6
7
8
9
10
11
public  static  void  show(File file){
File[] files = file.listFiles();
for (File f : files) {
if ( ! f.isFile()){
show(f);
}else {
System.out.println(f.getName());
}
}
}

25、使用字节流将c:/1.txt 复制到d:/2.txt

1
2
3
4
5
6
7
8
9
10
11
12
FileInputStream fis=new FileInputStream("c:/1.txt");
FileOutputStream fos=new FileOutputStream("d:/2.txt");

byte[] b=new byte[1024];
int temp;
while ( (temp=fis.read(b)) !=-1 ){
fos.write(b,0,temp);
}

fis.close();
fos.close();

26、字节流有哪些? 缓冲流的加速方式

1
2
3
4
5
6
7
8
9
10
11
InputStream
FileInputStream
BufferedInputStream
ObjectInputStream
OutputStream
FileOutputStream
BufferedOutputStream
ObjectOutputStream

缓冲流内置了默认大小的数组

27、多线程有几种实现方式?你推荐哪一种

1
2
3
4
5
1 继承Thread类
2 实现Runnable接口
3 实现Callable接口
4 线程池
推荐使用线程池 因为线程池里面的线程可以循环使用。

28、synchronized和Lock锁两者区别:

1
2
3
4
5
1.首先synchronized是java内置关键字,Lock是个java接口;
2.synchronized会自动释放锁,Lock需要调用unlock()方法手动释放锁
3.用synchronized关键字修饰的同步代码,如果线程1获得对象锁,线程2会一直等待
而Lock接口锁定的同步代码,如果线程1获得对象锁,线程2尝试获取不到锁的话,线程2可以不用一直等待。
4.Lock锁适合大量代码的同步问题,synchronized锁适合少量代码的同步问题。

产生多线程死锁的必要条件及解决方法

1
2
3
4
5
6
7
8
死锁产生的根本原因是资源竞争。如果若干个线程正常运行,遇到彼此需要对方占有的资源时,就可能产生线程死锁.
死锁产生的条件包括以下4点:
资源互斥:即资源仅能让一个线程使用而不支持多个线程同时使用。
请求保持:已经拥有资源的线程在请求其他资源时并没有释放当前资源。
不能剥夺:已经获得的资源在自主释放前不能使用其他手段剥夺。
循环等待:各个线程对资源的需求构成了一个循环。
解决方法:
破坏循环等待是最有效的解决死锁的方法。

29、什么是java序列化?如何实现java序列化

1
2
序列化(ObjectOutputStream)可以将内存中Java对象写在硬盘上,反序列化(ObjectInputStream)就是将硬盘的内容读取到内存中重新构建对象;java是通过实现序列化接口
(Serializable接口) 实现的序列化.

30、兔子递归

1
2
3
4
5
6
public static int getNum(int month){
if(month==1 || month==2){
return 1;
}
return getNum(month-1)+getNum(month-2);
}

31、插入排序

1
2
3
4
5
6
7
8
9
10
11
int[] nums={17,3,20,5};
for (int i = 1; i <nums.length ; i++) {
int insertValue=nums[i];//待插入的值 也就是无序列表的第一个值
int insertIndex=i-1;//待比较值的下标 初始值是有序列表最后一个值的下标
while (insertIndex>=0&&insertValue<nums[insertIndex]){
nums[insertIndex+1]=nums[insertIndex];
insertIndex--;
}
nums[insertIndex+1]=insertValue;
}
System.out.println(Arrays.toString(nums));

32、java中创建对象的方式

1
2
3
4
5
6
调用构造方法:
new对象
反射
不调用构造方法:
反序列化 Object clone()
克隆

33、创建Class对象的3种方式

1
2
3
1 Class.forName("类的完整路径")
2 类型.class
3 对象.getClass()

34、如何实现线程安全的HashMap

1
2
3
有2种办法让HashMap线程安全,分别如下:
  方法一:通过Collections.synchronizedMap()返回一个新的Map,这个新的map就是线程安全的。 这个要求大家习惯基于接口编程,因为返回的并不是HashMap,而是一个Map的实现。
  方法二:重新改写了HashMap,具体的可以查看java.util.concurrent.ConcurrentHashMap. 这个方法比方法一有了很大的改进。

ConcurrentHashMap实现原理

1
2
3
采用Node + CAS + Synchronized来保证并发安全进行实现,
在JDK1.7中ConcurrentHashMap,数据结构上,首先整体上是数组+链表+红黑树的结构与HashMap保持一致,其次取消了Segment分段锁的数据结构,取而代之的是Node,Node的value和next都是由volatile关键字进行修饰,可以保证可见性。将细化的粒度从段进一步降低到节点。线程安全实现上,采用CAS+Synchronized替代Segment分段锁。
cas是比较再交换的算法

35、oracle多表连接的分类 内连接和外连接的区别

1
2
3
内连接  外连接  自连接   交叉连接
内连接会过滤不满足连接条件的记录
外连接会把主表的所有记录显示,如果关联表没有关联记录,全部显示空

36、oracle中常用的函数 分别介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
聚合函数
min() 取最小值
max() 取最大值
sum() 求和
avg() 求平均值
count() 求记录总数

数字格式化函数
round(数字,保留的小数位) 数字函数,会四舍五入
trunc(数字,截断的小数位) 数字函数,不会四舍五入,截断函数
mod() 求余数

字符串函数
upper() 转大写
lower() 转小写
concat 或者|| 字符串连接
substr() 字符串截取函数
lenght() 字符串长度
replace() 替换函数、
ltrim()去左边空格 rtrim() 去右边空格

转换函数(日期函数)
sysdate 返回当前系统时间,没有括号
to_char() 将日期转换成指定格式的字符串, 将数字格式化成指定格式的字符串
to_date() 将字符串转日期
last_day(sysdate) 返回date日期所在月份的最后一天日期

nvl(列名,默认值) 滤空函数

decode() 选择函数

37、行转列 列转行

1
2
3
4
5
6
7
8
9
10
11
12
13
--行转列
select name,
max(decode(course,'数学',score)) 数学,
max(decode(course,'英语',score)) 英语,
max(decode(course,'语文',score)) 语文
from tb_student group by name;
--列转行
select name,'语文' course,cn_score score from tb_student2
union
select name,'数学' course,math_score from tb_student2
union
select name,'英语' course,en_score from tb_student2;

38、oracle和mysql分页

1
2
3
4
5
6
7
oracle分页:
select * from
(select t1.*,rownum rn from
(select * from student) t1 where rownum<=6) t2 where t2.rn>4;

mysql分页:
select * from teacher limit 10,5;

39、oracle和mysql区别

1
2
3
4
1、mysql主键支持自增长,而oracle不支持,只能通过序列达到自增效果。
2、Mysql用limit做分页,oracle用rownum做分页
3、Oracle和 mysql的函数不同
4、oracle varchar2(3) 以字节为单位 mysql5.0.3开始 char varchar的数字都是以字符为单位

Mysql具有存储引擎的概念 常用MyISAM与InnoDB区别

名称 MyISAM InnoDB
事务处理 不支持 支持
数据行锁定 不支持 支持
外键约束 不支持 支持
全文索引 支持 不支持
表空间大小 较小 较大、约2倍

40、查询语句执行速度很慢 如何优化

1
2
3
4
5
6
7
8
9
10
1)SELECT子句中避免使用*号
2)多表连接时,使用表别名关联字段
3)多表连接查询时,将表与表之间的关联条件写在WHERE左边关联,WHERE右边再写过滤最大的条件
4)FROM子句中包含多个表的情况下,将表数据最少的表放在最后,因为数据库的解析器是按照从右到左的顺序处理FROM子句中的表数据,FROM子句中写在最后的表将被最先处理
5)模糊查询 like,like ‘关键字%’会走索引,如果使用like ‘%关键字%’ 和’%关键字’将全文索引
6)尽可能使用exists代替in,而对于连续的数据可以使用between就不要使用in和not in
7)单独使用Group By和Order by时,Group By和Order by的列尽可能要有索引,如果没有索引,执行过程中会产生临时表,如果Group By和Order by组合使用时如果条件列不一样,也会产生临时表降低效率。
8)对于insert的优化,可以从三个方面入手,插入单条数据时,将数据进行有序(根据索引的顺序)插入,插入多条数据时将数据合并到一条语句中执行,例如:
insert
对于批量插入多条数据可以使用事务进行插入处理。

41、 数据库三大范式

1
2
3
第一范式:确保每列的原子性
第二范式:确保表中的每列,都和主键相关
第三范式:确保每列都和主键列直接相关,而不是间接相关

42、创建表和修改表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
create table teacher(
tno number(4) not null,--设置教室编号和长度,内容不能为空
tname varchar2(10) not null, --教室姓名
tid char(18),--身份证号
gender char(2),--性别
birthdate date --出生日期
)
-- 添加列
alter table teacher add(
hiredate date, --入职日期
sal number(7,2), --薪水
wechat varchar2(20) --微信
)
-- 修改列
alter table teacher modify(tname varchar2(30))
-- 删除列 删除单列 删除多列
alter table teacher drop column wechat;
-- 删除多列
alter table teacher drop(birthdate,hiredate)

43、索引的作用?和它的优缺点是什么?

1
索引是一张特殊的查询表,可以加快查询速度,但是索引会减慢数据增删改的效率

44、什么样的字段适合建索引?

1
2
3
4
5
1、频繁搜索的列 (where tname)
2、经常排序、分组的列 (order by group by)
3、经常连接的列 (dept teacher deptno)
4、列的值不重复
5、列的值不经常做修改

Oracle中创建了索引,什么样的原因可能使索引不能正常使用?

1
2
3
4
5
6
7
8
9
10
1、列使用is null 和is not null  列的索引会失效
2、where子句对存在索引的列使用函数时,会使优化器忽略掉这些索引,但是把函数应用在条件上,索引可以生效
select * from staff where trunc(birthdate) = ‘01-MAY-82’; 会忽略索引
select * from staff where birthdate < (to_date(‘01-MAY-82’) + 0.9999); 索引生效
对于min和max函数,oracle仍然使用索引
3、模糊查询 like 'aaa%' 会用到索引
like '%aaa' %在前面不会使用索引
4、where子句使用不等于操作 <> != NOT colume>=? NOT colume<=?
5、等于和范围索引不会被合并使用
job和deptno都是非唯一索引,这种条件下oracle不会合并索引,它只会使用第一个索引

45、写一段jdbc代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl","ycy","m123");
String sql = "select * from teacher";
PreparedStatement statement=conn.prepareStatement(sql);
ResultSet rs = statement.executeQuery();
while(rs.next()){
int tno = rs.getInt("tno");
String tname = rs.getString("tname");
Date birthdate = rs.getTimestamp("birthdate");
System.out.println(tno+"==>"+tname+"==>"+birthdate);
}
rs.close();
statement.close();
conn.close():

46、PreparedStatement和Statement区别

1
2
3
1 PreparedStatement是预编译的sql语句
2 PreparedStatement可以防止sql注入

47、tomcat服务器文件夹下有哪些子文件夹,每个子文件夹的作用

1
2
3
4
5
6
7
bin:存放各种平台下用于启动和停止Tomcat的脚本文件
conf: 存放Tomcat服务器的各种配置文件
lib: 存放Tomcat服务器所需的各种jar文件
logs: 存放Tomcat的日志文件
temp: Tomcat运行时用于存放临时文件
webapps: 当发布web应用时,默认情况下会将web应用的文件存放于此目录中
work: Tomcat把由JSP生成的Servlet放于此目录下

48、一个web项目的基本目录结构

1
2
3
4
5
6
7
8
9
hello项目名
--xxx.html
--xxx.js
--xxx.css
--xxx.jsp
--WEB-INF(这个目录下的资源,浏览器不能直接访问)
--lib(存放项目用到的所有jar包)
--classes(存放java文件编译的class文件)
--web.xml(web项目的配置文件)

49、request对象的常用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
request是jsp内置对象 属于HttpServletRequest类型 封装了浏览器提交到服务器的所有请求数据
1、获取请求行的请求方式
String method = request.getMethod();
2、获取请求行的请求资源路径uri
String requestURI = request.getRequestURI();
3、获取完整的请求url
String requestURL = request.getRequestURL.toString();
4、获取请求头
String userInfo = request.getHeader("User-Agent");
5、获取请求体
String username = request.getParameter("username");
6、获取一组相同key的属性
String[] hobbies = request.getParameterValues("hobby");

50、jsp9大内置对象(********常问):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1、out(JspWriter):用来向客户端发送文本数据
方法:print 向客户端打印数据(将各种类型的数据转换成字符串)
write 向客户端打印数据(字符、字符数组、字符串)
println 向客户端打印数据(将鄂中类型的数据转换成字符串)并换行
2、config(ServletConfig):对应Servlet中的ServletConfig
3、page:当前jsp页面
4、pageContext(PageContext):代表page域的域对象
5、exception(Throwable):只有在错误页面中可以使用这个对象
6、request(HttpServletRequest):请求对象
方法:
setCharacterEncoding() (设置的是request内部保存数据的编码格式,不包括rul编码格式)。
getParameter(“userName”) 从请求体中获取指定的数据
getParameterValues(“no1”) (返回的是一个数组对象)
7、response(HttpServletResponse):响应对象
方法:sendRedirect(String location) (页面重定向)
RequestDispatcher对象的forward()方法 转发
8、application(ServletContext):代表整个web应用的域对象
方法:String getRealPath(String path) 返回相对路径的真实路径
Object getAttribute(String key) 通过key获取对象值
9、session(HttpSession):代表一次会话的域对象
方法:setAsetAttribute(String key,Object value):以key/value的形式保存对象值
getAttribute(String key):通过key获取对象值
setMaxInactiveInterval():设定session的非活动时间 单位是秒
invalidate():设置session对象失效

51、jsp执行过程

1
jsp先翻译成java文件 再编译成class文件 最后执行

52、get和post区别

1
2
3
4
1 get提交数据在地址栏  post在请求体
2 get不安全 post安全
3 get只能提交少量数据 post可以提交大量数据
4 get代表从服务器查询数据 post代表向服务器新增数据

53、转发和重定向区别

1
2
3
4
5
6
7
8
1 转发一次请求  重定向两次请求
2 转发地址栏不会变 重定向地址栏会变
3 转发只能访问内部资源 重定向可以访问外部资源
4 转发性能优于重定向

项目访问路径:request.getContextPath()
转发时写的路径,默认前面会加上项目访问路径 也就是 /aaa 所以转发路径不用写项目的虚拟路径直接写web下的文件夹
重定向写的路径就需要加上项目访问路径

54、当我在地址栏输入URL回车后 发生了什么

1
2
3
4
5
1、url经过域名解析得到服务器的ip地址
2、通过tcp的3次握手与服务器建立连接
3、通过http协议将请求数据发送到服务器
4、服务器处理完请求也是通过http协议将响应数据传递给浏览器
5、通过tcp的4次挥手将客户端和服务器端的连接断开

TCP HTTP 协议 UDP 协议

1
2
3
TCP是面向连接的通信协议,通过三次握手建立连接,通过tcp的4次挥手将客户端和服务器端的连接断开
http协议其实就是超文本传输协议,
UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。

55、request.getAttribute() 和 request.getParameter() 有何区别

1
2
3
4
request.getAttribute()是根据属性名从request域对象中获取对应的属性值
request.getParameter()是从浏览器提交的请求数据取值

相同点:获取不存在的key值都是返回null

56、什么是cookie cookie的作用 (一般不问)

1
2
3
4
5
cookie是一段文本,由服务器创建,浏览器保存,当浏览器每次请求服务器,都会将cookie归还服务器,由服务器使用。
作用:
免登录
显示上一次访问时间
历史记录

57、 session的原理

1
2
3
session是依赖Cookie实现的服务器端对象
当用户第一次请求服务器时,服务器会创建session,并创建一个Cookie,在Cookie中保存了session的id,发送给客户端。
当用户第二次访问服务器时,会在请求中把保存了sessionId的Cookie发送给服务器,服务器通过sessionId查找session对象,然后可以直接使用。也就是说,只要浏览器容器不关闭,无论访问服务器多少次,使用的都是同一个session对象。这样也就可以让多个请求共享同一个session了。

58、session和cookie的区别

1
2
3
1、session数据安全 cookie数据相对不安全
2、session数据存在服务器 cookie存在客户端浏览器
3、session可以存大量的数据 cookie大小有限制 一个cookie最大4kb

59、servlet生命周期 load-on-startup的作用

1
2
3
4
5
6
1 当浏览器第一次请求servlet时,服务器会自动创建servlet对象,然后继续调用init方法进行对象初始化
init方法调用一次 servlet是单例的
2 浏览器每次请求servlet,service方法就会执行一次,处理浏览器请求
3 当服务器关闭时,会调用一次destroy释放资源

当load-on-startup取值>=0时,服务器启动时就创建servlet对象

60、cookie完成5分钟免登录(只需要月考之前背)(一般不问)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//login.jsp
Cookie[] cookies = request.getCookies();
if (cookies!=null){
for (Cookie c : cookies) {
if ("username".equals(c.getName())){
response.sendRedirect(request.getContextPath()+"/request/index.jsp");
}
}
}

//dologin.jsp
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
String unlogin = request.getParameter("unlogin");

if ("admin".equals(username)&&"m123".equals(pwd)){
//用户名和密码正确
if(unlogin!=null){
Cookie cookie=new Cookie("username",username);
cookie.setMaxAge(60*5);
response.addCookie(cookie);
}
//登录成功一定是通过重定向去index.jsp
response.sendRedirect(request.getContextPath()+"/request/index.jsp");
}

61、jsp页面传递数据的方式?

1
1 form表单 2  域对象  3 超链接  4  cookie  5 <jsp:param>

62、jsp 四大域和每个域数据的使用范围

1
2
3
4
page域   数据只能在当前页面使用
request域 数据在一次请求中使用
session域 数据在一次会话中使用
application域 数据在整个web应用都可以使用

63、tomcat容器是如何创建servlet类实例?用到了什么原理?(一般不问)

1
当容器启动时,会读取在webapps目录下所有的web应用中的web.xml文件,然后对 xml文件进行解析,并读取servlet注册信息。然后,将每个应用中注册的servlet类都进行加载,并通过 反射的方式实例化

64、JDBC中的CLOB和BLOB数据类型是什么 (一般不问)

1
2
字符大对象(CLOB)是由具有关联代码页的单字节字符组成的字符串。此数据类型适用于存储面向文本的信息,最大容量4G
二进制大对象(BLOB)是由字节组成的二进制字符串,没有关联的代码页。此数据类型适用于存储图像,语音,图形和其他类型的业务数据。最大容量4G

65、jsp静态包含和动态包含的区别

1
2
include指令是静态包含  会将多个jsp合并成一个jsp,翻译成一个java文件,编译成一个class文件
include标签是动态包含 将每个jsp各自生成java文件,编译成class文件,然后在当前jsp调用另外一个jsp

66、jsp 9大内置对象

1
2
3
4
5
6
7
8
9
out(JspWriter):用来向客户端发送文本数据;
config(ServletConfig):对应Servlet中的ServletConfig;
page :当前JSP页面
pageContext(PageContext):代表page域的域对象;
exception(Throwable):只有在错误页面中可以使用这个对象;
request(HttpServletRequest):请求对象;
response(HttpServletResponse):响应对象;
application(ServletContext):代表整个web应用的域对象;
session(HttpSession):代表一次会话的域对象

67、(一般不问)连接池是什么? 它的好处是什么

1
2
3
连接池是装有连接的容器,使用连接的话,可以从连接池中进行获取,使用完成之后将连接归还给连接池
优点:
连接对象创建和销毁是需要耗费时间的,由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。

68、装饰者模式

1
2
3
4
5
6
7
8
9
10
是你   还有你   一切拜托你
1 装饰类和目标类继承同一个类或者实现同一个接口
2 装饰类内部包含目标类的成员变量(父类类型)
3 不需要增强的方法全部直接调用目标类的方法
需要增强的方法进行方法重写

在什么地方使用过装饰者模式?
使用缓冲流
数据库连接池
用装饰者模式做过一个敏感字符的过滤器

工厂模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
pulbic class FactoryBean{
C c;
public static C getBean(String type){
if(type.equals(“1”)){
c=getA();
}else{
c=getB();
}
return c;
}
public static void getA(){
return new B();
}
public static void getB{
return new B();
}
}
class C{
}
class B extends C{
}
class A extends C{
}

public class DrinkFactory{
Drink drink;
public static Drink getDrink(String type){
if(type == null){
return null;
}
if("coffee".equals(type)){
drink = new Conffee();
}else if("milk".equals(type)){
drink = new Milk();
}
return drink;
}
}

69、什么是mvc设计模式 每个部分使用的技术

1
2
3
controller 控制器 负责接收用户请求,调用视图显示数据 servlet  springmvc
model 模型 负责处理用户请求,将结果返回控制器 hibernate mybatis
view 视图 负责显示数据 jsp html

70、事务是什么? jdbc控制事务的模板?

1
2
3
4
5
6
7
8
9
10
11
事务可以确保一组sql语句要么全部成功,要么全部失败。
Connection conn=DriverManager.getConnection("url","用户名","密码");
try{
conn.setAutoCommit(false);
update-1
update-2
conn.commit();
}catch(Exception ex){
conn.rollback();
}

71、过滤器(Filter)怎么执行的(一般不问)

1
首先初始化过滤器 ,然后所有的请求需要经过一个一个的过滤器,执行顺序要根据web.xml里配置的<filter-mapping>的位置前后执行,每个过滤器之间通过chain.doFilter连接, 最后抵达真正请求的资源

72、敏感字符过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
public MyRequest(HttpServletRequest request) {
super(request);
this.request=request;
}
@Override
public String getParameter(String name) {
List<String> list=new ArrayList<String>();
list.add("坏蛋");
String value = request.getParameter(name);
if (value!=null){
for (String s : list) {
if (value.contains(s)){
value=value.replaceAll(s,"*");
}
}
}
return value;
}
}

public class WordFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request=(HttpServletRequest)req;
MyRequest myRequest=new MyRequest(request);
filterChain.doFilter(myRequest,res);
}
}

73、什么是脏读 不可重复读 幻读 解决方法?

1
2
3
4
5
6
脏读:  一个事务读取到另外一个事务未提交数据
将事务隔离级别设置读已提交(oracle数据库的默认隔离级别)
不可重复读: 一个事务对同一条记录的2次读取不一致,因为另外一个事务中间对记录进行了修改
设置可重复读的隔离级别(mysql数据库的默认隔离级别)
幻读: 一个事务对一张表的2次查询不一致,因为另外一个事务中间对表进行了插入或者删除
设置串行化的隔离级别

74、事务的四大特性是:(概念性问题–面试)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
原子性(Atomicity):
事务中所有操作是不可再分割的原子单位。
*事务中所有操作要么全部执行成功,要么全部执行失败。
一致性(Consistency):
*事务执行后,数据库状态与其它业务规则保持一致。
如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
隔离性(Isolation):
*隔离性是指在并发操作中,不同事务之间应该隔离开来,
使每个并发中的事务不会相互干扰。
持久性(Durability):
*一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,
即使提交事务后,数据库马上崩溃,
在数据库重启时,也必须能保证通过某种机制恢复数据。

原子性:事务中所有操作要么全部执行成功,要么全部执行失败。

一致性:事务执行后,数据库状态与其它业务规则保持一致。
如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。

隔离性:在并发操作中,不同事务之间应该隔离开来

持久性:一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中

75、编码过滤器(需要用语言说出来)

1
2
3
4
5
6
7
8
public class EncodingFilter implements Filter {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}

}

敏感字符过滤器(需要用语言说出来)

1
2
3
4
先定义一个类继承HttpServletRequestWrapper类
再声明HttpServletRequest成员变量,通过构造方法赋值
重写父类的getParameter方法,先拿到目标对象getParameter获取的原始值,过滤敏感字符,将结果返回
再声明一个过滤器类,创建装饰类对象,对目标request进行包装,传入filterChain的doFilter方法

76、已知有两个集合,要求在jsp中通过jstl遍历用户数据和用户对应部门的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Huser属性id username password createtime did
Hdept属性id deptName
did是 Huser 关联Hdept的外键
List<Huser> listUser=new ArrayList<>();
List<Hdept> listDept=new ArrayList<>();
数据假设已经存入集合
request.setAttribute("listUser",listUser);
request.setAttribute("listDept",listDept);

<c:forEach items="${listUser}" var="user">
${user.id}==>${user.username}==>
<fmt:formatDate value="${user.createtime}" pattern="yyyy-MM-dd">
==>
<c:forEach items="${listDept}" var="dept">
<c:if test="${user.did==dept.id}" >${dept.deptName}</c:if>
</c:forEach>
</c:forEach>

77、跨域

1
2
如果请求的url跟当前的url 协议 端口号任意一个不同,就属于跨域
百度服务器能接收到请求,也能响应浏览器,但是浏览器拦截数据,不会显示,需要进行跨域设置(在服务器设置响应头,通知浏览器允许接收数据,不要拦截)

78、cookies、sessionStorage和localStorage解释及区别

1
2
3
4
5
6
Cookie
Cookie 是小甜饼的意思。顾名思义,cookie 确实非常小,它的大小限制为4KB左右。它的主要用途有保存登录信息,比如你登录某个网站市场可以看到“记住密码”,这通常就是通过在 Cookie 中存入一段辨别用户身份的数据来实现的。
localStorage
localStorage 是 HTML5 标准中新加入的技术,它并不是什么划时代的新东西。早在 IE 6 时代,就有一个叫 userData 的东西用于本地存储,而当时考虑到浏览器兼容性,更通用的方案是使用 Flash。而如今,localStorage 被大多数浏览器所支持,如果你的网站需要支持 IE6+,那以 userData 作为你的 polyfill 的方案是种不错的选择。
sessionStorage
sessionStorage 与 localStorage 的接口类似,但保存数据的生命周期与 localStorage 不同。做过后端开发的同学应该知道 Session 这个词的意思,直译过来是“会 话”。而 sessionStorage 是一个前端的概念,它只是可以将一部分数据在当前会话中保存下来,刷新页面数据依旧存在。但当页面关闭后,sessionStorage 中的数据就会被清空。
特性 Cookie localStorage sessionStorage
数据的生命期 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 除非被清除,否则永久保存 仅在当前会话下有效,关闭页面或浏览器后被清除
存放数据大小 4K左右 一般为5MB 一般为5MB
与服务器端通信 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 仅在客户端(即浏览器)中保存,不参与和服务器的通信 仅在客户端(即浏览器)中保存,不参与和服务器的通信
易用性 需要程序员自己封装,源生的Cookie接口不友好 源生接口可以接受,亦可再次封装来对Object和Array有更好的支持 源生接口可以接受,亦可再次封装来对Object和Array有更好的支持

sessionStorage的使用:

1
2
3
4
5
6
7
8
9
10
//获取sessionStorage对象
var storage = window.sessionStorage;
//保存数据语法:
sessionStorage.setItem("key", "value");
//读取数据语法:
var lastname = sessionStorage.getItem("key");
//删除指定键的数据语法:
sessionStorage.removeItem("key");
//删除所有数据:
sessionStorage.clear();

79、maven的作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1、依赖管理(对项目依赖的jar包进行管理)
2、一键构建项目

maven工程的目录结构
项目名
--src
-- main
--java (存放所有的java源码)
--resources (存放项目的xml配置文件)
--webapp (存放静态资源 css js 图片 html jsp web项目才有)
---test
-- java (存放测试类)
-- resources(存放测试需要的配置文件 一般为空)
-- pom.xml 存储需要jar包的坐标.

maven坐标的主要组成
groupId:定义当前maven项目属于哪个项目
artifactId:定义实际项目中的某一个模块
version:定义当前项目的当前版本
packaging:定义当前项目的打包方式

bin:存放了maven 的命令,比如mvn tomcat:run
boot:存放了一些maven 本身的引导程序,如类加载器等
conf:存放了maven 的一些配置文件,如 setting.xml 文件
lib:存放了maven 本身运行所需的一些jar 包
根据这些坐标,在maven库中可以找到唯一的jar包
maven的作用:
依赖管理
项目的一键构建

创建maven的web项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1、pom.xml删除多余的代码
2、补齐4个文件夹,设置文件夹类型
3、webappp/WEB-INF/web.xml
换跟标签的头部

clean(清理):删除整个target文件夹

maven的默认生命周期 每个生命周期对应一个maven命令
每次执行指定的生命周期命令,都会从第一个命令Compile开始,一直运行到指定命令结束

Compile(编译):
将src/main/java下面的所有java文件编译成class文件,将结果输出到target文件夹
test(测试):
将src/test/java下面的所有测试类编译成class文件,将结果输出到target文件夹,同时会运行测试类中所有@Test修饰的测试方法
package(打包)
将整个maven工程按照pom.xml的 <packaging></packaging>标签配置进行打包,如果写jar,那么就打jar包,如果写war包,那么就打war包
一般java工程打jar包,web项目打war包
install(安装)
将maven项目打包后放入本地仓库,其他项目通过坐标引入jar包

80、hibernate的开发步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//1 加载hibernate配置文件
//configure() 默认读取src下的hibernate.cfg.xml
//src/main/java 和 src/main/resource都代表src根目录
//运行时会合并成一个目录
Configuration configure = new Configuration().configure();
//2 创建SessionFactory
SessionFactory sessionFactory = configure.buildSessionFactory();
//3.创建session对象
Session session = sessionFactory.openSession();
//4 开启事务
Transaction transaction = session.beginTransaction();
//5 对数据库增删改查
HUser hUser = new HUser();
hUser.setName("漂流记");
hUser.setPassword("m123");
hUser.setCreatetime(new Date());
session.save(hUser);
//6 提交事务
transaction.commit();
//7 关闭session
session.close();

81、hibernate中get和load的区别

1
2
3
4
5
1、
get是立即查询
load支持延迟加载,使用对象的时候查询数据库
2、
如果根据主键查询不到数据 get返回null load抛异常ObjectNotFoundException

82、什么是Hibernate延迟加载。

1
Hibernate从数据库获取某一个对象数据时,由于没有使用该对象的数据(除标识符外),Hibernate只是为该对象创建一个代理对象,这个对象上的所有属性都为默认值;只有在真正需要使用该对象的数据时才创建这个真正的对象,真正从数据库中加载它的数据。

83、hibernate一级缓存和二级缓存

1
2
3
4
1 一级缓存是session级别的缓存,同一个session发送2条相同的sql语句,第二次查询不会查询数据库,
直接从一级缓存获取数据。
2 二级缓存是SessionFactory级别的缓存,同一个SessionFactory打开的所有session共享一个二级缓存
当查询数据时,先查一级缓存,如果没有数据再查二级缓存,如果还没有数据最后查询数据库。

mybatis一级缓存和二级缓存的区别

1
2
3
4
5
一级缓存是sqlsession级别 同一个sqlsession中 发送2次相同的sql语句
第二次不再从数据库查询 直接由一级缓存返回数据

二级缓存是mapper的namespace级别 相同的namespace共享一个二级缓存
查询数据时先查二级缓存 在查一级缓存 最后查数据库

84、hibernate查询方式

1
2
3
4
5
1 oid方式
2 hql语句
3 sql语句
4 qbc查询
5 对象导航查询

85、hibernate对象的三种状态

1
2
3
1 瞬时态(临时态) 刚刚new出来的对象
2 持久态 通过session.save()将对象存入数据库,对象由瞬时态转换持久态
3 游离态 通过session.close()关闭session,对象由持久态转换游离态

86、什么是悲观锁和乐观锁

1
2
3
4
5
6
7
8
9
10
悲观锁
可以通过for update实现
当一个事务获取数据时,认为其他事务会操作同一条记录,所以这个事务会对记录锁定,
只有当这个事务提交时,其他事务才允许对记录进行操作

乐观锁
可以通过版本号version实现,
当查询数据时,将数据版本号version一起查询,当执行update语句时,在update语句的where部分将自己的version和数据库中的version做匹配,
匹配成功,数据库的version加1
匹配失败,更新失败

什么是hibernate和mybatis悲观锁和乐观锁

1
2
3
4
5
6
悲观锁:
hibernate自动在select最后生成for update
mybatis需要在select最后手写for update
乐观锁
hibernate配置version列 version属性 version标签 在update修改时 where条件 会自动有version判断
mybatis配置version列 version属性 在update修改时 where条件手写version判断

87、 mybatis #{} ${}区别

1
2
1 #{} 占位符 会生成jdbc的? 避免sql注入
2 ${} 拼接符 做字符串的连接 不能避免sql注入

分页流程

1
2
3
4
5
6
7
8
9
10
11
没使用框架:
前端传的数据是查询的页码以及每页条数
后台定义一个PageBean 里面数据有 1、当前页码2、每页条数3、总记录数4、总页数5、当前页数据
前端传到service,service传到dao,在dao中先声明pageBean对象
先存入当前页码和每页条数,然后查询出总记录数以及需要返回的数据,总页数会在PageBean自动计算
最后将pageBean对象返回
使用mybatis框架的pagehelper的分页插件:
需要先导入分页插件(spring的话还需要写一个分页插件的配置文件,springboot可以直接使用)
前端传查询的页码以及每页条数到service
service先写通过PageHelper.startPage(pageNum, pageSize);设置
返回的时候new一个PageInfo对象,第一个参数为查询的list集合的数据,第二个参数设置页码数量,默认为8

88、mybatis动态mapper的实现原理?mapper接口中的方法能不能重载?

Mybatis中通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么??Dao接口里的方法,参数不同时,方法能重载吗?

1
2
Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。
Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。

89、 mybatis的多对一和一对多如何实现?

1
2
多对一使用association标签
一对多使用collection标签

90、Hibernate和Mybatis的区别

1
2
3
1  Hibernate自动生成sql   Mybatis需要手写sql
2 Hibernate数据库无关性好 mybatis无法做到数据库无关性,不同的数据库需要写不同SQL。
3 Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。

91、动态代理区别

1
2
jdk动态代理(难度高) 基于接口产生代理对象
cglib动态代理 基于目标类产生代理对象 基于子类代理

92、spring能帮我们做什么事情 (什么是spring)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
spring包含ioc和aop2大功能
ioc是控制反转 将对象的创建交给spring容器
di是依赖注入 给对象中的属性赋值
常用的依赖注入有3种
1 set注入
2 构造注入
3 注解注入 使用resource和autowired2个注解

aop是面向切面编程 可以实现不修改源码的情况下给程序动态添加功能
底层依赖于jdk动态代理和cglib动态代理,如果目标类实现了接口,优先使用jdk动态代理
aop有5种通知
1 前置通知
2 后置通知
3 最终通知
4 异常通知
5 环绕通知
可以使用aop做日志功能,将程序的运行信息记录到log日志文件

93、请写出在applicationContext.xml中创建package1.DestBean对象放入IOC容器并且注入sourceBean对象的代码.(手写纸上)

1
2
3
4
5
<bean id="sourceBean" class="package1.SourceBean">
</bean>
<bean id="destBean" class="package1.DestBean">
<property name="sourceBean" ref="sourceBean"></property>
</bean>

94、Spring的两种代理JDK和CGLIB的区别

1
2
3
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
1
2
3
4
5
代理模式:
1、代理类和目标类实现同一个接口
2、代理类内部声明目标类(父类类型)的成员变量
和增强类的成员变量
3、在代理对象的代理方法调用目标类的目标方法和增强类的增强方法

95、Spring中的设计模式有哪些

1
2
3
4
5
6
1. 工厂模式  	
2. 单例模式
3. 适配器模式
4. 代理模式
5. 模板模式
6. 策略模式

96、Resource和Autowired注解的区别

1
2
3
4
Resource注解如果有name属性 将name属性的值当做对象id从spring容器中查找对象
如果没有name属性,以属性名作为对象id查找对象,如果找不到对象,继续按照属性的类型查找

Autowired注解是按照属性的类型查找

98、IOC是什么,DI是什么?

1
2
3
4
5
6
7
8
9
10
ioc 控制反转 负责创建对象  将对象的创建权交给spring容器管理
di 依赖注入 负责给对象中的属性赋值
1 set注入
需要给属性提供set方法 使用set方法给属性赋值
2 构造注入
3 注解注入 有resource和autowired 2个注解
4 c命名空间,p命名空间
IOC:就是对象之间的依赖关系由容器来创建,对象之间的关系本来是由我们开发者自己创建和维护的,在我们使用Spring框架后,对象之间的关系由容器来创建和维护,将开发者做的事让容器做,这就是控制反转。BeanFactory接口是Spring Ioc容器的核心接口。
DI:我们在使用Spring容器的时候,容器通过调用set方法或者是构造器来建立对象之间的依赖关系。
控制反转是目标,依赖注入是我们实现控制反转的一种手段。

99、 什么是aop?有几种通知?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
aop是面向切面编程,可以在不修改源代码的基础上给程序动态添加功能
aop底层是依赖jdk动态代理和cglib动态代理,如果目标类实现接口,优先使用jdk动态代理
5种通知:
1 前置通知 在目标方法之前运行
2 后置通知 在目标方法之后运行
3 最终通知 在目标方法之后运行,发生异常最终通知也会运行
4 异常通知 发生异常后运行
5、环绕通知 等于以上4种通知
你用aop做过什么?(日志) 最重要
通过aop的环绕通知,在目标方法执行之前可以记录用户的请求地址 请求方式
请求的类名和方法以及用户传递过来的请求数据以及目标方法执行的开始时间
当目标方法执行之后,还记录了目标方法的返回结果和目标方法的结束时间

定义aop的常用注解:
@Aspect:作用是把当前类标识为一个切面供容器读取

@Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice
@After: final增强,不管是抛出异常或者正常退出都会执行

100、创建jdk动态代理对象

1
2
3
4
5
6
7
8
Proxy.newProxyInstance(ClassLoader classLoader,Class[] interfaces,InvocationHandler接口);
三个参数:
1、ClassLoader类加载器
动态代理会自动生成一个代理类,也需要加载到方法区内存 也需要ClassLoader
①自动生成的代理类在磁盘上有没有对应的class文件? 没有
2、一组接口 Class[] interfaces
3、InvocationHandler接口 处理方法 当调用代理对象的所有方法时,
都是调用InvocationHandler的invoke()

101、 spring mvc工作流程 参考课件

1
2
3
4
5
6
7
8
9
10
11
1、用户发送请求至前端控制器DispatcherServlet
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
5、执行处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、DispatcherServlet将ModelAndView传给ViewResolver视图解析器
9、ViewReslover解析后返回具体View
10、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户

102、Mybatis 如何防止 sql 注入?mybatis 拦截器了解过吗,应用场景是什么?

1
2
3
4
mybatis使用#{}防止sql注入。 
Mybatis拦截器只能拦截四种类型的接口:Executor、StatementHandler、
ParameterHandler和ResultSetHandler。Mybatis 可以对这四个接口中所有的方法进行拦截。
Mybatis拦截器常常会被用来进行分页处理。

103、fastdfs

1
文件服务器,可以自己搭建使用

104、什么是Ajax和JSON,它们的优缺点?

1
2
3
4
5
ajax是异步的JavaScript和xml,用于在Web页面中实现异步数据交互,实现页面局部刷新。
优点:可以使得页面不重载全部内容的情况下加载局部内容,降低数据传输量,避免用户不断刷新或者跳转页面,提高用户体验

JSON是一种轻量级的数据交换格式
优点:轻量级、易于人的阅读和编写,便于机器(JavaScript)解析,支持复合数据类型(数组、对象、字符串、数字)

105、简述ajax的执行过程?

1
2
3
4
1 创建XMLHttpRequest对象
2 执行open,设置请求方式,请求url,是否异步
3 执行send发送请求
4 绑定事件 根据请求状态(4代表已完成)和服务器响应状态(200),处理结果

106、ajax请求时,如何解释json数据?

1
使用eval() 或者JSON.parse()

107、ajax的最大的特点是什么

1
ajax可以实现异步通信效果,实现页面局部刷新,带来更好的用户体验,还可以按需获取数据,节约带宽资源

108、Spring支持几种类型的事务管理?

1
2
3
4
5
6
7
8
9
10
1 编程式事务: 
对于编程式事务管理,
简单的说就是在代码中需要直接加入处理事务的逻辑,
可能需要在代码中显式调用beginTransaction() commit() rollback()
等事务管理相关的方法,如在执行a方法的时候需要事务处理,
你需要在a方法开始时候开启事务,处理完成之后,在方法结束的时候,关闭事务.
2 声明式事务:
spring倡导的非侵入式的开发方式.声明式事务管理使业务代码不受污染,
有两种常用的方式,一种是基于tx和aop命名空间的xml配置文件,
另一种就是基于@Transactional注解.

109、spring事务传播特性有哪些?

1
2
3
4
5
6
7
required 支持当前事务,如果不存在就新建一个(默认)
requires_new 如果有事务存在,挂起当前事务,创建一个新的事务
supports 支持当前事务,如果不存在,就不使用事务
not_supported以非事务方式运行,如果有事务存在,挂起当前事务
nested如果当前事务存在,则嵌套事务执行
mandatory支持当前事务,如果不存在,抛出异常
never 以非事务方式执行,如果有事务存在,抛出异常

110、什么是JSONP和CORS,它们的区别是什么?

1
2
3
4
5
Jsonp和CORS是用来解决跨域访问的解决方案.
JSONP的原理是动态创建script标签, CORS是跨域资源共享,需要在服务器端设置CORS配置
1.1. JSONP发送的不是ajax请求, CORS发送的是真正的ajax请求
1.2. JSONP不支持post请求, CORS支持
1.3. JSONP没有兼容问题, CORS有兼容问题,只有ie10和谷歌火狐等浏览器才支持

111、角色类Role有属性(roleId, roleName) , 用户类User有属性(name,age,role) 写出一个List对象转换后的json字符串. 集合中至少包含一个用户和一个角色.

1
[{“name”:”张三”,”age”:18, “role”: {“roleId”: 1, “roleName”:”管理员”}}]

112、springmvc注解

1
2
3
4
5
6
7
8
9
1.@Controller 写在类上,标记为控制器类
2.@RequestMapping 用来处理请求地址映射的注解
3.@ResponseBody 表示该方法的返回结果直接写入HTTP response body中。一般在异步获取数据时使用
6.@RequestParam 用于将请求参数区数据映射到功能处理方法的参数上 还可以设置默认值
@RequestBody 前端json对象转类对象
@Value从配置文件取值
@PathVaribale注解 用于绑定url中的占位符
4.@Autowired 做bean的在注入时使用
5.@Resource 做bean的在注入时使用

controller和RestController的区别

1
restController等于controller+responseBody

113、springmvc怎么做文件上传

1
2
3
4
5
6
7
8
9
10
11
1 input type="file"
2 method = "post"
3 enctype = "multipart/form-data"

后台
声明MultipartFile参数接收上传的文件,MultipartFile是接口需要先在配置文件中先声明实现类
1 准备uuid当做新的文件名
2 取出上传文件名的后缀 ext
3 准备上传路径 如果路径不存在 创建出来
4 文件上传 pic.transferTo(new File(path,uuid+"."+ext));
5 将新的文件名存入对象 插入数据库

oss实现文件上传流程介绍

1
2
3
4
5
6
7
前端只传后端签名
1、web前端请求应用服务器,获取上传所需参数(如oss的accessKeyId、policy、callback等参数)
2、应用服务器返回相关参数
3、web前端直接向oss服务器发起上传文件请求
4、等上传完成后oss服务会回调应用服务器的回调接口
5、应用服务器返回响应给oss服务
6、oss服务将应用服务器回调接口的内容返回给web前端

114、你对springboot的理解

1
2
3
4
5
6
springboot 是一个快速开发的框架。其采用注解的配置方式,简化了XML配置.并且内置web服务器(tomcat) , 还能够通过自动装配快速整合其他框架,降低了框架整合复杂度,真正开箱即用。

优点:
a. 是一个快速开发的框架。其采用注解的配置方式,简化了XML配置.
b.内置web服务器(tomcat),无需部署war文件 它是java项目 打成jar 包 java -jar XXX.jar
c. 简化了maven配置,其内部封装大部分的主流框架依赖 自动装配spring

115、什么是restful

1
2
3
4
5
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询。

116、redis的数据类型有哪些

1
2
3
4
5
1) 字符串类型 string
2) 哈希类型 hash
3) 列表类型 list
4) 集合类型 set
5) 有序集合类型 sortedset(zset)

117、redis的持久化机制

1
2
3
1、RDB:默认方式,不需要进行配置,默认就使用这种机制
* 在一定的间隔时间中,检测key的变化情况,然后持久化数据
2、AOF:日志记录的方式,可以记录每一条命令的操作。可以每一次命令操作后,持久化数据

redis的应用场景

1
2
3
4
5
6
7
•   缓存(数据查询、短连接、新闻内容、商品内容等等)
• 聊天室的在线好友列表
• 任务队列。(秒杀、抢购、12306等等)
• 应用排行榜
• 网站访问统计
• 数据过期处理(可以精确到毫秒
• 分布式集群架构中的session分离

118、 NOSQL和关系型数据库比较

1
2
3
关系型数据库与NoSQL数据库并非对立而是互补的关系,即通常情况下使用关系型数据库,在适合使用NoSQL的时候使用NoSQL数据库,
让NoSQL数据库对关系型数据库的不足进行弥补。
一般会将数据存储在关系型数据库中,在nosql数据库中备份存储关系型数据库的数据

119、ajax技术体系的组成部分有哪些

1
2
3
4
5
6
-- html  做题时不选
css
dom
xml
xmlHttpRequest 核心对象 根据它来发送ajax请求(js的内置对象)
javaScript

120、项目衍进流程:

1
2
3
4
5
1、单体架构 所有的功能集中一个项目
2、分布式架构 按照功能拆分成多个子系统,每个子系统还是包含完整的三层架构
3、soa面向服务的架构,把工程拆分成服务层和表现层2层
表现层只负责接收用户请求,然后调用服务层查询数据库处理请求
4、微服务

自动生成接口文档

1
2
3
项目继承swagger插件
swagger文档
回去自学

正向代理与反向代理

1
2
3
4
5
6
7
8
正向代理有什么用为什么要这么做:
作用:正向代理隐藏了用户,用户的请求被代理服务器接收代替,到了服务器,服务器并不知道用户是谁。
用途:当你用浏览器访问国外的网站时,被block(拒绝)时,你可以在国外搭建一个代理服务器,这样就可以正常访问了(只是举一个列子)
反向代理有什么用为什么要这么做:
作用:用户请求过多,服务器会有一个处理的极限。所以使用反向代理服务器接受请求,再用均衡负载将请求分布给多个真实的服务器。既能提高效率还有一定的安全性。
用途:如果不采用代理,用户的IP、端口号直接暴露在Internet(尽管地址转换NAT),外部主机依然可以根据IP、端口号来开采主机安全漏洞,所以在企业网,一般都是采用代理服务器访问互联网。
正向代理与反向代理最简单的区别:
正向代理隐藏的是用户,反向代理隐藏的是服务器

gc垃圾回收

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1 什么是GC
程序运行时,内存空间是有限的,如何及时的把不再使用的对象清除,将内存释放出来,这就是GC要做的事

2 需要GC的内存区域
jvm有5块内存
其中程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理
因此,我们的内存垃圾回收主要集中于 java 堆和方法区


3 GC的对象
需要进行回收的对象就是已经没有存活的对象,比如这个对象在栈中没有任何变量引用

4 gc的触发时机
(1)程序调用System.gc()时可以触发

(2)系统自身来决定GC触发的时机(根据Eden区和From Space区的内存大小来决定。当内存大小不足时,则会启动GC线程并停止应用线程)

GC的核心算法
1、标记清除法/标记压缩法
2、复制收集算法
3、引用计数法

事务处理

1
2
3
4
5
一次操作更新或修改多张表,一般为了保证数据一致,需要增加事务处理
在项目中创建一个TransactionManagementConfig类,开启基于注解的事务管理对@Transactional
总结:在@Transactional注解中,如果不配置rollbackFor属性,那么事务只会在遇到RuntimeException的时候才会回滚,如果加上rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚
小节:自定义异常一般可以选择继承RuntimeExceptioin
如果发生检查异常Exception时,想让事务正常回滚,可以进行配置:@Transactional(rollbackFor = Exception.class)
1
2
3
4
5
6
7
8
9
10
package com.sc.springcloud.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement
@Configuration
public class TransactionManagementConfig {
}

Springmvc和spring的区别

1
2
Springmvc是控制层,用来接收前台传值,调用service层和持久层,返回数据再通过springmvc层把数据返回到前台。
Spring是框架的粘合剂,有ioc控制反转依赖注入和aop面向切面编程

反射

IO流

多线程

git

shiro

shiro+jwt+redis - 无状态token登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
权限管理框架
可以帮助我们完成:
身份认证/登录:验证用户是不是拥有相应的身份;
授权(权限验证):验证某个已认证的用户是否拥有某个权限;即判断用
户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用
户对某个资源是否具有某个权限;
加密:保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
会话管理:用户登录后就是一次会话,在没有退出之前,它的所有信
息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的
Web 集成
缓存:比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了
做到快速开发,降低系统成本
shiro相比于spring security,spring security依赖spring运行,而shiro相对独立,最主要的是因为shiro使用简单、灵活,所以现在越来越多的用户选择shiro。

rabbitMQ(消息队列 kafka)

1
2
3
4
5
6
7
8
9
10
11
12
应用场景:
1、任务异步处理。
将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。提高了应用程序的响应时间。
比如注册完成之后,可以通过消息队列,异步的发送短信以及邮件给注册成功的用户提示已注册成功
2、应用程序解耦合
MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合。

为什么使用RabbitMQ呢?
1、使用简单,功能强大。
2、基于AMQP协议。
3、社区活跃,文档完善。
4、高并发性能好,这主要得益于Erlang语言。 5、Spring Boot默认已集成RabbitMQ
1
2
3
4
5
6
7
8
9
10
11
12
13
总结:
、发送端操作流程
1)创建连接
2)创建通道
3)声明队列
4)发送消息
2、接收端
1)创建连接
2)创建通道
3)声明队列
4)监听队列
5)接收消息
6)ack回复

工作模式

1
2
3
4
5
6
7
RabbitMQ有以下几种工作模式 :
1、Work queues 工作队列
2、Publish/Subscrib 发布订阅
3、Routing 路由
4、Topics 通配符
5、Header Header转发器
6、RPC 远程过程调用

前后端分离项目中的日期格式化

1
2
3
4
5
数据库查询的时间返回给前端:
1、给字段添加注解 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
2、application.properties中进行全局配置
spring.jackson.date-format=yyyy-MM-dd
前端数据传到后台数据对象的属性上 加:@DateTimeFormat(pattern = "yyyy-MM-dd")

netflix(网飞)

eureka服务注册与发现

1
2
eureka做服务注册与服务发现功能的    生活举例   相当于卖房过程中的房产中介
卖房的人将房产信息注册到中介,买房的人通过中介发现卖房人信息,最终根据卖房人信息找到卖房人继续完成后续操作

ribbon负载均衡服务

1
客户端负载均衡 基于eureka的服务发现根据微服务名找到服务提供者的list集合,在通过IRule的负载均衡规则在list集合中选择一台服务提供者,根据ip和端口号进行远程调用

OpenFeign服务接口调用

1
远程服务接口调用,Feign是一个声明式WebService客户端,使用Feign能让编写web Service客户端更加简单,它的使用方法就是定义已给接口,然后再上面添加注解,OpenFeign是springcloud在Feign的基础上支持了SpringMVC的注解,如@RequesMapping等等,OpenFeign的@FeignClient可以解析SpringMVC的@RequestMappinig注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务

Hystrix断路器

1
2
3
4
5
6
7
8
用于服务降级和服务熔断
在分布式应用中存在服务雪崩效应,服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。
例如:A是服务提供者,B依赖于A,而C和D又依赖于B,如果A出现故障会导致B出现问题,并且将问题扩大到C和D,雪崩效应就形成了
解决方法
1 服务降级
如果A服务器出现故障,可以返回一个备用信息,做服务降级,这样B不用一直等待A的结果,可以正常做其他事情
2 服务熔断
当在一定的时间内,发出的请求次数达到的熔断要求的请求总数,并且错误百分比也到达了设定值,将断路器打开,这时所有的请求直接拒绝,返回降级信息。当一段时间过后,断路器进入半开状态,将一条请求放行,如果响应正常,断路器关闭,否则断路器重新进入打开状态。

Geteway网关

1
2
是一个网关  
在微服务架构中,后端服务不会直接开放给调用端,而是通过一个API网关比如gateway根据请求的url,路由到相应的服务工程。当添加API网关后,由API网关直接与调用方通信进行权限控制,后将请求均衡的分发给后台服务端。

代码生成器

mybatis-plus

1
2
3
4
5
6
7
8
9
10
11
12
version(乐观锁)、deleted(逻辑删除)、gmt_create、gmt_modified
lombok注解
@Date
@AllArgsConstructor
@NoArgsConstructor
实体类注解:
@TableI(type=Idtype.) 标识为主键 一般设置ASSIGN_ID 雪花算法
@TableField(fill = FieldFill.INSERT) 表示表的字段 数据插入时操作
@TableField(fill = FieldFill.INSERT_UPDATE) 表示表的字段 数据更新时操作
@Version 代表改字段是乐观锁version注解
@TableField(exist = false) ,表示该字段在数据库中不存在 ,所以不会插入数据库中
@TableLogic 逻辑删除注解

nacos(服务注册与发现 配置中心)

dubbo

ssm

Linux常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
文件目录类:
pwd 显示当前所在位置
ls 查看该目录下的所有的目录和文件
cd 切换目录
mkdir 增加目录操作 加-p创建多级目录
touch 指令创建空文件
cp 复制文件
rm 删除目录或者文件
mv 修改目录或文件名或者是移动目录或者文件
cat/more/less/tail 查看文件
cat只能显示最后一屏内容
more可以显示百分比 回车向下一行 空格向下一页
less使用键盘上的PgUp和PgDn向上 和向下翻页
tail -10 查看文件的后10行
> 输出重定向 : 会将原来的文件的内容覆盖 ls -l >文件
>> 追加: 不会覆盖原来文件的内容,而是追加到文件的尾部。 ls -l >>文件
vim 正常模式 插入模式/编辑模式 命令行模式
:wq 保存文件退出
:q! 不保存文件退出
yy拷贝 5yy当前行向下5行拷贝 p粘贴
dd删除 5dd删除当前行向下5行
设置行号 取消行号:set nu :set nonu
u退回上一步
搜索查找类
find 查找文件或目录 find /root -name "*.txt"
压缩解压类
tar -zcvf 打包压缩后的文件名 要打包压缩的文件
z:调用gzip压缩命令进行压缩
c:打包文件
v:显示运行过程
f:指定文件名
tar [-xvf] 压缩文件
x:
rpm -qa 查找已安装所有rpm软件包
rpm -qa | grep xx 查找xx是否已安装
yum list | grep xx 软件列表
yum install xx 下载安装
shutdown -h now立即关机
reboot 重启
useradd 用户名 新建用户
passwd 用户名 指定密码
userdel 用户名 删除用户
useradd -g 用户组 用户名 增加用户时直接加上组

Linux中Vi和Vim区别是什么?

1
2
3
4
5
6
1、多级撤销:在VI里,按u只可以撤销上次命令,但是在vim里面可以无限制撤销;
2、易用性:vi只能运行于Unix中,而vim不仅可以运用于Unix,还可以运行于Linux、Windows、mac等多个操作平台;
3、语法加亮:vim可以用不同的颜色来加亮你的代码;
4、可视化操作:vim不仅可以在终端运行,还可以运行于x Windows、Mac os、Windows。
5、对vi完全兼容:某种情况下,你可以将vim当做vi来使用。
vi和vim同属于Linux中的编辑器,但是vim比较高级,可以当做vi的升级版本

springcloud

1
eureka、ribbon、openFeign、Hystrix、geteway

问题

亮点 展现自己的亮点

1
2
自学一项新技术  并且把技术应用到项目里面   自学能力很好
模块需要的前端页面和后台逻辑都是一个人完成 独立开发一个模块 开发能力强

数据库设计

1
在开发之前,会做需求分析,将表设计好,在做开发

底层和应用开发关系 了解底层对开发什么好处

1
2
3
4
5
Hashmap底层和开发应用的关系
答: 底层和开发肯定是有关系,比如知道了Hashmap底层以后,就知道了为了确保key的唯一性,调用了hashcode()和equals()2个方法。所以在开发中如果将自定义的对象作为key时,我需要在类中重写hashcode和equals()2个方法。
还有HashMap是线程非安全的,如果考虑线程安全问题,可以使用ConcurrentHashMap.

然后我们开发项目都是使用了框架,如果熟悉底层原理,以后切换其他框架也可以很快上手。或者在开发过程中遇到问题,可以很快的定位到错误,解决隐患。

前后端分离的项目,如何解决跨域问题的?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
https://note.youdao.com/ynoteshare/index.html?id=87a205bf932427d5934cb969896a697e&type=note&_time=1644915146565

@Component
@WebFilter(urlPatterns = "/", filterName = "myOriginFilter")
@Order(1)//指定过滤器的执行顺序,值越大越靠后执行
public class OriginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// 处理跨域
//允许跨域访问的域,可以是一个域的列表,也可以是通配符”*”;
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
//允许脚本访问的返回头,请求成功后,脚本可以在XMLHttpRequest中访问这些头的信息
httpServletResponse.setHeader("Access-Control-Expose-Headers", "*");
//允许自定义的头部,以逗号隔开,大小写不敏感;
httpServletResponse.setHeader("Access-Control-Allow-Headers", "*");
//允许使用的请求方法,以逗号隔开;
httpServletResponse.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
//缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数;
httpServletResponse.setHeader("Access-Control-Max-Age", "10000");
//自定义的头部,所有用setRequestHeader方法设置的头部都将会以逗号隔开的形式包含在这个头中,要与响应头中的Access-Control-Allow-Headers相匹配才能进行跨域访问
request.setAttribute("Access-Control-Request-Headers", "*");
filterChain.doFilter(request, response);
}
}


spring跨域注解 @CrossOrigin。
对B项目HelloController做如下修改,添加@CrossOrigin注解。跨域问题解决
@CrossOrigin(origins = "*",maxAge = 3600)
public class HelloController {

@ResponseBody
@GetMapping("/hello")
public Map<String,Object> hello(String name){
System.out.println("接收到请求,name="+name);
Map<String,Object> result=new HashMap<>();
result.put("code","200");
result.put("msg","hello "+name);
return result;
}

}

看你项目负责的功能不多,怎么需要这么长时间

1
2
3
4
5
6
7
8
9
10
11
 不是说三四个月都在写代码,是从需求分析,项目开发,项目测试整个时间是这么长,其中项目测试其实会花费挺长时间。
1、立项
2、项目需求评审
3、项目架构搭建
4、项目需求分配(熟悉框架)
5、开发时间预估
6、代码开发
7、项目部署
8、提交测试
9、bug回归
10、一轮需求 二轮需求 三轮需求

为什么离职

1
之前是因为自己刚踏入it行业,正好有个玩得好的朋友在福州发展,认为去那边发展的话正好能有个照应,在福州发展了1年了,想着离家近一点也更好点,离宜春近的地方,也就只有南昌,所以离职来南昌这边了

介绍下你的项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
人力资源管理系统:
我主要负责了基本信息,考勤管理,工资管理,
基本信息: 员工信息表,部门表,(部门职位中间表),职位表 主要包括开通账户并记录员工的信息,以及入职后的工作岗位
考勤管理:考勤表,排班表(分配员工的工作时间,也可以根据部门统一分配)

汽车服务管理
主要的模块,销售模块,车辆模块,客户模块,维修模块等
我主要参与了销售模块,车辆模块

物业管理系统
我主要只负责了3个模块 楼栋管理、业主管理以及采购管理
就以楼栋管理为例:楼栋管理分为楼栋信息管理,单元信息管理,房屋管理,商铺管理
楼栋信息:id 名称 分区(A/B/C/D) 编号 创建员工id 创建时间 最后一次修改时间
对楼栋管理进行curd,且很多信息都做了poi的导入导出操作
房屋管理的话,查询的时候可以直接指定哪一栋进行搜索房屋信息,以及可以根据房屋状态 已入住、
楼栋管理主要是对小区内的楼栋信息,单元信息,房屋信息以及商铺管理进行管理与查询,以及利用poi对信息进行批量导入导出,
业主管理主要有业主信息,对业主进行房屋绑定,房屋解绑,以及点详情可以查看业主绑定的房屋信息和车位信息以及可以去查看响应的的物业费
业主的账户信息管理,主要是查看业主账户中还有多少余额,对账户余额进行充值,以及账户明细对账户充值记录的管理
房屋与业主的绑定情况
采购管理大致分为库存信息,采购物品,物品出库
采购管理:仓库信息,物品信息,物品类型,物品供应商,物品规格,采购申请,出入库明细,调拨记录,调拨明细主要是为了poi的导出,物品领用
库存信息主要有 仓库信息,物品信息(仓库的物品库存),物品的类型,物品的规格(例如物品什么颜色,物品的长宽,物品是多少瓦的)
采购物品主要有 采购流程管理,采购申请,采购代办,采购已办
物品出库,领用流程管理,领用申请,领用代办,领用已办

2到3年的职业规划 必问********

1
2
3
1、前期在开发项目的同时尽快熟悉业务
2、中期不断提升自己的开发能力,最终可以负责核心模块
3、后期可以参与项目的管理,把控一个项目的整体开发

对公司想了解的问题

1
2
3
贵公司使用什么技术?
开发团队的规模
有什么福利

你的项目几个人开发的,开发了多长时间

1
2
3
开发团队:前端1人,后端三人以及项目经理
用的什么数据库?部署在哪里?地址有吗?多少人在用?
关于部署在哪?地址是多少?多少人在用这块的问题,如果项目不是给自己开发的,都可以说不清楚,我做完开发之后,部署这块是公司实施去部署的,后面我没有管这些。

你以前工资多少?有交五险一金吗

1
2
面试的效果可以    前期刚去是6k   后期涨到7.5k 
没有交一金,五险的话是折现给我发的

你最快什么时候能够入职?

1
2
可以找理由稍微延后几天,最好不要超过三天。
可以说需要找房子,晚个三天入职等。。。

Vue

vue组件的属性名介绍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1)数据
data:Vue 实例的数据对象
components:Vue实例配置局部注册组件
(2)类方法
computed:计算属性
watch:侦听属性
filters:过滤器
methods:Vue实例方法
render:渲染函数,创建虚拟DOM
(3)生命周期
created:在实例创建完成后被立即调用,完成初始化操作
mounted:el挂载到Vue实例上了,开始业务逻辑操作
beforeDestroy:实例销毁之前调用
2、Vue组件
props:用于接收来自父组件的数据
template:组件模板

使用箭头函数和普通函数的区别

1
2
3
1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,
这样this的指向才是vm 或 组件实例对象。

父组件调用子组件

1
2
首先父组件给子节点打标识,设置子节点的ref属性设置标识名   <pagination ref="pagination"></pagination>
父组件中通过this.$refs.标识名.方法()

父子组件相互调动

1
parent /children:访问父 / 子实例

子组件调用父组件

1
2
3
4
首先父组件给子节点添加v-bind:子组件声明的接收名="方法名"  
父组件中写<pagination v-bind:list="list"></pagination>
子组件中写 props: {list: {type: Function,default: null } }
子组件通过this.list直接可以调用父组件的list方法了

如何实现不是父子关系的组件之间的相互调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1、全局事件总线   先在vue的原型对象中添加一个$bus属性,这样所有组件对象都能看见$bus这个属性对象
包含事件处理相关方法的对象(只有一个) 所有的组件都可以得到
Vue 原型对象上包含事件处理的方法:
1) $on(eventName, listener): 绑定自定义事件监听
2) $emit(eventName, data): 分发自定义事件
3) $off(eventName): 解绑自定义事件监听
4) $once(eventName, listener): 绑定事件监听, 但只能处理一次
2、消息订阅与发布
包含以下操作:
(1) 订阅消息 --对应绑定事件监听
(2) 发布消息 --分发事件
(3) 取消消息订阅 --解绑事件监听
需要引入一个消息订阅与发布的第三方实现库: PubSubJS
3、vuex
专门在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 vue 应 用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方 式,且适用于任意组件间通信
使用场景:1. 多个组件依赖于同一状态 2. 来自不同组件的行为需要变更同一状态

vue项目的ajax库:axios

router

1
1. 定义路由组件 2注册路由3 使用路由  实现路由跳转

谈谈你对 Vue 生命周期的理解?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(1)生命周期是什么?
Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载 Dom -> 渲染、更新 -> 渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
(2)各个生命周期的作用
生命周期 描述
beforeCreate 组件实例被创建之初,组件的属性生效之前
created 组件实例已经完全创建,属性也绑定,但真实 dom 还没有生成,$el 还不可用
beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用
mounted el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子
beforeUpdate 组件数据更新之前调用,发生在虚拟 DOM 打补丁之前
update 组件数据更新之后
activited keep-alive 专属,组件被激活时调用
deactivated keep-alive 专属,组件被销毁时调用
beforeDestory 组件销毁前调用
destoryed 组件销毁后调用

直接给一个数组项赋值,Vue 能检测到变化吗?

1
2
3
4
5
6
7
由于 JavaScript 的限制,Vue 不能检测到以下数组的变动:
当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
了解决第一个问题,Vue 提供了以下操作方法:
Vue.set
为了解决第二个问题,Vue 提供了以下操作方法
Array.prototype.splice

computed 和 watch 的区别和运用的场景?

1
2
3
4
5
omputed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
运用场景:
当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

v-show 与 v-if 有什么区别?

1
2
3
v-if 是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 “display” 属性进行切换。
所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。

说说你对 SPA 单页面的理解,它的优缺点分别是什么?

1
2
3
4
5
6
7
8
9
SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。
优点:
用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
基于上面一点,SPA 相对对服务器压力小;
前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点:
初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载;
前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。

什么是 MVVM?

1
2
Model–View–ViewModel (MVVM) 是一个软件架构设计模式,是一种简化用户界面的事件驱动编程方式。
MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。

Vue 的父组件和子组件生命周期钩子函数执行顺序?

1
2
3
4
5
6
7
8
9
Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分:
加载渲染过程
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
子组件更新过程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
父组件更新过程
父 beforeUpdate -> 父 updated
销毁过程
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed

谈谈你对 keep-alive 的了解?

1
2
3
4
eep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:
一般结合路由和动态组件一起使用,用于缓存组件;
提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。

组件中 data 为什么是一个函数?

1
因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。

v-model 的原理?

1
2
3
4
我们在 vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
text 和 textarea 元素使用 value 属性和 input 事件;
checkbox 和 radio 使用 checked 属性和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件

vue-router路由模式有几种?

1
2
3
hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器;
history : 依赖 HTML5 History API 和服务器配置。具体可以查看 HTML5 History 模式;
abstract : 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.

Vue 框架怎么实现对象和数组的监听?

1
2
如果被问到 Vue 怎么实现数据双向绑定,大家肯定都会回答 通过 Object.defineProperty() 对数据进行劫持,但是 Object.defineProperty() 只能对属性进行数据劫持,不能对整个对象进行劫持,同理无法对数组进行劫持,但是我们在使用 Vue 框架中都知道,Vue 能检测到对象和数组(部分方法的操作)的变化,
Vue 框架是通过遍历数组 和递归遍历对象,从而达到利用 Object.defineProperty() 也能对对象和数组(部分方法的操作)进行监听。

react、vue中的key有什么作用?(key的内部原理)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1. 虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,
随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
2.对比规则:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
(2).旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。
3. 用index作为key可能会引发的问题:
1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
2. 如果结构中还包含输入类的DOM:
会产生错误DOM更新 ==> 界面有问题。
4. 开发中如何选择key?:
1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,
使用index作为key是没有问题的。

Vue修改数组中的某个元素一定要用如下方法:

1
2
3
4
5
6
7
8
9
10
1.使用这些API:
push()、可向数组的末尾添加一个或多个元素,并返回新的长度
pop()、 用于删除并返回数组的最后一个元素
shift()、 用于把数组的第一个元素从其中删除,并返回第一个元素的值
unshift()、可向数组的开头添加一个或更多元素,并返回新的长度
splice()、 向/从数组中添加/删除项目,然后返回被删除的项目
sort()、 用于对数组的元素进行排序
reverse() 用于颠倒数组中元素的顺序
2.Vue.set() 或 vm.$set()
特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!

虚拟 DOM 的优缺点?

1
2
3
4
5
优点:
保证性能下限
无需手动操作 DOM
跨平台
缺点:无法进行极致优化

虚拟 DOM 实现原理?

1
2
3
4
虚拟 DOM 的实现原理主要包括以下 3 部分:
用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
diff 算法 — 比较两棵虚拟 DOM 树的差异;
pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。

你有对 Vue 项目进行哪些优化?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(1)代码层面的优化
v-if 和 v-show 区分使用场景
computed 和 watch 区分使用场景
v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
长表性能优化
事件的销毁
图片资源懒加载
路由懒加载
第三方插件的按需引入
优化无限列表性能
服务端渲染 SSR or 预渲染
(2)Webpack 层面的优化
Webpack 对图片进行压缩
减少 ES6 转为 ES5 的冗余代码
提取公共代码
模板预编译
提取组件的 CSS
优化 SourceMap
构建结果输出分析
Vue 项目的编译优化
(3)基础的 Web 技术的优化
浏览器缓存
CDN 的使用
使用 Chrome Performance 查找性能瓶颈

补充

Ascii码

A-Z 65-90

a-z 97-122

0-9 48-57