面试题01
高频
00事务ACID
-
定义:事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。
-
四大特性
-
A 事务的原子性(Atomicity):指一个事务要么全部执行,要么不执行.也就是说一个事务不可能只执行了一半就停止了.比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱.不可能划了卡,而钱却没出来.这两步必须同时完成.要么就不完成.
-
C 事务的一致性(Consistency):指事务的运行并不改变数据库中数据的一致性.例如,完整性约束了a+b=10,一个事务改变了a,那么b也应该随之改变.
-
I 独立性(Isolation):事务的独立性也有称作隔离性,是指两个以上的事务不会出现交错执行的状态.因为这样可能会导致数据不一致.
-
D 持久性(Durability):事务的持久性是指事务执行成功以后,该事务所对数据库所作的更改便是持久的保存在数据库之中,不会无缘无故的回滚.
-
01 MySQL引擎
引擎:其用于存储、处理和保护数据的核心服务
作用:设计并创建数据库以保存系统所需的关系和文档;实现系统以方位和更改数据库中存储的数据;为单位或客户部署实现的系统;提供日常管理支持以优化数据库的性能。
- InnoDB(默认的存储引擎):是一个事务型的存储引擎,有行级锁定和外键约束。
- 适用场景:经常更新的表,适合处理多重并发的更新请求;支持事务;可以从灾难中恢复(通过bin-log日志等);外键约束。只有他支持外键;支持自动增加列属性auto_increment。
Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别,该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL后台的完整数据库系统,MySQL运行时Innodb会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎不支持FULLTEXT类型的索引,而且它没有保存表的行数,当SELECT COUNT(*) FROM TABLE时需要扫描全表。当需要使用数据库事务时,该引擎当然是首选。由于锁的粒度更小,写操作不会锁定全表,所以在并发较高时,使用Innodb引擎会提升效率。但是使用行级锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表。
- MyIsam:是MySQL默认的引擎,但是它没有提供对数据库事务的支持,也不支持行级锁和外键,因此当INSERT(插入)或UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些;MyIsam 存储引擎独立于操作系统,也就是可以在windows上使用,也可以比较简单的将数据转移到linux操作系统上去。
- 适用场景:不支持事务的设计,但是并不代表着有事务操作的项目不能用MyIsam存储引擎,可以在service层进行根据自己的业务需求进行相应的控制;不支持外键的表设计;查询速度很快,如果数据库insert和update的操作比较多的话比较适用;对表进行加锁的场景;MyISAM极度强调快速读取操作;MyIASM中存储了表的行数,于是SELECT COUNT(*) FROM TABLE时只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么MyIASM也是很好的选择。查询大于更新的操作场景
- 缺点:就是不能在表损坏后恢复数据。(是不能主动恢复)
意味着:引擎在创建表的时候,会创建三个文件,一个是.frm文件用于存储表的定义,一个是.MYD文件用于存储表的数据,另一个是.MYI文件,存储的是索引。操作系统对大文件的操作是比较慢的,这样将表分为三个文件,那么.MYD这个文件单独来存放数据自然可以优化数据库的查询等操作。有索引管理和字段管理。MyISAM还使用一种表格锁定的机制,来优化多个并发的读写操作,其代价是你需要经常运行OPTIMIZE TABLE命令,来恢复被更新机制所浪费的空间。
- Memory(堆内存):使用存在内存中的内容来创建表。每个MEMORY表只实际对应一个磁盘文件。MEMORY类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用HASH索引。
但是一旦服务关闭,表中的数据就会丢失掉。 HEAP允许只驻留在内存里的临时表格。驻留在内存里让HEAP要比ISAM和MYISAM都快,但是它所管理的数据是不稳定的,而且如果在关机之前没有进行保存,那么所有的数据都会丢失。在数据行被删除的时候,HEAP也不会浪费大量的空间。HEAP表格在你需要使用SELECT表达式来选择和操控数据的时候非常有用。
-
Mrg_Myisam(分表的一种方式-水平分表):是一个相同的可以被当作一个来用的MyISAM表的集合。“相同”意味着所有表同样的列和索引信息。也就是说,他将MyIsam引擎的多个表聚合起来,但是他的内部没有数据,真正的数据依然是MyIsam引擎的表中,但是可以直接进行查询、删除更新等操作。
-
Blackhole(黑洞引擎):任何写入到此引擎的数据均会被丢弃掉, 不做实际存储;Select语句的内容永远是空。
他会丢弃所有的插入的数据,服务器会记录下Blackhole表的日志,所以可以用于复制数据到备份数据库。
充当日志服务器
02 InnoDB底层原理
InnoDB的内存架构主要分为三大块,缓冲池(Buffer Pool)、重做缓冲池(Redo Log Buffer)和额外内存池
InnoDB为了做数据的持久化,会将数据存储到磁盘上。但是面对大量的请求时,CPU的处理速度和磁盘的IO速度之间差距太大,为了提高整体的效率, InnoDB引入了缓冲池。
当有请求来查询数据时,如果缓存池中没有,就会去磁盘中查找,将匹配到的数据放入缓存池中。同样的,如果有请求来修改数据,MySQL并不会直接去修改磁盘,而是会修改已经在缓冲池的页中的数据,然后再将数据刷回磁盘,这就是缓冲池的作用,加速读,加速写,减少与磁盘的IO交互。
缓冲池说白了就是把磁盘中的数据丢到内存,那既然是内存就会存在没有内存空间可以分配的情况。所以缓冲池采用了LRU算法,在缓冲池中没有空闲的页时,来进行页的淘汰。但是采用这种算法会带来一个问题叫做缓冲池污染。
当你在进行批量扫描甚至全表扫描时,可能会将缓冲池中的热点页全部替换出去。这样以来可能会导致MySQL的性能断崖式下降。所以InnoDB对LRU做了一些优化,规避了这个问题。
MySQL采用日志先行,在真正写数据之前,会首先记录一个日志,叫Redo Log,会定期的使用CheckPoint技术将新的Redo Log刷入磁盘,这个后面会讲。...................
03 索引
-
定义:在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。
-
作用:快速取数据;保证数据记录的唯一性;实现表与表之间的参照完整性;在使用ORDER by、group by子句进行数据检索时,利用索引可以减少排序和分组的时间。
-
缺点:1.索引需要占物理空间。2.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。
.....................
04 索引优化
-
弊端:不要盲目的创建索引,只为查询操作频繁的列创建索引,创建索引会使查询操作变得更加快速,但是会降低增加、删除、更新操作的速度,因为执行这些操作的同时会对索引文件进行重新排序或更新。但是,在互联网应用中,查询的语句远远大于DML的语句,甚至可以占到80%~90%,所以也不要太在意,只是在大数据导入时,可以先删除索引,再批量插入数据,最后再添加索引。
-
优化准则:
-
like语句的前导模糊查询不能使用索引;因:因为页面搜索严禁左模糊或者全模糊,如果需要可以使用搜索引擎来解决。
-
union、in、or 都能够命中索引,建议使用 in;有些地方说在where条件中使用or,索引会失效,造成全表扫描,这是个误区:
①要求where子句使用的所有字段,都必须建立索引;
②如果数据量太少,mysql制定执行计划时发现全表扫描比索引查找更快,所以会不使用索引;
③确保mysql版本5.0以上,且查询优化器开启了index_merge_union=on, 也就是变量optimizer_switch里存在index_merge_union且为on。
-
负向条件查询不能使用索引;负向条件有:!=、<>、not in、not exists、not like 等。可使用in优化。
-
...................
-
05 面向对象思想的理解(面向对象vs面向过程)
- 面向对象:对象是类的一个实例,有状态和行为;类是一个模板,它表述一类对象的行为和状态。
面向过程更多的是以“执行者”的角度去思考问题,而面向对象则多是以“组织者”的角度来思考问题,例:比如我们有一个需要产生随机数的需求,如果是以“面向过程”的思维,那我们更关注的是如何去设计一个算法,来保证比较均衡的产生所需的随机数;而以“面向对象”的思维,那我们更多关注的是“找谁”来帮我们完成这件事,比如Random类,调用其中提供的方法来实现即可。所以面向对象的思维更多的是考虑如何去选择合适的工具,然后组织起来干一件事,封装、继承、多态...均是以面向对象的思维来进行设计实现。过程即函数,通过编写函数进行实现,而对象则是通过调用函数来进行完成一件事的。
06 JDK、JRE、JVM的区别
- JDK(Java Development Kit):Java开发的工具包,提供了Java的开发环境和运行环境,即包含了JRE以及JVM,在安装JDK时自动安装后两者
- JRE(Java Runtime Environment):Java的运行环境,包含Java虚拟机及一些基本的类库
- JVM(Java Virtual Machine):Java虚拟机,提供执行字节码文件的能力,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。它有一个解释器组件,可以实现Java字节码和计算机操作系统之间的通信。还包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。这个也是java最大的特色跨平台性,也就是一处编写,处处运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。
如果只运行Java程序,只需要安装JRE即可。JVM是实现Java跨平台的核心,但JVM本身并不是跨平台的,不同的平台需要安装不同的JVM,

