膜拜!华为大牛透彻讲解Java面试题100道必考题

什么是面向对象
面向对象的封装,多态,继承?
封装:明确标识出允许外部使用的成员函数和数据项
继承:继承基类的方法,并做出自己的改变和扩展
多态:基于对象所属类的不同,外部对同一个方法的调用,实际执行的逻辑不同

JDK、JRE、JVM三者联系的区别?
JDK:java开发工具
JRE:运行时环境
JVM:虚拟机

JDK包含JRE、java工具

==和equals?
==对比的是栈中的值,基本数据类型变量值,引用类型是堆中内存对象的地址

简述final作用?
修饰类:表示类不能被继承
修饰方法:表示方法不可被子类覆盖,但可以重载
修饰变量:表示变量一旦被赋值,不可以更改它的值
修饰类变量:只能在晶体初始化中指定初始值或者声明该类变量时指定初始值
修饰成员变量:可以非晶体初始化块,声明该变量或者是构造器中执行的初始值。
修饰局部变量:可以在定义指定默认值,也可以不指定默认值
修饰基本类型的变量:数值一旦初始化,不能更改
修饰引用类型变量:初始化之后不能再让其指另一个对象、但引用值可变。

为什么局部内部类和匿名内部类只能访问局部final变量?
内部类和外部类,是处于同一个级别,内部类不会因为,定义在方法中就会随着方法的执行完毕就被销毁。

String、StringBuffer、StingBuilder区别以及使用场景?
String是fnail修饰的,不可变,也不可继承。每次操作都会产生新的String对象。
SringBuffer和StingBuilder都是在原对象操作
StringBuffer是线程安全的。StringBuilder线程不安全
StringButter方法都是sychronized修饰的。
性能:SpringBuilder > SpringBuffer > String
场景:经常需要改变字符串内容时使用后面两个
优先使用:StringBuider、多线程共享变量使用:StringBuffer

重载和重写的区别?
重载:发生在同一个类中,方法名相同,参数类型不同。个数不同,顺序不同,方法返回值和访问修饰符可以不同,发生在编译时
重写:发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类 抛出的异常范围小于等于父类,访问修饰符范围大于等于父类,如果父类方法修饰符为prvate则子类就不能重写该方法

接口和抽象类?
抽象类可以存在普通成员函数,而接口只能存在public abstract方法。
抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
抽象类只能继承一个,接口可以实现多个继承

hashcode与equals的区别?
如果两个对象相等,则hashcode一定也是相同的。
两个对象相等,对两个对象分别调用equals方法都返回ture。
俩个对象有相同hashcode值,他们也不一定相等。
因此,equels方法被覆盖,则hashcode方法也必须覆盖
如果没有重写hashcode,则该class两个对象无论如何都不会相等

List 和Set的区别?
List:有序,按对象进入的顺序保存对象,可重复,允许多个null元素对象,可以使用iterator取出所有的元素,在遍历,还可以使用get()获取指定下标的元素
Set:无序,不可重复,最多允许有一个null元素对象,取元素只能用iterator接口取得所有元素,在遍历各个元素。

ArrayList 和LinkedList的区别?
ArrayList :基于动态数组,适合下标访问(随机访问)扩容机制,因为数组长度固定,超出长度存储时候,需要新建数组。
LinkedList:基于链表,可以存储在分散的内存中,适合数据插入以及删除操作,不适合查询,需要逐一遍历,遍历必须使用Iterator不能使用for循环。

HashMap和HashTable的区别?底层实现是什么?
HashMap方法由sychronized修饰,线程非安全,HashTable线程安全
HashMap允许key和value为null。而HashTable不允许
底层实现:数组+链表

如何实现一个IOC容器?
配置文件配置包扫描路径
递归包扫描获取class文件
反射,确定需要交给ioc管理的类
对需要注入的类进行依赖注入

