面试八股文

Java基础

面向对象三大特性

OOP,Object Oriented Programming。使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系。面向对象是相对面向过程而言,面向过程就是分析解决问题所需要的步骤,然后用函数把这些步骤一一实现,使用的时候调用函数。面向对象则是把解决问题按照一定队则划分为多个独立的对象,然后通过调用对象的方法来解决问题。面向对象三大特性:

  • 封装:将对象的属性和行为封装起来,不让外界知道具体的实现细节。private修饰的成员变量和方法只能被这个类本身访问;defalult可以被这个类本身和同一包中的类访问;protected可以被这个类本身、他的子类及同一包中的类访问;public可以被所有类访问。
  • 继承:基于已有类为基础,构建新的类。子类可以调用父类public、protected以及同包下default的成员变量,还可以重写父类已有的方法。Java中通过super来实现对父类成员的访问,通过this来访问本类的成员。
  • 多态:为了解除父子类继承的耦合度,多态允许父类引用指向子类对象(向上转型)。这样父类引用既可以使用子类重写的功能又能访问父类的成员。

类生命周期

java源文件 --javac编译–>
java字节码 --类加载–>
class对象 --实例化–>
实例对象 ----> 卸载

加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialication)、使用(Using)和卸载(Unloading)七个阶段。
其中验证、准备和解析三个部分统称为连接(Linking)。加载、验证、准备、解析和初始化是类的加载过程。
加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定,它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言地运行时绑定(也称动为态绑定)。

加载:读取class文件,将字节流所代表的静态存储结构传化为运行时数据结构存储在方法区内,并在堆中生成该类class类型的对象的过程。
验证:文件格式(是否符合class文件格式规范,并且能够被当前版本虚拟机处理)、元数据(主要对字节码描述的信息进行语义分析)、字节码、符号引用(发生在虚拟 机将符号引用转化为直接引用的时候)
准备:主要为类变量(static)分配内存并设置初始值(数据类型默认值)。这些内存都在方法区分配。
解析:主要是虚拟机将常量池中的符号引用转化为直接引用的过程。
初始化:类构造器()方法执行

类加载

类的加载是将.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆中创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。

启动类加载器Bootstrap Classloader 负责虚拟机启动时加载jdk核心类库以及后两个类加载器
扩展类加载器Extension Classloader 继承自ClassLoader,负责加载{JAVA_HOME}/jre/lib/ext/目录下所有的jar包
应用程序类加载器Application Classloader 是Extension ClassLoader的子对象,负责加载应用程序classpath目录下所有的jar和class文件

双亲委派机制

当一个类加载器收到类加载任务,会先交给其父类加载器去完成,因此最终加载任务都会传递到顶层的启动类加载器,只有当父类加载器无法完成加载任务时,子加载器才会尝试执行加载任务。
双亲委派可以避免重复加载,父类已经加载了,子类就不需要再次加载; 更加安全,很好的解决了各个类加载器的基础类的统一问题,如果不使用该种方式,那么用户可以随意定义类加载器来加载核心api,会带来相关隐患。

jdk、jre、jvm

JDK是Java开发工具包,包括jre和一些工具javac(编译)、java、javap(反编译)、jconsole(java虚拟机执行状况监视器,用来监控虚拟机内存、线程、cpu使用情况以及相关得java进程MBean)等
JRE是Java运行时环境
JVM是Java Virtual Machine

jdk1.8 新特性

Lambda表达式:匿名函数
Comparator comparator = (x, y) -> Integer.compare(x, y);
Stream API:处理集合数据,可以执行非常复杂的查找、过滤和映射数据等操作。

在系统设计中,会使用到”池”的概念。比如数据库连接池,socket连接池,线程池,组件队列。”池”可以节省对象重复创建和初始化所耗费的时间。对那些被系统频繁请求和使用的对象,使用此机制可以提高系统运行性能。

”池”是一种”以空间换时间”的做法,我们在内存中保存一系列整装待命的对象,供人随时差遣。

java创建对象的几种方式

  • 使用new语句创建对象,可以调用任意的构造函数。
  • 通过反射方式,调用java.lang.Class或者是java.lang.reflect.Constructor类的newInstance()实例方法。
  • 调用对象的clone()方法,需要先实现Cloneable接口,实现其中的clone方法。
  • 运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法。
ObjectOutputStream obj1 = new ObjectOutputStream(new FileOutputStream("a.txt"));
User user1 = new User();
user1.setName("张三");
user1.setAge(20);

obj1.writeObject(user1);

ObjectInputStream obj2 = new ObjectInputStream(new FileInputStream("a.txt"));
User user2 = (User) obj2.readObject();

mybatis缓存机制

一级缓存:SqlSession级别缓存,默认开启,是一种内存型缓存,不要求实体对象实现Serializable接口。
二级缓存:namespace级别缓存,可以是由一个SqlSessionFactory创建的SqlSession之间共享缓存数据。要求实体类必须实现序列化接口。
二级缓存与一级缓存原理相同,默认也是采用PerpetualCache,HashMap存储,不同在于其存储作用域为Namespace,并且可以自定义存储源。

sqlsession执行查询,首先会查询二级缓存,二级缓存中没有再去查询一级缓存,一级缓存中没有再从数据库中查找,并将结果放到缓存。

增删改会清空缓存,在CachingExecutor的update()方法里会调用flushCacheIfRequired(ms),flushCacheIfRequired就是从标签中取到的flushCache属性值。增删改的flushCache默认为开启true。

mybatis一级缓存默认开启,二级缓存开启:mybatis.configuration.cache-enabled:true

查询关闭一级缓存