面试题总结,不定期更新

问:设计模式六大原则有哪些.
答:1.单一原则,一个类只负责一项职责,尽量做到类的只有一个行为原因引起变化;a,业务对象,业务逻辑拆分。
2里氏替换原则,子类可以扩展父类的功能,但不能改变原有父类的功能。(目的,增强程序的健壮性),实际项目中,每个子类对应不同的业务含义,使父类作为参数,传递不同的子类完成不同的业务逻辑。
3.依赖倒置原则:面向接口编程,(通过接口作为参数实现应用场景)抽象就是接口或者抽象类,细节就是实现类
  含义:
    上层模块不应该依赖下层模块,两者应依赖其抽象;
    抽象不应该依赖细节,细节应该依赖抽象;
【接口负责定义public属性和方法,并且申明与其他对象依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑】
4.接口隔离:建立单一接口;(扩展为类也是一种接口,一切皆接口)
   定义:
    a.客户端不应该依赖它不需要的接口;
    b.类之间依赖关系应该建立在最小的接口上;
 【接口的设计粒度越小,系统越灵活,但是灵活的同时结构复杂性提高,开发难度也会变大,维护性降低】
5. 迪米特原则:最少知道原则,尽量降低类与类之间的耦合;一个对象应该对其他对象有最少的了解
6.开闭原则:用抽象构建架构,用实现扩展原则;
问:分布式架构设计中的CAP原理:
答:cap原则又称cap定理,指的是在一个分布式系统中:
Consistency(一致性):每次读操作都能保证返回的是最新数据
Availability(可用性):任何一个没有发生故障的节点,会在合理的时间内返回一个正常的结果。
Partition tolerance(分区容错性):当节点间出现网络分区,照样可以提供服务。
问:计算机网络七层协议模型具体是哪些
答:应用层,传输层,表示层,链路层,物理层,会话层,网络层

int和integer区别,以及应用场景

int是基本数据类型,Integer是封装类。int的初始值是0,Integer是null。即Integer可以区分出未赋值和值为0的区别,Int则无法表达出未赋值的情况。比如,想要表达出没有参加考试和考试为0的区别。

什么样的情况会引起OutOfMemoryError,内存溢出。

内存中加载的数据量过于庞大,如一次从数据库读取过多数据。集合类中有对对象的引用,使用完后未情况,使得jvm不能回收。代码死循环等。

设计模式
共23种设计模式,又分为三大类:

1.行为型模式:访问者模式,模板模式,策略模式,状态模式,观察者模式,备忘录模式,中介者模式,迭代器模式,解释器模式,命令模式,责任链模式。
2.结构型模式:适配器模式,桥接模式,组合模式,装饰模式,外观模式,亨元模式,代理模式。
3.创建型模式:单例模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式。

各个模式的关键点总结:

单例模式:某个类只能有提一个实例,供一个全局的访问点。
简单工厂:一个工厂类根据传入的参量决定创建出那一种产品类的实例。
工厂方法:定义一个创建对象的接口,让子类决定实例化那个类。
抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类。
建造者模式:封装一个复杂对象的构建过程,并可以按步骤构造。
原型模式:通过复制现有的实例来创建新的实例。
适配器模式:将一个类的方法接口转换成客户希望的另外一个接口。
组合模式:将对象组合成树形结构以表示“”部分-整体“”的层次结构。
装饰模式:动态的给对象添加新的功能。
代理模式:为其他对象提供一个代理以便控制这个对象的访问。
亨元(蝇量)模式:通过共享技术来有效的支持大量细粒度的对象。
外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
状态模式:允许一个对象在其对象内部状态改变时改变它的行为。
观察者模式:对象间的一对多的依赖关系。
备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
中介者模式:用一个中介对象来封装一系列的对象交互。
命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。
责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。

工厂模式的作用,为什么要用工厂模式。

工厂模式是为了解耦:把对象的创建和使用的过程分开,就是类A想调用类B,那么只是调用B的方法,而至于B的实例化,就交给工厂类。
工厂可以降低代码重复。如果创建B过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多重复代码。可以把这些创建对象B的代码放到工厂里统一管理,既减少代码,也方便以后对B的管理。
工厂模式可以减少错误,因为工厂管理了对象的创建逻辑,使用者不需要知道具体的创建过程,只管使用即可,减少了使用者因为创建逻辑导致的错误。

工厂模式的一些适用场景:

对象的创建过程/实例化准备工作很复杂,需要很多初始化参数,查询数据库等。类本身有好多子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变。

什么是单例模式,什么情况下使用单例模式,为什么使用单例模式

单例模式是一种常用的软件设计模式,在它的核心结构中只包含一个被称为单例的特殊类。单例模式的要点:一是某个类只能有一个实例;二是它必须自行创建这个实例。三是它必须自行像整个系统提供这个实例。单例模式作用:一是解决多线程并发访问问题,二是节约系统内存,提高系统运行效率,提高系统性能。像数据库连接池就是使用单例模式,像spring创建的controller就是单例。