什么是字节码?采用字节码的好处是什么?
在java中,这种虚拟机理解的代码叫做字节码。既class文件,他不面向任何特定的处理器,只面向虚拟机
好处是:java通过字节码的方式,在一定程度上,解决了传统解释性语言执行效率低的问题。同时又保留了,解释性语言可以移植的特点。

Java类加载器有哪些?
JDK自带有三个类加载器:bootsrap Classloader、ExClassLoader、AppClassLoader
bootsrap Classloader是ExClassLoader父类加载器、默认负责加载jar包和class文件
ExClassLoader是AppClassLoader父类加载器,负责加载jar包和class类
AppClassLoader是自定义加载器的父类, 负责加载claspath下的文件。系统类加载器,线程上下文加载器。

继承ClassLoader实现自定义类加载器

双亲委托模型
bootsrap Classloader -->> 委派到顶层之后,缓存中还是没有,则到加载路径中查找,有则加载返回,没有则向下查找.

ExClassLoader:

  • 向上委派:实际上就是找缓存,是否加载了该类,有则直接返回,没有继续向上。
  • 向下委派:查找加载路径,有则加载返回,没有则继续向下查找。

AppClassLoader 系统类加载器及默认上下文类加载器

双亲委派模型的好处:
为了安全,避免用户编写类动态替换java核心类。,也避免了类的重复加载。

Java中的异常体系
java中所有异常都来自父类Throwable
Throwable下有俩个子类,Exception和error
Error是程序无法处理的错误,一旦出现这个错误,程序被迫停止运行
Exception不会导致程序的停止,又分为RunTimeException运行时异常和CheckedException检查异常。
RunTimeException常常发生在程序运行过程中,会导致程序当前线程执行失败,
CheckedException发生在编译过程中,会导致程序编译不通过。

GC如何判断对象可以被回收?

  • 引用计数法:每一个对象有一个引用计数属性,新增一个引用时计数+1,引用释放时计数-1.计数为0可以回收
  • 可达性分析法:从GC Roots开始向下搜索,搜索所走过的路径成为引用链,当一个对象,到GCRoots没有任何引用链相连时。则证明此对象不可用。那么虚拟机就判断是可回收对象。

GCRoots的对象有:

  • 虚拟机栈中引用的对象
  • 方法区中静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNM引用的对象

线程的生命周期,线程有哪些状况?
线程通常有五种状态:创建,就绪,运行,阻塞,死亡

阻塞情况又分为哪三种?

  • 等待阻塞:运行线程执行wait方法,该线程会释放占用的所有资源。jvm会把该线程放入“等待池”中。进入这个状态是不能自动唤醒。必须依靠notify和notifyall唤醒。wait是object类的方法
  • 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则jvm会把该线程放入:“锁池”中。
  • 其他阻塞:运行的线程执行sleep和join方法。或者发出I/0请求,JVM会把该线程置为阻塞状态,当sleep状态超时,join等待线程终止或者超时,线程重新转入就绪状态,sleep是Thread类的方法。

sleep、wait、join、yield的区别
sleep()是Thread类的静态本地方法,不会释放锁。不需要唤醒,用于当前线程休眠,会加入到等待队列、不依赖synchronized关键字
wait()是object类的本地方法。等待状态,需要唤醒。用于多线程之间的通信。
join()执行后进入阻塞状态,例如,在线程b调用线程a的join,b会进入阻塞队列。直到线程a结束,或者中断线程。
yield()执行后直接进入就绪状态。马上释放cpu执行权。

对线程安全的理解
不是线程安全,应该是内存安全。堆是共享内存,可以被所有线程访问、

Thread、Runable的区别
Thread和Runable的实质是继承关系。没有可比性。无论使用Runable还是Thread,都会new Thread、然后执行run方法。用法上,如果有复杂的线程操作需求。那就选择Thread、如果只是简单的执行一个任务,那就Runable

Threadlocal的原理和使用场景
每一个Thread对象,含有一个ThreadLocalMap类型的成员变量threadlocal、它存储本线程中,所有ThreadLocal对象以及对应的值。

当执行set方法时,Threadlocal首先获取当前线程对象。然后获取当前线程的ThreadlocalMap对象。在以当前ThreadLocal对象为KEY。将值存储禁ThreadLocalMmap对象中。
当执行get方法时。Threadlocal首先会获取当前线程对象,然后获取当前线程ThreadLocalMap对象。在以当前ThreadLocal对象为KEY,获取对应的值value

使用场景:
1.进行对象跨层传递的时候,使用ThreadLocal避免多次传递。
2.线程数据隔离
3.进行事务操作。用于存储线程事务信息
4.数据库连接,session会话管理

ThreadLocal内存泄露原因。如何避免

不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄漏

强引用:使用普遍的new,一个对象具有强引用,不会被对象垃圾回收。当内存空间不足,java虚拟机宁愿抛出错误,使程序异常终止,也不回收这种对象。
弱引用:jvm垃圾回收时候,无论内存表示充足,都会回收被弱引用关联的对象。

并发、并行、串行的区别
并发允许俩个任务彼此干扰。统一时间点,只有一个任务执行,交替执行
并行在时间上是重叠俩个任务同一时刻互不相干扰。
串行在时间点上不可能发生重叠。前一个任务没搞定,下一个任务只能等着。

并发的三大特征:
原则性、要么全部指向完成。要么都不执行
有序性:对于那些改变顺序之后不会对最终结果造成影响的代码
可见性:当多线程访问同一个变量,一个线程修改这个变量的值,其他线程立即看到修改的值

Spring是什么?
是一个轻量级的框架(IOC)和(AOP)的容器框架。
通过IOC控制反转技术达到解耦性
提供了面向切面编程的丰富知识。
包含并管理bean的配置和生命周期。
将简单的组件配置,组成复杂的应用。

对AOP的理解
AOP将程序中交叉业务的逻辑,(安全,日志,事务)封装成切面,然后注入到目标对象。
OOP设计中,它导致了大量代码的重复,不利于各个模块的应用
oop允许定义控制上下文切换,不能控制左右,这个时候需要用到AOP切面,控制左右切换。
AOP可以对某个对象,或者某些对象的功能进行增强。

对IOC的理解
容器概念、控制反转、依赖注入

IOC容器,实际上是map(key,value)里面存放各种对象。然后我们在代码需要用到的对象时候,通过DI依赖注入(autowired)

Spring框架中用到了哪些设计模式?
简单工厂、工厂方法、单例模式、适配器模式、装饰器模式、动态代理、观察者模式、策略模式

Spring事务实现方式、和原理以及隔离级别?
有两种使用事务方式:一种是编程式、一种是声明式。@Transaction就是开启声明式的事务

首先,事务这个概念是数据库层面的。spring只是基于数据库中的事务进行了扩展。
Spring事务隔离级别是数据库的隔离级别,外加一个默认级别

  • read uncommitted(未提交读)
  • read committed(提交读、不可复读)
  • repeatable(可重复读)
  • serializable(可串行化)

Spring事务传播机制?
Required:默认的事务传播类型,如果没有事务,自己新建一个事务,如果当前存在事务,则加入该事务
supports :当前存在事务,则加入当前事务,如果没有当前事务,就以非事务方法执行
mandatory :当前存在中事务,则加入当前事务,如果当前事务不在,抛出异常
requires_new:创建一个新事务,如果存在当前事务,则挂起该事务
not_suppirted:非事务方法执行,如果当前存在事务,则挂起事务
never:不使用事务,如果当前事务存在,则抛出异常
nested:如果当前事务存在,则在嵌套事务中执行。否则required的操作一样,(开启一个事务)

Spring事务什么时候失效?

  1. 发生自调用
  2. 方法不是public
  3. 数据库不支持事务
  4. 没有被spring管理
  5. 异常被吃掉、事务不会回滚

Spring 和 SpringMVC 和 SpringBoot区别?
Spring 是IOC容器,用来管理Bean。使用依赖注入实现控制反转。可以方便整个各种框架
Spring MVC 是spring对web框架一个解决方案。
SpringBoot提供了一个快速开发工具包。让程序员更方便。简化了配置。

Mybatis优缺点:

优点:

  1. 基于sql语句编程。相当灵活
  2. 能够与spring很好集成
  3. 提供映射表标签
  4. 减少了JDBC代码量,不需要手动开关连接

缺点:
sql语句编写工作量大。依赖数据库,导致数据库移植性差

#{}和${}的区别?
#{}是预编译处理。是占位符,变量是在DBMS中,对应的变量自动加上单引号,有效防止sql注入
${}是字符串替换、拼接符,变量是在DBMS外,对应的变量不会加上单引号

索引的原理:把无序的数据变成有序的数据

  • 把创建索引的列内容进行排序
  • 对排序结果生成倒排表
  • 在倒排表内容上拼上数据地址链
  • 插叙的时候,先拿到倒排表内容。再取出数据地址链,从而拿到具体数据

索引设计的原则?

  • 合适索引的列出现在where子句中的列,或者链接子句中指定的列
  • 定义外键的数据列一定要建立索引
  • 更新频繁字段不合适创建索引
  • 不要过度索引。
  • 查询很少,重复值比较多不要建立索引
  • 尽量扩展索引,不要新建索引

Mysql锁的类型有哪些?
基于锁的属性分类:共享锁、排他锁
基于锁的粒度分类:行级锁、表级锁、页级锁、记录锁、间隙锁、临键锁
基于锁的状态分类:意向共享锁、意向排他锁

事务的基本特性和隔离级别?
事务基本特性ACID分别是:
原子性:要么全部是执行,要么全部不执行
一致性:比如A转账给B,100块钱,假设A只有90块,支付之前我们数据库里的数据都是符合约束的。但是如果事务执行成功,我们的数据库数据就破坏约束了,因此事务不能成功。所以说事务提供了一致性的保证。
隔离性:实物店修改在最终提交前,对其他事务是不可见的。
持久性:一旦事务提交,所做的修改就会永久保存到数据库

隔离级别:

  • read uncommitted(未提交读,脏读)
  • read committed(提交读、不可复读)
  • repeatable(可重复读,幻读)
  • serializable(可串行化)

ACID靠什么保证的?
A原子性是由undo log日志保证的,它记录了需要回滚的日志信息。事务回滚时撤已经执行成功的sql
C一致性由其他三大特性保证,程序代码要保证业务上的一致性。
I隔离性有MVCC来保证
D持久性,由内存+redo log日志来保证,mysql修改数据同时在内存和redo log记录这次操作,死机的时候可以从redo log 恢复

什么是MVCC?
多版本并发控制:读取数据时候,通过快照方式将数据保存下来,这样读锁和写锁不冲突。

MVCC只在 不可复读和幻读两个隔离级别下工作。其他两个隔离级别和mvcc不兼容,因为,脏读总是读取最新的数据行,而不是符合当前事务版本的数据行,而串行则会对所有读取的行都加锁。

这就是Mysql的MVCC,通过版本链,实现多版本。可并发读写,写读。通过readview生成策略不同实现不同隔离几倍

Mysql主从同步原理?

Mysql主从复制中主要有三个线程:master(Binlog dump thread)、slave(I/O thread、SQL thread)、master一条线程、slave两条线程。

  • 主节点binlog,主从复制的基础是主库记录数据库的所有变更过记录到binlog、binlog是数据库服务器启动的那一刻起,保存所有修改数据库结构或内容的一个文件。
  • 主节点log dump 线程,当binlog有变动时,log dump 线程读取其内容并发送给从节点
  • 从节点I/O线程接收binlog内容、并将其写入到relay log文件中。
  • 从节点的SL线程读取relay log 文件内容对数据库更新进行重放,最终保证主从数据库的一致性

