一、JavaSE
1、自增变量
public static void main(String[] args){
int i = 1;
i = i++;
int j = i++;
int k = i + ++i * i++;
System.out.println("i=" + i);
System.out.println("j=" + j);
System.out.println("k=" + k);
}
输出结果:i=4 j=1 k=11
分析:将等号右边的从左到右加载值依次压入操作数栈,自增自减操作都是直接修改变量的值,不经过操作数栈,更新局部变量表,按照优先级进行运算,赋值之前临时结果也是存储在操作数栈中。
2、单例设计模式
Singleton:单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。例如代表JVM运行环境的Runtime类。
要点:一是某个类只能有一个实例,即构造器私有化;二是它必须自行创建这个实例,即含有一个该类的静态变量来保存这个唯一的实例;三是它必须自行向整个系统提供这个实例,即对外提供获取该实例对象的方式,(1)直接暴露(2)用静态变量的get方法获取;
常见形式:饿汉式:直接创建对象,不存在线程安全问题
直接实例化饿汉式
public class Singleton1 {
public static final Singleton1 INSTANCE =new Singleton1();
private Singleton1(){
}
}
枚举式
public enum Singleton2 {
INSTANCE
}
静态代码块饿汉式,适用于复杂的初始化数据。
public class Singleton3 {
public static final Singleton3 INSTANCE;
static {
INSTANCE=new Singleton3();
}
private Singleton3(){
}
}
懒汉式:延迟创建对象
线程不安全(适用于单线程)
public class Singleton4 {
public static Singleton4 instance;
private Singleton4(){
}
public static Singleton4 getInstance(){
if(instance==null){
instance=new Singleton4();
}
return instance;
}
}
线程安全(适用于多线程)
public class Singleton5 {
public static Singleton5 instance;
private Singleton5(){
}
public static Singleton5 getInstance() {
if(instance==null){
synchronized (Singleton5.class){
if(instance==null){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
instance=new Singleton5();
}
}
}
return instance;
}
}
静态内部类形式(适用于多线程)
public class Singleton6 {
private Singleton6(){
}
private static class Inner{
private static final Singleton6 INSTANCE=new Singleton6();
}
public static Singleton6 getInstance(){
return Inner.INSTANCE;
}
}
3、类初始化和实例初始化
类初始化过程:
一个类要创建实例需要先加载并初始化该类,main方法所在的类需要先加载和初始化;一个子类要初始化需要先初始化父类;一个类初始化就是执行<clinit>()方法,<clinit>()方法有静态类变量显示赋值代码和静态代码块组成,类变量显示赋值代码和静态代码块代码从上到下顺序执行,<clinit>()方法只执行一次。
总结:先父类再子类,静态类变量显示赋值代码由上到下顺序执行一次。
实例初始化过程:
实例初始化方法就是执行<init>()方法,该方法可能重载由多个,有几个构造器就有几个该方法;该方法由非静态实例变量显示赋值代码和非静态代码块、对应构造器代码组成;非静态实例变量显示赋值代码和非静态代码块从上到下顺序执行,而对应构造器的代码最后执行;每次创建实例对象,调用对应构造器,执行的就是对应的<init>方法;<init>方法的首行式super()或super(实参列表),即对应父类的<init>方法。
在子类的构造器中一定会先调用父类的构造器。
4、方法的重写:
哪些方法不可以被重写:final方法、静态方法、private等子类中不可见方法
对象的多态性:子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码;非静态方法默认的调用对象是this;this对象在构造器或者是<init>方法中就是正在创建的对象。
Override重写:
重写是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变。即外壳不变,核心重写。
重写的好处在于子类可以根据需要,定义特定于自己的行为。也就是子类能够根据需要实现父类的方法。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。
在面向对象原则里,重写意味着可以重写任何现有方法。
在子类中使用super关键字调用父类的被重写方法。
Overload重载:
重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
5、方法的参数传递机制
形参是基本数据类型:传递数据值;
实参是引用数据类型:传递地址值;特殊的类型String、包装类等对象不可变性;
6、成员变量和局部变量
局部变量和成员变量的区别:
声明的位置:局部变量在方法体{}中,形参,代码块{}中;成员变量在类中方法外,分为类变量(由static修饰)和实例变量(没有static修饰)。
修饰符:局部变量,final;成员变量,public、protected、private、final、static、volatile、transient
值存储的位置:局部变量,栈;实例变量,堆;类变量,方法区。
作用域:局部变量从声明处开始,到所属的}结束;实例变量在当前类中“this.”,在其它类中“对象名.”访问;类变量在当前类中“类名.”,在其它类中“类名.”或“对象名.”访问
生命周期:局部变量,每一个线程,每一次调用执行都是新的生命周期;实例变量,随着对象的创建而初始化,随着对象的被回收而消亡,每一个对象的实例变量是独立的;类变量,随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类变量是共享的。
当局部变量和实例变量重名:在实例变量前面加“this.”
局部变量与类变量重名:在类变量前面加“类名.”
7、JVM内存模型:
程序计数器:程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。
虚拟机栈:虚拟机栈描述的是Java 方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
本地方法栈:与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native 方法服务。
堆:Java 堆(Java Heap)是Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;运行时常量池。
8、compareTo方法与compare方法
compareTo方法使用:str1.compareTo(String str2):str1>str2返回正整数1,str1<str2返回负整数-1,str1=str2返回0
compare方法:
//e1>e2时返回负整数 e1=e2时返回0 e1>e2时返回正整数
public int compare(int[] e1, int[] e2) {
if (e1[0] != e2[0]) {
return e1[0] - e2[0];
} else {
return e2[1] - e1[1];
}
}
自定义排序:Arrays.sort(),自定义排序规则,前者大于后者,返回1升序,返回-1降序。
Arrays.sort(envelopes, new Comparator<int[]>() {
//e1>e2时,返回值-1表示降序,返回值1表示升序
public int compare(int[] e1, int[] e2) {
if (e1[0] != e2[0]) {
return e1[0] - e2[0];
} else {
return e2[1] - e1[1];
}
}
});
9、java左移右移、数学运算、位运算
无符号左移>>> 有符号左移>>
1<<3:表示2的3次方,1>>3:表示2的-3次方。5<<=1:表示5的二进制位左移1位。
&、&&、|、||
10、Java枚举类
理解:类的对象只有有限个,确定的,我们称此类为枚举类。当需要定义一组常量时,强烈建议使用枚举类。如果枚举类中只有一个对象,则可以作为单例模式的实现方式。
如何定义枚举类:jdk5.0之前,自定义枚举类。jdk5.0,可以使用enum关键字定义枚举类。
自定义枚举类:
enum关键字定义枚举类:默认继承于java.lang.Enum类
Enum类的主要方法:
使用enum关键字定义的枚举类实现接口:
情况一实现接口,在enum类中实现抽象方法;情况二让枚举类的对象分别实现接口中的抽象方法。
二、SSM
1、Spring中bean的作用域
在Spring中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。bean是对象,一个或多个不限定;bean由Spring IoC容器管理;我们的应用程序由一个个bean构成。
IoC(Inversion of Control),控制反转,通过依赖注入(DI)方式实现对象之间的松耦合关系。程序运行时,依赖对象由【辅助程序】动态生成并注入到被依赖对象中,动态绑定两者的使用关系。Spring IoC容器就是这样的辅助程序,它负责对象的生成和依赖的注入,然后交由我们使用。IoC就是一个对象定义其依赖关系而不创建他们的过程。
自己理解:bean对象通过IoC绑定与另一个对象的依赖关系。
bean作用域用于确定那种类型的bean实例应该从Spring容器中返回给调用者。默认singleton。
2、Spring支持的常用数据库事务传播属性和隔离级别
事务是什么?事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤销。事务的四大特性:
Spring支持的常用数据库事务传播属性和事务隔离级别:
事务的属性:
1、propagation:用来设置事务的传播行为
事务的传播行为:一个方法运行在了一个开启了事务的方法中时,当前方法是使用原来的事务还是开启一个新的事务
Propagation.REQUIRED:默认值,使用原来的事务
Propagation.REQUIRED_NEW:将原来的事务挂起,开启一个新的事务
2、isolation:用来设置事务的隔离级别
Isolation.REPEATABLE_READ:可重复读,MySQL默认的隔离级别
Isolation.READ_COMMITTED:读已提交,Oracle默认的隔离级别,开发时通常使用的隔离级别
数据库事务并发问题:
可重复读是当另一个事务将读取的数据修改后,依旧可以读取到修改之前的数据。
3、SpringMVC中解决POST请求中文乱码问题
表单中的name属性值要与POJO类中的属性名一致。Spring MVC会将请求参数名和POJO属性名自动匹配,自动为该对象填充属性值。
4、Spring MVC工作流程
5、MyBatis中当实体类中的属性名和表中的字段名不一样,怎么办?
写sql语句时起别名
在MyBatis的全局配置文件中开启驼峰命名规则
在Mapper映射文件中使用resultMap来自定义映射规则
三、Java高级
1、Linux常用服务类相关命令
centos6:service 服务名 start/stop/status、查看服务 chkconfig --list|grep xxx、chkconfig --level 5 服务名 on
centos7:systemctl start/stop/status 服务名、查看服务 systemctl list-unit-files、自启动systemctl enable 服务名
2、git相关分支命令
3、redis持久化
RDB(Redis DataBase):在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。
AOF(Append Of File):
4、Mysql什么时候建索引?
索引是帮助MySQL高效获取数据的数据结构。
5、JVM垃圾回收机制
四、项目相关
1、redis在项目中的使用场景
五种数据类型:String、Hash、List、Set、Zset
2、Elasticsearch和Solr区别
3、单点登录
一处登录多处使用。前提:单点登录多使用在分布式系统中。
单点登录三种实现方式: