1,jdk,jre,jvm
关系:JDK包含JRE,JRE包含JVM
JDK=JRE+JAVA工具
JRE=JVM+lib类库
程序执行流程:javac把.java文件编译成.class文件;.class文件放到JVM,JVM根据JRE的lib的类库解释.class文件,把.class解释成机器码,映射到操作系统。
2,==和equals
==比较的是栈中的值,所以基本数据类型比较的是数值,引用数据类型比较的是引用的地址。
equals如果使用时不重写,和==
一样的用法。
比如常用的String就重写了equals()
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
3,final关键字
结论:
● 修饰类:表示类不可以被继承
● 修饰方法:表示方法不能被子类重写,但可以重载
● 修饰变量:表示变量一旦被赋值就不能改变它的值
(1)修饰成员变量
● 如果final修饰的是类变量:则只能在静态初始化块中,或者声明该类变量时初始化
// 第一种:声明该类变量时指定初始值
final static int a=10;
// 第二种:在静态初始化代码块中初始化
final static int a;
static{
a=10;
}
● 如果final修饰的是成员变量:可以在声明该变量是初始化,或者非静态代码块初始化、
// 第一种:声明该类变量时指定初始值
final int a=10;
// 第二种:在非静态代码块初始化
final int a;
{
a=10;
}
(2)修饰局部变量
系统不会为局部变量初始化,局部变量必须由程序员显示的初始化(使用之前赋值不是声明就必须赋值)。因此
final修饰的局部变量可以在声明变量时初始化(一旦初始化之后不能修改),
也可以暂时不初始化但使用时必须初始化(也是只能初始化一次)
(3)修饰基本数据类型和引用数据类型
● 如果修饰的是基本数据类型变量,数值一旦初始化之后就不能更改。
final int a=10;
// 错误 ,一旦初始化不能改变
a=20;
● 如果修饰的是引用数据类型,初始化之后不能指向另一个对象。但引用值可以改变。
// 正确 引用值可以改变
final int[] a=new int[]{1, 2, 3};
a[1]=4;
for (int i=0;i<a.length;i++){
System.out.println(a[i]);
}
// 错误
final int[] a=new int[]{1, 2, 3};
a=new int[5];
4, String 、StringBuffer 、 StringBuild
(1) String是final修饰的,不可变的,每次比如拼接、截取实际上都是产生一个新的对象,
若频繁改变消耗内存性能差。
(2) StringBuffer和StringBuffer都是在原来的对象上操作。
(3) StringBuffer是线程安全的(类里面的方法都是synchronized修饰的,效率低),
StringBuffer是线程不安全的。
性能:StringBuild > StringBuffer > String
使用场景:不经常改变字符串的值使用String;
经常改变字符串的值时优先使用StringBuild,(多线程 、共享变量)时使用StringBuffer。
5, 重写和重载
● 重载:发生在同一个类中,方法名必须相同
⭕ 参数类型不同,个数不同,顺序不同(方法返回值和访问修饰符可以不同)
● 重写:发生在子类和父类之间,方法名和参数列表必须相同
⭕ 返回值范围小于等于父类
⭕ 抛出异常范围小于等于父类
⭕ 访问修饰符范围大于等于父类
⭕ 如果父类是private修饰不能重写
6,接口和抽象类的区别
(1) 抽象类可以存在成员函数,而接口中只能存在【public abstart】方法
(2) 抽象类中的成员变量可以是任何类型的,而接口中的成员变量只能是【public static final】类型的常量
(3) 抽象类只能继承一个,接口可以实现多个
更深一层
(1)接口:
接口是对类的行为进行约束,可以强制约束不同的类有相同的行为。但是对如何实现该行为
没有任何约束。比如一个接口有eat() 和 drink() 两个方法就强制了实现类必须实现着两个
方法,但具体怎么实现没有约束。
(2)抽象类:
抽象类设计的目的是代码复用。当不同的类具有某些相同的行为时,就可以抽取出一个父类。
父类中包括已经实现的部分方法,和抽象的让子类实现的方法。
7,List 和 Set 的区别
(1) List: 有序,按照对象进入的顺序保存对象,可重复,允许多个Null,可以使用Iterator取出所有的元素,
再逐一遍历;也可以使用get(int index)获取指定下标的元素。
(2) Set: 无序,不可重复,最多允许一个Null,只能使用Iterator取出所有的元素,再逐一遍历。
8,hashcode和equals
8.1 hashCode()作用
hashCode()的作用是获得哈希码,也称散列码;哈希码实际上就是 ‘ 对象.hashCode() ’ 计算出来的一个int类型的值。
这个int的值确定了该对象在哈希表中的索引。hashCode()定义在Object类中,在任何的方法中都可以使用。
(哈希表存储的是键值对,见就是生成的int,值就是对象)。散列表的特点就是能够根据key快速的检索出对应的value
8.2 为什么使用hashcode
hashCode()的应用之一:“HashSet检查重复”。
对象加入HashSet时,HashSet会先计算该对象的hashCode值来判断该值加入的索引的位置。如果该位置没有值就直接插入,
如果该位置有值就使用equals比较这两个对象是否是一个对象。如果是同一个对象禁止放入,
不是同一个对象重新生成不同于上次的hashCode值,再次进行上面的比较。hasnCode大大减少了equals的次数,提高性能,
如果没有hashCode每次equals遍历比较那完犊子了。
8.3 总结:
① 不同的对象可以生成同一个hasnCode值(哈希冲突),所以比较的时候会出现hasnCode值一样对象不同。
② 如果是两个相同的对象hashCode值一定相同。
③ equals方法重新,hashCode方法一定重写。
8,final finally finalize 的区别
final:修饰符(关键字)可以修饰方法、类、变量。修饰的类不能再派生新的子类即不能被继承。
修饰变量时,该变量在使用的过程中不能被修改,必须在声明时,在引用中只能读取不可修改,即为常量。
修饰方式时,也同样只能使用,不能在子类中重写。
9,spring的事务管理支持哪几种方式?每种方式的具体使用方式是什么?
9.1 事务的几种实现方式
(1)编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用
beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
(2)基于 TransactionProxyFactoryBean的声明式事务管理
(3)基于 @Transactional 的声明式事务管理
(4)基于Aspectj AOP配置事务
————————————————
版权声明:本文为优快云博主「WilliamDream」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/CHINACR07/article/details/78817449
10 日志
10.1 常用日志门面
SLF4J (simple logging Facade for java) Java的简单日志门面-》门面理解为接口。
10.2 日志的实现框架
log4j log4j2 logback(springboot默认)
10.3 为什么需要日志门面和日志实现
日志门面是一套API,只提供规范不提供实现,在项目中使用日志门面和日志实现的组合,就避免的项目
项目中途更换日志难的问题,只需要更换实现框架即可,代码不要更改。
11 redis的持久化
redis提供了两种持久化策略 RDB和AOF
11.1 RDB RDB是在指定的时间间隔对数据拍快照。
redis会单独创建(fork)一个子进程来进行持久化,会将数据先写入一个临时的文件,等待持久化完毕用这个临时文件替代上次持久化好的文件。整个过程主线程不进行任何的IO操作,确保极高的性能。如果需要进行大规模的数据恢复,并且对数据的完整性不是非常的敏感,那么RDB更高效。
默认的时间间隔:
save 900 1 900秒内至少有1个key变化则保存
save 300 10 300秒内至少有10个key变化则保存
save 60 10000 60秒内至少有10000个key变化则保存
11.2 AOF AOF持久化以日志的形式记录redis每次更新的操作语句。
如果需要恢复数据就重新执行记录的更新日志。
记录日志的策略:
appendfsync always:每产生一条更新就保存 安全效率低。
appendfsync everysec:每秒保存一次。如果最后一次保存之后,还没有到一秒断电,则丢弃了最后一次的数据。(推荐)
appendfsync no:从不保存,将数据交给操作系统处理。更快最不安全。
12 redis是单线程为什么还那么快?
12.1 完全基于内存,绝大多数请求是纯粹的内存操作,非常快速。数据存储在内存中。
12.2 数据结构简单,对数据的操作简单。
12.3 采用单线程,避免不必要的上下文切换和竞争条件,不存在多线程切换消耗cpu,不用考虑各种锁的问题。
12.4 使用多路I/O复用模型,非阻塞IO