为什么要重写equals()和hashcode()方法

可以这么理解,首先当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true 。
当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false
如果不重写equals,那么比较的将是对象的引用是否指向同一块内存地址,重写之后目的是为了比较两个对象的value值是否相等。
hashcode是用于散列数据的快速存取,如利用hashset/hashmap/hashtable类来存储数据时,都是根据存储对象的hashcode值来进行判断是否相同。
这样如果我们对一个对象重写了equals,意思是只要对象的成员变量值都相等那么equals就等于true,但不重写hashcode,那么我们在new一个新的对象,当原对象.equals(新对象)等于true时,两者的hashcode却是不一样的,由此将产生了理解的不一致,如在存储散列集合时,将会存储了两个值一样的对象,导致混淆,因此,也需要重写hashcode().
问:
springCloudGateWay 网关鉴权:
答:
问:
netty的堆外内存,是怎么管理堆外内存的。
答:

java后端对接app,数据安全怎么做

这个问题,其实不光是app端,像现在的前后端分离后,都是要做些交互上的数据安全。像这方面一般采用什么做法呢:
1.通信使用https
2.请求签名,防止参数被篡改。
3.身份确认机制,每次请求验证合法性
4.app中使用ssl pinning防止抓包操作
5.对所有请求和相应进行加解密操作
6.网络限制,比如某些特定网络请求对应接口
7.多会话式加密请求方式
等等.....还有很多种方法,大家可以自行搜查资料。
所谓多会话式加密请求,其实是借鉴的SIP协议在进行呼叫及注册时候的规则,SIP协议在发送INVITE请求时,第一次会收到407鉴权请求,根据服务回的相关信息,按照统加密规则进行加密,然后再次INVITE,把相关鉴权信息带上,鉴权通过了才会发送呼叫。根据这种原理,我们的多伦会话请求的基本思路是,第一次请求带上需要操作的相关信息,收到服务回的相关信息,根据相同规则,生成加密串,再重复提交,后端校验,然后进行后续操作。

那么,这其中的重点就在双方认证的规则。

具体流程如下:


image.png
数据库方面单纯从数据库来做,大数据量的表怎么操作,提高效率
redis分布式锁原理
redis常使用它的哪些特性,发挥了什么作用。

有时候面试会问,那redis你用了哪些特性,为什么用有什么效果这样子,有的会就会有点蒙了,这该怎么回答。其实就是在问redis的八大特性优点这些东西,别被混淆了。
八大特点以及使用场景:
1.速度快
说到Redis的速度快,大家的第一反应一定是内存读取,那是肯定的,但如果面试的时候仅仅说到这点,那还是远远不够的,至少还有以下三点要补充:
Redis是用C语言实现的,而众所周知,C语言是“距离”操作系统最近的的编程语言,执行速度快
Redis采用了单线程的架构(这点很容易遗忘,但是是Redis的最重要特性),避免了多线程的资源竞争问题
Redis的源码非常精简,可以说是集性能和优雅于一身的代码
基于键值对的服务器
  Redis的全程是Remote Dictionary Server,是集合了五种数据结构:字符串、列表、哈希、集合、有序集合,可以说五种数据结构都是围绕于key-value的形式,而value不仅仅可以是值,还能是具体的数据结构,这给予了Redis强大的变化性和灵活能力。
丰富的功能
  除了数据结构的强大,另外就是Redis所提供的丰富的功能了:

提供了key过期的功能,这能运用于实现缓存
提供了发布订阅的功能,可运用于消息队列,如celery
支持lua脚本功能,当觉得Redis的命令实现功能不够时,就能利用lua来创建新的功能
提供了简单的事务功能,不过不能支持回滚,但也能一定程度上保持事务的特性
提供了pipeling功能,这样客户端可以将多条命令一次io,减少了网络的开销
简单稳定
  Redis的简单表现在两方面,一方面是在3.0版本之前源代码仅3万行,后面3.0加入了集群后代码加到了5万行,而5万行的源代码对于开发人员来说,要理解掌握它也显得并不是那么难;另一方面就是Redis是单线程的结构,这使得Redis的服务端处理模型变得简单,客户端开发也显得简单。
  Redis虽然代码少,并且是单线程的,但是它又非常的稳定,很少会出现因为自身bug而down掉的情况。
客户端语言多
  Redis目前基本可以说和MySQL的知名度一样高了,太多的运用场景,太多的支持语言,常见的比如:java的jedis,Python的redis、PHP、C、C++等等。
持久化
  Redis还支持两种方式的持久化,即将数据写入磁盘的方法,RDB和AOF,两种方法各有利弊,这里就不详细介绍了。
主从复制
  那数据库的主从复制、集群功能是非常重要的,可以在Redis异常挂了后不影响客户端的使用,而Redis也是支持主从复制功能。


image.png

高可用和分布式
  Redis从2.8版本后提供了高可用实现的Redis Sentinel,即Redis的“哨兵机制”,可以保证Redis节点的故障发现和自动转移,这实现了Redis强大的分布式功能。
Redis的应用场景
缓存
  缓存可以说是Redis最常用的功能之一了,合理的缓存不仅可以加快速度的访问速度,以及可以减少后端的压力(通常就是MySQL的压力)。可以说,一个合理的缓存可以极大地提高网站的性能。

排行榜系统
  利用Redis的列表和有序集合的特点,可以制作排行榜系统,而排行榜系统目前在商城类、新闻类、博客类等等,都是比不可缺的。

计数器应用
  计数器的应用基本和排行榜系统一样,都是多数网站的普遍需求,如视频网站的播放计数,电商网站的浏览数等等,但这些数量一般比较庞大,如果存到关系型数据库,对MySQL或者其他关系型数据库的挑战还是很大的,而Redis基本可以说是天然支持计数器应用。

消息队列系统
  Redis支持发布订阅系统和阻塞队列的功能,可以充当一般的消息队列功能,虽然和专业的消息队列MQ比如RebbitMQ比起来还优点差距,但也基本够用了,比如celery的异步模型,Redis也是celery官方指定的2种队列的一种。
社交网络
  对于社交网络来说,一般用户量是及其庞大的,此时的关系型数据库就捉襟见肘了,比如好友点赞、关注、推送等等功能,用Redis就能比较轻松地实现这些功能。

spring的事务隔离级别和传播机制

隔离级别:
1、ISOLOCATION_DEFAULT: 数据库默认级别
2、ISOLOCATION_READ_UNCOMMITTED: 允许读取未提交的读, 可能导致脏读,不可重复读,幻读
3、ISOLOCATION_READ_COMMITTED: 允许读取已提交的读,可能导致不可重复读,幻读
4、ISOLOCATION_REPEATABLE_READ : 不能能更新另一个事务修改单尚未提交(回滚)的数据,可能引起幻读
5、ISOLOCATION_SERIALIZABLE: 序列执行效率低
传播级别:
1、PROPERGATION_MANDATORY: 方法必须运行在一个事务中,不存在事务则抛出异常
2、PROPERGATION_NESTED:  存在事务则运行在嵌套事务中,不存在则创建一个事务
3、PROPERGATION_NEVER: 当前方法不能运行在事务中,存在事务则抛出异常
4、PROPERGATION_NOT_SUPPORT: 当前存在事务则将其 挂起
5、PROPERGATION_REQUIRED: 不存在事务则创建一个事务
6、PROPERGATION_REQUIRES_NEW: 新建一个自己的事务,不论当前是否存在事务
7、PROPERGATION_SUPPORT: 存在事务则加入,不存在也可以

synchronized和和Lock有什么区别
1.synchronized是关键字属于jvm层面,monitorenter(底层是通过monitor对象来完成,其实wait、notify等方法也依赖于monitor对象,只有在同步块或同步方法中才能调用wait、notify等方法)

lock是具体类(java.util.concurrent.locks.lock)是api层面的锁。
2.使用方法:synchronized不需要用户去手动释放锁,当synchronized代码执行完后系统会自动让线程释放对锁的占用。
reentrantlock则需要用户去手动释放锁,若没有主动释放锁,就有可能导致出现死锁现象。
3.等待是否可中断
synchronized不可中断,除非抛出异常或者正常运行完成
reentrantlock可中断,(1)设置超时方法trylock(long time,TimeUnit unit)(2)lockInterruptibly()放代码块中,调用interrupt()方法可中断
4.加锁是否公平
synchronized非公平锁
reentrantlock两者都可以,默认非公平锁,构造方法可以传入true,true为公平锁,false为非公平锁。
5.锁绑定多个条件Condition
synchronized没有
reentrantlock用来实现分组唤醒需要唤醒的线程,可以精确唤醒,而不是像synchronized要么随机唤醒一个线程要么全部唤醒

FileSystemResource 和 ClassPathResource 有何区别?

在FileSystemResource 中需要给出spring-config.xml文件在你项目中的相对路径或者绝对路径。在ClassPathResource中spring会在ClassPath中自动搜寻配置文件,所以要把ClassPathResource 文件放在ClassPath下。
如果将spring-config.xml保存在了src文件夹下的话,只需给出配置文件的名称即可,因为src文件夹是默认。
简而言之,ClassPathResource在环境变量中读取配置文件,FileSystemResource在配置文件中读取配置文件。

你可能感兴趣的:(面试题总结,不定期更新)