简述MyISAM和InnoDB的区别?
MyISAM:
不支持事务,但是每次查询都是源自的;
支持表级锁,既每次操作是对整个表加锁;
存储表的总行数:
一个MyISAM表有三个文件:索引文件、表结构文件、数据文件;
采用 非聚簇索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引保持一致。但是辅索引不要保证唯一性

InnoDB:
支持ACID事务,支持事务的四种隔离级别;
支持行级锁及外键约束:因此可以支持写并发;
不存储总行数
采用聚簇索引,辅索引的数据域保存在存储主键值;因此从辅索引查找数据,要先通过辅索引找到主键值。在访问辅索引。最好使用自增主键。防止插入数据时,为维持B+树结构,文件的大调整。

Mysql中索引类型以及对数据库的性能影响
普通索引:允许被所有的数据列包含重复的值。
唯一索引:可以保证数据记录的唯一性;
主键:一种特殊的唯一索引,在一张表只能定义一个主键索引。主键用于标识一条记录。使用关键字来创建
联合索引:索引可以覆盖多个数据列,
全文索引:通过建立倒排索引,极大的提升检索效率,解决判断字段是否包含问题,是目前搜索引擎使用的一种关键技术

索引可以极大的提高查询速度。
通过使用索引,可以在查询过程中,使用优化隐藏,提高系统的性能。
索引需要占用物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要空间更大。如果非聚簇索引很多,一旦聚簇索引改变,那么多有非聚簇索引都会跟着变。

Redis中的缓存RDB和AOF机制?
RDB: Redis DataBase 在指定的时间间隔内将内存中的数据集快照写入磁盘。
优点:

  1. 整个reidis数据库将只包含一个文件dump.rdb方便持久化。
  2. 容灾性好,方便备份
  3. 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是I/O最大化。

缺点:

  1. 数据安全性低。
  2. 由于RDB是通过fork子进程来协助完成数据持久化工作,所以,如果数据比较大。会导致整个服务器停止服务几百秒。

AOF:Append Only File 以日志的形式记录服务器所处理的每一个写,删除操作,查询操作不会记录。以文本方式记录,可以打开文件看到详细的操作记录。

优点:

  1. 数据安全,redis中提供了3种同步策略。即每秒同步,每修改同步,和不同步。事实上。每秒同步也是异步完成的,效率非常高
  2. 通过append模式写文件,即中途服务宕机也不会破坏已经存在的内容,可以通过redis-cheke-aof工具解决数据一致问题。
  3. AOF机制的rewrittre模式。定期对AOF文件进行重写,达到压缩目的。

缺点:

  1. AOF比RDB文件大,恢复速度慢
  2. 数据集大的时候,比RDB启动效率低
  3. 运行效率没有RDB高.

AOF文件比RDB更新频率高,优先使用AOF还原数据。
AOF比RDB更安全也更大
RDB性能比AOF好
如果两个都配了,优先加载AOF

Redis的过期键的删除策略?
定时删除、定期删除、惰性删除

惰性过期:只有当访问一个Key时,才会判断key是否过期,过期则清除。该策略最大化节省CPU,却对内存不友好,如果没有访问key,大量的过期key不会被删除,占用大量的内存空间

定期过期:每隔一段时间,会扫描一定数量的数据库字典中一定数量key、并清除其中已经过期的key。通过调整定时扫描时间间隔和每次扫描的限定耗时。可以在不同情况下使用CPU内存资源达到最优的平衡效果

Redis线程模型。单线程为什么这么快?

Redis基于Reactor模式开发网络事件处理器。这个处理器叫做文件事件处理器,它是单线程的。所以redis是单线程的模型。采用IO多路复用机制来同时监听socket、根据监听socket上事件来选择对应的事件处理器来处理。可以实现高性能的网络通信模型,跟其他内部单线程模块进行对接。保证了redis内部线程模型的简单性。

文件事件处理器的结构包含4部分:多个socket、IO多路复用程序,文件事件分派器以及事件处理器,命令请求处理器,命令回复处理器,连接应答处理器等)

单线程快的原因:

  1. 纯内存操作
  2. 核心是基于非阻塞的IO多路复用机制
  3. 单线程反而避免了多线程上下文切换带来的性能问题

Redis事务实现?

事务开始、命令入队、事务执行、

redis集群方案?
哨兵模式:
sentinel,哨兵是redis集群中的非常重要的一个组件,主要有以下功能:

  • 集群监控:负责监控redis master 和slave进程是否正常工作
  • 消息通知:如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员
  • 故障转移:如果master挂掉,slave上
  • 配置中心:如果故障转移发怂,通知client客户端新的master地址。

哨兵用于实现redis集群的高可用,本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。

  • 故障转移时候,判断一个master是否宕机了,需要大量部分哨兵同意,涉及了哨兵的选举
  • 即使部分哨兵节点挂掉,哨兵集群还是能正常工作
  • 哨兵通常需要3个实例,来保证自己健壮
  • 哨兵+redis主从部署架构,是不保证数据零丢失,只保证redis集群高可用
    -对于哨兵+redis主从这种复杂结构,尽量测试环境和生产环境,都进行充足的测试和演练

Redis Cluster是一种服务端Sharding技术,
方案说明:

  1. 通过哈希方式,将数据分片,每个阶段均分存储一定哈希槽。默认16384槽位
  2. 每份数据分片会存储在多个互为主从的多节点上。
  3. 数据写入先写主节点,在同步到从节点。
  4. 同一个分片多个节点间的数据不保存一致性
  5. 读取数据时,当客户端操作key没有分配在这个节点上,redis会放回转向指令,指向正确的节点
  6. 扩容时,需要把旧节点数据迁移到一部分新节点。

优点:
无中心架构,支持动态扩容,对业务透明
剧本监控和自动故障转移能力
客户端不需要连接集群所有的点,连接任意一个节点即可
高性能,客户端直连节点,免去了代理损耗

缺点:
运维很复杂,数据迁移需要人工干预
只能使用0号数据库
不支持批量操作
分布式逻辑和存储模块耦合

redis主从复制
全量复制:

  1. 主节点通过bgasve命令fork子进程进行RDB持久化,该过程非常耗CPU,内存,硬盘IO
  2. 主节点通过网络将RDB文件发送给从节点,对主从节点的贷款会带来消耗
  3. 从节点清空老数据,载入新RDB文件的过程是阻塞,无法响应客户端命令,如果从节点执行bgrewriteaof,会带来额外消耗

部分复制:复制偏移量、复制积压缓冲区、服务器运行、

CAP理论、Base理论.
c(一致性):更新操作成功并返回客户端,所有节点在同一时间数据完全一致
A(可用性):即服务一直可用,而且正常响应时间
P(分区容错性):分布式系统在遇到某节点,或者网络分区故障,仍然能够对外提供满足一致性和可用化服务。

CP和AP,分区容错是必须保证,当发生网络分区,如果要继续服务,强一致性和可用性只能二选一

BASE是:
B A(基本可用)

  • 响应时间上的损失:正常情况下,处理请求需要0.5s返回结果。系统出现故障,处理用户请求的时间3s。
  • 系统功能上的损失:系统访问量突然剧增,系统的部分非核心功能无法使用

S(软状态) 数据同步允许一定延迟
E(最终一致性)系统中所有副本,经过一段时间后最终达到一致性,不要求实时
BASE是CAP演化而来的,虽然做不到强一致性,但每个应用根据自身业务特点,采用适当方法使系统达到最终一致性

负载均衡算法,类型
轮询法、随机法、源地址哈希法、加权轮询法、加权随机法、最小连接数法

类型:

  • DNA方法实现负载均衡
  • 硬件负载均衡:F5和A10
  • 软件负载均衡:Nginx 、Haproxy、Lvs
  • 13
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千筹问战

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值