面试问题整理

接口(interface)和抽象类(abstract class)的区别是什么?

  • 一个类实现(implemens)接口时必须实现接口的所有的方法
  • 接口中的属性都是被public static final修饰的,只有常量没有变量
  • 一个类可以实现多个接口
  • 接口方法默认修饰符是public abstract,且不可以使用其他修饰符
  • 不能有构造方法
  • 接口强调的是功能
    作用:降低耦合

  • 一个类继承(extends)抽象类时,如果不实现所有的抽象方法,该类也必须是抽象类
  • 抽象类既可以有变量,也可以有常量
  • 一个类只能继承一个抽象类
  • 抽象方法可以有public、protected和default来修饰
  • 可以有构造方法、抽象方法和其他方法
  • 抽象类强调的是从属关系
    作用:把相同的东西提取出来,即重用

Servlet的生命周期

  • Servlet 通过调用 init () 方法进行初始化。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 通过调用 destroy() 方法终止(结束)。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

补充:

Servlet 调用的service() 方法:
  • 每一次请求服务器都会开启一个新的线程并执行一次service方法,service根据客户端的请求类型,调用doGet、doPost等方法。
Servlet初始化

分三种情况:

  • loadOnStartup < 0 或者 没有设置loadOnStartup
    web容器启动的时候不做实例化处理,servlet首次被调用时做实例化
  • loadOnStartup > 0
    web容器启动的时候做实例化处理,顺序是由小到大,正整数小的先被实例化
  • loadOnStartup = 0
    web容器启动的时候做实例化处理,相当于是最大整数,因此web容器启动时,最后被实例化

Object类的常见方法总结

  • protected Object toString()
    返回该对象的字符串表示,如果不重写是getClass().getName() + '@' + Integer.toHexString(hashCode())-->com.leyou.Test@506c589e
  • protected Object getClass()
    返回此 Object 的运行时类。class com.leyou.Test
  • protected Object equals(Object object)
    指示其他某个对象是否与此对象“相等”。
    注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
  • protected int hashCode()
    返回该对象的哈希码值。
    如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
  • public final void wait(long timeout)
    在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。
  • void notifyAll()
    唤醒在此对象监视器上等待的所有线程。
  • Object clone()
    创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。
    x.clone() != x为true
    x.clone().getClass() == x.getClass()为true
    x.clone().equals(x)为true

为什么equals()方法要重写?

  • 判断两个对象在逻辑上是否相等,如根据类的成员变量来判断两个类的实例是否相等,而继承Object中的equals方法只能判断两个引用变量是否是同一个对象。这样我们往往需要重写equals()方法。
  • 我们向一个没有重复对象的集合中添加元素时,集合中存放的往往是对象,我们需要先判断集合中是否存在已知对象,这样就必须重写equals方法。

equals重写有什么注意事项?

equals 方法在非空对象引用上实现相等关系:

  • 自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
  • 对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
  • 传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
  • 一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
  • 非空性:对于任何非空引用值 x,x.equals(null) 都应返回 false。

spring ioc底层用的什么数据结构?

  • xml配置文件
  • dom4j解决xml
  • 工厂设计模式
  • 反射

HashMap

  • HashMap的默认长度为16,是为了降低hash碰撞的几率
  • 红黑树一直是O(logn),链表查找的时间复杂度为O(n)

HashMap的put流程

①.判断键值对数组是否为空或为null,若条件成立则执行resize()进行扩容;
②.根据键值key计算hash值得到插入的数组索引,如果索引位置的值为null,直接新建节点添加,转向⑥,如果不为空,转向③;
③.判断桶位的首个元素是否和key一样,如果相同直接覆盖value,否则转向④,这里的相同指的是hashCode以及equals;
④.判断桶位是否为treeNode,即该节点是否是红黑树,如果是红黑树,则直接在树中插入键值对,否则转向⑤;
⑤.遍历该桶位的节点,判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作(这里用的尾插发);遍历过程中若发现key已经存在直接覆盖value即可;
⑥.插入成功后,判断实际存在的键值对数量size是否超过阈值,如果超过,进行扩容。

  • 大约记得是它首先会看key为不为空,为空就调用一个put空值的函数,不为空的话它就调用hash()函数计算hash值吗,接着会先判断这个hash值对应的地址空间是否已经有值了,如果有的话,它会把新的存进去,把旧的返回,放在后面形成链表,在jdk1.8之后,当链表超过8的时候就变成了红黑树了

补充

  • HashMap 允许插入键为 null 的键值对。
  • 因为无法调用 null 的 hashCode() 方法,也就无法确定该键值对的桶下标,只能通过强制指定一个桶下标来存放。HashMap 使用第 0 个桶存放键为 null 的键值对。

hashMap为什么线程不安全?