-
JVM原理
- JVM时java的核心和基础,在java编译器和os平台之间的虚拟处理器,可在上面执行字节码程序。
- java编译器只要面向JVM,生成JVM能理解的字节码文件。java源文件经编译成字节码程序,通过JVM将每条指令翻译成不同的机器码,通过特定平台运行。
-
JVM 内存模型
- java代码具体执行过程

-
运行时数据区,即JVM内存结构图

07 ==和equals的区别
==比较的是值,比较基本的数据类型即数值,比较引用类型即引用指向值的地址
equals默认比较的是地址,因为这个方法的最初定义在Object上,默认的实现就是比较地址
final当变量前有修饰符final时则表示该变量已不可变,当与之另外个final声明的变量相加时也时,可与一个总的变量相等
例:
final string s1 = "zs";
final string s2 = "zs";
string s3 = "zszs";
string s4 = s1+s2;
System.out.println(s3=s4);
//输出返回的是true,若不添加final时返回的是false,当出现new关键字时是在内存中开辟了一个空间和地址名。不同的对象new时是比较是不相同的
08 构造器(构造方法)是否可以被重写
- 首先构造器是不能被继承的,因为每个类的类名都不相同,而构造器名称与类名相同,所以根本谈不上继承。
- 又由于构造器不能继承,所以就不能被重写。但是,在同一个类中,构造器是可以被重载的。即全参构造器和无参构造器,参数不同即为重载。
重载:对于同一个类中,如果这个类里面有两个或者多个重名的方法,但是方法的参数个数、类型、顺序至少有一个不一样,这时候就构成方法的重载。作用:方法重载就是对不同数据类型的数据实现相似的操作
重写:当一个子类继承一父类,而子类中的方法与父类中的方法的名称、参数个数、类型都完全一致时,就称子类中的这个方法重写了父类中的方法。重写也是覆盖,即使用注解@Override。只有继承的前提下才会说是重写。 特点:1. 当子类重写了父类的函数,那么子类的对象如果调用该函数,一定调用的是重写过后的函数,可以通过super关键字进行父类的重写函数的调用。2. 继承可以使得子类增强父类的方法。细节 :参数名必须相同;参数列表必须相同;子类重写父类的函数的时候,函数的访问权限必须大于等于父类的函数的访问权限否则编译报错;子类重写父类的函数的时候,返回值类型必须是父类函数的返回类型或该返回值类型的子类,不能返回比父类更大的数据类型。
继承与重写的不同
重载:前提:所有的重载函数必须在同一类中,
特点:函数名相同,参数列表不同,与其他的无关(访问控制符、返回值类型)
不同:个数不同、顺序不同、类型不同
重写:前提:继承
特点:函数名必须相同、参数列表必须相同,子类的返回值类型要等于或小于父类的返回值类型
09 IO流中,inputstream(输入流)能不能new
1. 什么样的类不能被实例化
- 接口interface
- 抽象类abstract
- 构造方法的访问权限为私有private
2. 实例化
- 是指在面向对象的编程中,通常把用类创建对象的过程称之为实例化
3. Java中创建(实例化)对象的五种方法
-
用new语句创建对象,这是最常见的创建对象的方法。
-
通过工厂方法返回对象。如:Spring中通过getBean("xxx")获取Bean。
-
调用对象的clone()方法。
-
运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。如:
Object obj = Class.forName("java.lang.Object").newInstance(); -
通过I/O流(包括反序列化),如运用反序列化手段,调用java.io.ObjecInputStream对象的readObject()方法。
序列化是干什么的(将字节码转换为网络编码传输)
简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法)并且可以吧保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存objectstates,但是java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
什么情况下需要序列化
- 当你想把内存中的对象状态保存到一个文件中或者数据库中的时候;
- 想用套接字在网络上传输对象的时候
- 想通过RMI传输对象的时候
相关注意事项
- 序列化时,只对对象的状态进行保存,而不管对象的方法
- 当一个父类实现序列化,子类自动实现实例化,不需要显式实现Serializable接口
- 当一个对象的实例化变量引用其他对象,序列化该对象时也把引用对象进行实例化
- 并非所有的对象都可以实例化,至少为什么不可以,有许多的原因,安全方面的原因,资源分配方面的原因
10成员变量(全局变量)和局部变量有什么区别?
- 类中位置不同
- 成员变量:类中方法外
- 局部变量:代码块,方法定义中或者方法声明上(方法参数)
- 内存中的位置不同
- 成员变量:在堆中,堆用于存放new创建的对象和数组
- 局部变量:在栈中
- 生命周期不同
- 成员变量:随着对象的创建而存在,随着对象的消失而消失
- 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
- 初始化值不同
- 成员变量:有默认值(构造方法对它的值进行初始化)
- 局部变量:没有默认值,必须定义,赋值,然后才能使用
浙公网安备 33010602011771号