比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:

  1. 在 Items[Size] 的位置存放此元素;
  2. 增大 Size 的值。
    在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
    而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。
    那好,现在我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。

ConcurrentHashMap加的是什么锁?

  • ConcurrentHashMap引入了一个“分段锁(1.7)”的概念,具体可以理解为把一个大的Map拆分成N个小的HashTable,根据key.hashCode()来决定把key放到哪个HashTable中。
  • 放弃了Segment(分段锁)臃肿的设计,采用Node(数组+链表+红黑树)+CAS+Synchronize来保证线程安全
ConcurrentHashMap的get()方法是否需要加锁,为什么?
  • 1.8中ConcurrentHashMap的get操作全程不需要加锁,这也是它比其他并发集合如hashtable、用Collections.synchronizedMap()包装的hashmap;安全效率高的原因之一。
  • get操作全程不需要加锁是因为Node的成员val是用volatile修饰的和数组用volatile修饰没有关系。
  • 数组用volatile修饰主要是保证在数组扩容的时候保证可见性。

常见的异常整理

Java中的异常分为两大类:
1.Checked Exception(非Runtime Exception)
2.Unchecked Exception(Runtime Exception)

  • 算数异常类:ArithmeticException
  • 空指针异常类型:NullPointerException
  • 类型强制转换类型:ClassCastException
  • 下标越界异常:IndexOutOfBoundsExecption
  • 数组下标越界异常:ArrayIndexOutOfBoundsException
  • 类转换异常:ClassCastException

synchronize关键字的作用

synchronized的作用:
  • Synchronized是Java中解决并发问题的一种最常用最简单的方法 ,他可以确保线程互斥的访问同步代码
可以用来修饰:
  • 通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁
  • 静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁
  • 同步方法块,锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。
举例
  • 同一个对象在两个线程中分别访问该对象的两个同步方法,会产生互斥
  • 不同对象在两个线程中调用同一个同步方法,不会产生互斥
  • Synchronized修饰静态方法,用类直接在两个线程中调用两个不同的同步方法,会产生互斥

HashSet和TreeSet的区别

实现方式
  • HashSet:HashSet是哈希表实现的。
  • TreeSet:TreeSet是二叉树实现的。
数据是否有序
  • HashSet:HashSet中的数据是无序的。
  • TreeSet:Treeset中的数据是自动排好序的。
是否可以放入null值
  • HashSet:可以放入null,但只能放入一个null。
  • TreeSet:不允许放入null值。

Linux常用命令

  • cd。切换项目目录
  • pwd。用于显示工作目录
  • ls。列出路径或当前目录下的所有文件信息
  • cat <文件>。 表示读取文件内容
  • rm命令。rm是remove 的缩写。用于删除文件或文件夹,常用参数-r -f,-r表示删除目录,也可以用于删除文件,-f表示强制删除,不需要确认。同样的,删除文件前需保证当前用户对当前路径有修改的权限。
  • mkdir命令。用于创建文件夹
  • cp命令。用于复制文件或文件夹。
  • kill命令。结束当前进程
  • ifconfig/ipaddr。查看IP地址
  • touch。创建一个文件

SQL中IN和EXISTS用法的区别

  • in()适合B表比A表数据小的情况 (not in会使索引失效)
    select * from A where id in(select id from B)
  • exists()适合B表比A表数据大的情况
    select A.* from A where xx exists(select xx from B where A.id=B.id)
  • 当A表数据与B表数据一样大时,in与exists效率差不多,可任选一个使用.

线程池

  • new SingleThreadExecutor:创建一个单线程的线程池,保证所有任务的执行顺序按照任务的提交顺序执行。
  • new FixedThreadPool:创建一个固定大小的线程池。调用execute()方法。每次提交任务就成捡一个线程,直到线程达到线程吃的最大大小。
  • new CachedThreadPool:创建一个可缓存的线程池。大小不做限制
  • new ScheduledThreadPool:创建一个大小无限的线程池。定时以及周期性的执行任务的操作。

创建线程的方法

  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口

static

使用场景
  • 修饰成员变量和成员方法
  • 静态代码块
  • 修饰类(只能修饰内部类)
话术
  • 被 static 修饰的成员属于类,不属于单个这个类的某个对象,该类中所有对象共享,可以并且建议通过类名调用。被static 声明的成员变量属于静态成员变量,静态变量 存放在 Java 内存的方法区。且仅有一份。
  • 静态代码块定义在类中方法外, 静态代码块在非静态代码块之前执行(静态代码块—非静态代码块—构造方法)。 该类不管创建多少对象,静态代码块只执行一次.
  • 通过类名.来调用

Redis挂了怎么办?

  • 因为redis它有持久化的特性,所以在购物车这个场景,用redis其实已经足够了,退一万步说,redis挂了,购物车它不会造成特别大的损失。(时间间隔机制)但是我知道redis它有三种集群模式,主从模式,哨兵模式,还有一个是分片的模式,但是我们这个商城没有用到redis集群。
  • 万一Redis真的挂了,我们可以设置本地缓存(ehcache)+限流(hystrix),尽量避免我们的数据库被干掉(起码能保证我们的服务还是能正常工作的)。事发后:redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。
Redis持久化
  • RDB
    每隔多少秒生成快照存储到磁盘等介质上
  • AOF
    把所有的写指令记录下来,重启把写指令再重新执行一遍

排查系统遇到的问题

  • 事前:流量达到高峰,加入来了大批量的请求,做一些限流、降级的操作
  • 事中:出发了我们认定为Bug的逻辑,可以发一些邮件或者通知的报警
  • 事后:问题产生后去追查错误日志,cat命令,错误日志的排查

事务运用的场景

  • 操作多张表的时候
  • 循环更新、插入
    核心在于,某一个业务失败了是否可以回滚

ArrayList和LinkedList的插入,删除时间复杂度

操作 ArrayList LinkedList
读取 get() 根据下标直接查询,时间复杂度O(1) 遍历获取,时间复杂度O(n)
添加 add(E) 直接尾部添加,时间复杂度O(1) 直接尾部添加,时间复杂度O(1)
指定位置添加 add(index,E) 后面元素需要逐个移动,时间复杂度O(n) 指针指向操作,时间复杂度O(n)
删除 remove(E) 后面元素需要逐个移动,时间复杂度O(n) 直接指针操作,时间复杂度O(1)

之前用过Nginx吗? 你们一般都用它做什么?

  • Nginx肯定用过,首先它本身是一款性能很高的Web服务器,我们在处理以静态资源都会利用到它,当然也听说Nginx也可以结合一些脚本语言处理动态应用,不过这方面倒是没有接触过,我们公司一般会将nginx和Tomcat相结合来使用。另外它还有一个很功能就是充当反向带服务器,在我们的微服务中就是利用它来反向代理Zuul网关,从而可以实现zuul的高可用,而且它自身携带负载均衡,我们也可以通过修改配置文件来实现自己的配置。

索引(底层存储结构B+Tree)

索引的分类
  • 普通索引:加快查询
  • 唯一索引:加速+唯一(不能为空)
  • 主键索引:加速+唯一(可以为空)
  • 组合索引:多列值组成一个索引,专门用于组合索引(左前匹配原则)
  • 全文索引:利用分析技术等多种算法智能分析文本,筛选我们想要的结果
使用索引的条件:
  • 字段的识别度不低于70%
  • 经常作为where条件的字段适合创建索引
  • 经常作为Order by条件的字段适合创建索引
  • 经常作为表连接的字段适合创建索引
索引失效的条件:
  • 使用 != < > not in等关键字
  • 使用like,例如like %xxx%(失效),like xxx%(不会失效)
  • 索引字段不能用于进行计算
  • 不要在索引字段使用is null、is not null

在SpringCloud 体系你使用的Cookie 有没有遇到过什么问题

  • 确实遇到过Cookie 丢失的问题,原因是Zuul内部有默认的过滤器,会对请求和响应头信息进行重组,过滤掉敏感的头信息,而Cookie默认就是敏感信息,所以就给过滤掉啦,怎么解决呢,其实解决很简单,就是覆盖sensitiveHeaders这个过滤请求头的最终属性的为null就可以啦!需要我们在配置文件中配置 zuul.sensitive-headers=

volatile 的特性

  • 在Java中,每个线程都有一个独立的内存空间,称为工作内存; 它保存了用于执行操作的不同变量的值。在执行操作之后,线程将变量的更新值复制到主存储器,这样其他线程可以从那里读取最新值。
    简单地说,volatile关键字标记一个变量,在多个线程访问它的情况下,总是转到主内存,读取和写入。
  • 保证可见性(强制刷新在主存,其他线程缓存无效)和有序性(禁止指令重排序),这些都是上面的用内存屏障完成的。

  • 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。(实现可见性)
  • 禁止进行指令重排序。(实现有序性)
  • volatile 只能保证对单次读/写的原子性。i++ 这种操作不能保证原子性。

你要悄悄拔尖,然后惊艳所有人!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 1,188评论 0 5
  • Win7下如何打开DOS控制台? a:开始--所有程序--附件--命令提示符 b:开始--搜索程序和文件--cmd...
    逍遥叹6阅读 1,588评论 4 12
  • 面向对象主要针对面向过程。 面向过程的基本单元是函数。 什么是对象:EVERYTHING IS OBJECT(万物...
    sinpi阅读 1,046评论 0 4
  • 1.import static是Java 5增加的功能,就是将Import类中的静态方法,可以作为本类的静态方法来...
    XLsn0w阅读 1,214评论 0 2
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,629评论 0 11