转问题+回答 - 有哪些质量很高的Java面试题?

    知乎上看到一个问答,“你遇到过哪些质量很高的 Java 面试?” 本来想自己尝试回答一下,并对照作者回复的答案,以此来了解自己知识的欠缺之处,但发现写出来答案之后质量实在是不高,为避免误导读者,这里最后还是决定贴作者的答案。文章内容全部为转载知乎上允许转载的回答,但若有侵权依旧会立刻删除。

  1. 作者:@ZO01
    链接:你终将遇到的高质量Java面试题
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    • private修饰的方法可以通过反射访问,那么private的意义是什么?
      答:这题是一道思想题目,天天会碰到private,有没有想过这个问题?谈谈对java设计的认识程度,主要抓住两点:1.java的private修饰符并不是为了绝对安全性设计的,更多是对用户常规使用java的一种约束;2.从外部对对象进行常规调用时,能够看到清晰的类结构。
      注:
    • Java类初始化顺序
      答:基类静态代码块,基类静态成员字段(并列优先级,按照代码中出现的先后顺序执行,且只有第一次加载时执行)——>派生类静态代码块,派生类静态成员字段(并列优先级,按照代码中出现的先后顺序执行,且只有第一次加载时执行)——>基类普通代码块,基类普通成员字段(并列优点级,按代码中出现先后顺序执行)——>基类构造函数——>派生类普通代码块,派生类普通成员字段(并列优点级,按代码中出现先后顺序执行)——>派生类构造函数
        注:这儿的代码块是指的构造代码块。在类中没有任何修饰符、前缀、后缀的代码块就是构造代码块。构造代码块会在编译时插入到每个构造器的最前端,这样就保证不管调用哪个构造器,都会先执行构造代码块。
    • 对 方 法 区 和 永 久 区 的 理 解 以 及 它 们 之 间 的 关 系 \color{red}{对方法区和永久区的理解以及它们之间的关系}
      答:方法区是jvm规范里要求的,永久区是Hotspot虚拟机对方法区的具体实现,前者是规范,后者是实现方式。jdk1.8作了改变。本题看看对方在思想层面对jvm的理解程度,很基础的一个题目。
        注:根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。永久区也叫作永久代(PermGen space),这里的更改指的是从JDK1.8开始,永久代被Metaspace(元空间)取代。
    • 一个java文件有3个类,编译后有几个class文件
      答:文件中有几个类编译后就有几个class文件。
    • 局部变量使用前需要显式地赋值,否则编译通过不了,为什么这么设计
      答:成员变量是可以不经初始化的,在类加载过程的准备阶段即可给它赋予默认值,但局部变量使用前需要显式赋予初始值,javac不是推断不出不可以这样做,而是没有这样做,对于成员变量而言,其赋值和取值访问的先后顺序具有不确定性,对于成员变量可以在一个方法调用前赋值,也可以在方法调用后进行,这是运行时发生的,编译器确定不了,交给jvm去做比较合适。而对于局部变量而言,其赋值和取值访问顺序是确定的。这样设计是一种约束,尽最大程度减少使用者犯错的可能(假使局部变量可以使用默认值,可能总会无意间忘记赋值,进而导致不可预期的情况出现)。
    • R e a d W r i t e L o c k 读 写 之 间 互 斥 吗 \color{red}{ReadWriteLock读写之间互斥吗} ReadWriteLock
      答:ReadWriteRock 读写锁,使用场景可分为读/读、读/写、写/写,除了读和读之间是共享的,其它都是互斥的,接着会讨论下怎样实现互斥锁和同步锁的, 想了解对方对AQS,CAS的掌握程度,技术学习的深度。
    • S e m a p h o r e 拿 到 执 行 权 的 线 程 之 间 是 否 互 斥 \color{red}{Semaphore拿到执行权的线程之间是否互斥} Semaphore线
      答:Semaphore拿到执行权的线程之间是否互斥,Semaphore、CountDownLatch、CyclicBarrier、Exchanger 为java并发编程的4个辅助类,面试中常问的 CountDownLatch CyclicBarrier之间的区别,面试者肯定是经常碰到的, 所以问起来意义不大,Semaphore问的相对少一些,有些知识点如果没有使用过还是会忽略,Semaphore可有多把锁,可允许多个线程同时拥有执行权,这些有执行权的线程如并发访问同一对象,会产生线程安全问题。
    • 写一个你认为最好的单例模式
      写一个你认为最好的单例模式, 这题面试者都可能遇到过,也算是工作中最常遇到的设计模式之一,想考察面试者对经常碰到的题目的理解深度,单例一共有几种实现方式:饿汉、懒汉、静态内部类、枚举、双检锁,要是写了简单的懒汉式可能就会问:要是多线程情况下怎样保证线程安全呢,面试者可能说双检锁,那么聊聊为什么要两次校验,接着会问光是双检锁还会有什么问题,这时候基础好的面试者就会说了:对象在定义的时候加上volatile关键字,接下来会继续引申讨论下原子性和可见性、java内存模型、类的加载过程。其实没有最好,枚举方式、静态内部类、双检锁都是可以的,就想听下对不同的单例写法认识程度,写个双检锁的方式吧:
    public class Singleton {
        private Singleton() {
        }
        private volatile static Singleton instance;
        public static Singleton getInstance() {
            if (null == instance) {
                synchronized (Singleton.class) {
                    if (null == instance) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    注:这种方式是在获取实例时初始化,称为懒汉式。此处使用volatile关键字旨在禁止指令重排序优化,Java 5之前这种用法有缺陷。单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。

    • B 树 和 B + 树 是 解 决 什 么 样 的 问 题 的 , 怎 样 演 化 过 来 , 之 间 区 别 \color{red}{B树和B+树是解决什么样的问题的,怎样演化过来,之间区别} BB+
      答:B树和B+树,这题既问mysql索引的实现原理,也问数据结构基础,首先从二叉树说起,因为会产生退化现象,提出了平衡二叉树,再提出怎样让每一层放的节点多一些来减少遍历高度,引申出m叉树,m叉搜索树同样会有退化现象,引出m叉平衡树,也就是B树,这时候每个节点既放了key也放了value,怎样使每个节点放尽可能多的key值,以减少遍历高度呢(访问磁盘次数),可以将每个节点只放key值,将value值放在叶子结点,在叶子结点的value值增加指向相邻节点指针,这就是优化后的B+树。然后谈谈数据库索引失效的情况,为什么给离散度低的字段(如性别)建立索引是不可取的,查询数据反而更慢,如果将离散度高的字段和性别建立联合索引会怎样,有什么需要注意的?
      注:B+树一知半解。
    • 写 一 个 生 产 者 消 费 者 模 式 \color{red}{写一个生产者消费者模式}
      答:生产者消费者模式,synchronized锁住一个LinkedList,一个生产者,只要队列不满,生产后往里放,一个消费者只要队列不空,向外取,两者通过wait()和notify()进行协调,写好了会问怎样提高效率,最后会聊一聊消息队列设计精要思想及其使用。
      注:生产者 --> 缓冲 --> 消费者
    • 写 一 个 死 锁 \color{#FFD700}{写一个死锁}
      注:死锁的四个必要条件:互斥条件,请求与保持条件,不可剥夺条件,循环等待条件.
    • KaTeX parse error: Expected '}', got 'EOF' at end of input: …}{cpu 100%怎样定位}
      答:这个问题作者没有具体回答,不过咱们可以自己写下。
          首先可以用top找到占用cpu最高的进程 ID(关于top命令),再使用 top -Hp PID找到占用CPU最高的线程id。最后我们可以使用jstack pid打印出运行的栈信息具体查看代码做了什么。jstack显示的可能有点儿多,可以写到文件里或者是结合grep使用。
    • String a = “ab”; String b = “a” + “b”; a == b 是否相等,为什么
      答:相等,因为都存储在字符串常量池里
    • int a = 1; 是原子性操作吗
      答:不是,反编译class文件可看出来,int a = 1;也需要两步完成。
    • 可以用for循环直接删除ArrayList的特定元素吗?可能会出现什么问题?怎样解决
      答:不能,可能会出现数组下标越界
    • 新 的 任 务 提 交 到 线 程 池 , 线 程 池 是 怎 样 处 理 \color{red}{新的任务提交到线程池,线程池是怎样处理} 线线
      1. 第一步 :线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则执行第二步。
      2. 第二步 :线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里进行等待。如果工作队列满了,则执行第三步。
      3. 第三步 :线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
    • A Q S 和 C A S 原 理 \color{red}{AQS和CAS原理} AQSCAS
      答:抽象队列同步器AQS(AbstractQueuedSychronizer),如果说java.util.concurrent的基础是CAS的话,那么AQS就是整个Java并发包的核心了,ReentrantLock、CountDownLatch、Semaphore等都用到了它。AQS实际上以双向队列的形式连接所有的Entry,比方说ReentrantLock,所有等待的线程都被放在一个Entry中并连成双向队列,前面一个线程使用ReentrantLock好了,则双向队列实际上的第一个Entry开始运行。AQS定义了对双向队列所有的操作,而只开放了tryLock和tryRelease方法给开发者使用,开发者可以根据自己的实现重写tryLock和tryRelease方法,以实现自己的并发功能。
          比较并替换CAS(Compare and Swap),假设有三个操作数:内存值V、旧的预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,才会将内存值修改为B并返回true,否则什么都不做并返回false,整个比较并替换的操作是一个原子操作。CAS一定要volatile变量配合,这样才能保证每次拿到的变量是主内存中最新的相应值,否则旧的预期值A对某条线程来说,永远是一个不会变的值A,只要某次CAS操作失败,下面永远都不可能成功。
          CAS虽然比较高效的解决了原子操作问题,但仍存在三大问题。
          1)循环时间长开销很大。
          2)只能保证一个共享变量的原子操作。
          3)ABA问题。
    • synchronized底层实现原理
      答:实现依赖于对象头,当一个线程进入同步代码块时候,会将锁住对象的对象头相应位置设置为1,如果此时有其他线程需要进入,当读取到该位置为1时,则将无法进入。
    • volatile作用,指令重排相关
      答:volatile总共有两个作用:
      1.内存可见性
      2.禁止指令重排序
    • AOP和IOC原理
      答:AOP 和 IOC是Spring精华部分,AOP可以看做是对OOP的补充,对代码进行横向的扩展,通过代理模式实现,代理模式有静态代理,动态代理,Spring利用的是动态代理,在程序运行过程中将增强代码织入原代码中。IOC是控制反转,将对象的控制权交给Spring框架,用户需要使用对象无需创建,直接使用即可。AOP和IOC最可贵的是它们的思想。
    • S p r i n g 怎 样 解 决 循 环 依 赖 的 问 题 \color{red}{Spring怎样解决循环依赖的问题} Spring
      答:什么是循环依赖,怎样检测出循环依赖,Spring循环依赖有几种方式,使用基于setter属性的循环依赖为什么不会出现问题,接下来会问:Bean的生命周期。
      注:
      1)什么是循环依赖?
      所谓的循环依赖是指,A 依赖 B,B 又依赖 A,它们之间形成了循环依赖。或者是 A 依赖 B,B 依赖 C,C 又依赖 A。如果容器不处理循环依赖的话,容器会无限执行上面的流程,直到内存溢出,程序崩溃。
      2)如何解决循环依赖?
      在容器再次发现 beanB 依赖于 beanA 时,容器会获取 beanA 对象的一个早期的引用(early reference),并把这个早期引用注入到 beanB 中,让 beanB 先完成实例化。beanB 完成实例化,beanA 就可以获取到 beanB 的引用,beanA 随之完成实例化。所谓的”早期引用“是指向原始对象的引用。所谓的原始对象是指刚创建好的对象,但还未填充属性。
    • d i s p a t c h S e r v l e t 怎 样 分 发 任 务 的 \color{#FFD700}{dispatchServlet怎样分发任务的} dispatchServlet
      答:
    • m y s q l 给 离 散 度 低 的 字 段 建 立 索 引 会 出 现 什 么 问 题 , 具 体 说 下 原 因 \color{#FFD700}{mysql给离散度低的字段建立索引会出现什么问题,具体说下原因} mysql
      答:mysql为离散程度低的字段建立索引反而可能会降低效率。原因说不清。
  2. 作者:@E-臻
    来源:知乎
    链接:枚举的实质
    注:创建一个枚举类后,其实会在编译时生成一个继承Enum抽象类、被final修饰的类。具体分析可点进链接查看。

    • 枚举允许继承类吗?
      答:枚举不允许继承类。Jvm在生成枚举时已经继承了Enum类,由于Java语言是单继承,不支持再继承额外的类(唯一的继承名额被Jvm用了)。
    • 枚举允许实现接口吗?
      答:枚举允许实现接口。因为枚举本身就是一个类,类是可以实现多个接口的。
    • 枚举可以用等号比较吗?
      答:枚举可以用等号比较。Jvm会为每个枚举实例对应生成一个类对象,这个类对象是用public static final修饰的,在static代码块中初始化,是一个单例。
    • 可以继承枚举吗?
      答:不可以继承枚举。因为Jvm在生成枚举类时,将它声明为final。
    • 枚举可以实现单例模式吗?
      答:枚举本身就是一种对单例设计模式友好的形式,它是实现单例模式的一种很好的方式。
    • 当使用compareTo()比较枚举时,比较的是什么?
      答:枚举类型的compareTo()方法比较的是枚举类对象的ordinal的值。
    • 当使用equals()比较枚举的时候,比较的是什么?
      答:枚举类型的equals()方法比较的是枚举类对象的内存地址,作用与等号等价。
  3. 作者:微信公众号:Java后端技术

    • 问:数据库中最常见的慢查询优化方式是什么?
      答:加索引。
    • 问:为什么加索引可以优化慢查询?
      答:因为索引是一种优化查询的数据结构,并入MySQL的索引使用B+树实现。B+树这种数据结构可以优化查询速度。
    • 你知道哪些数据结构可以优化查询速度?
      答:哈希表,平衡二叉树,B树,B+树。
    • 那MySQL为什么会选择B+树呢?
      答:1)哈希表可以快速精确查询,但是不支持范围查找。2)因为二叉树是有序的,所以支持范围查找。但是因为左边的小于右边,所以大部分查找一次无法完成,相对效率又要低一点。所以又提出了B树,相对高度降低了,效率提高了一些。而B+树是在B树基础上把非叶子节点冗余了一份,提高了范围查找效率。
  4. 作者:【我自己】

    • 平时开发中你遇到过什么让你印象深刻的问题?
    • 使用Dubbo/MQ/Redis/MyBatis 时候遇到过什么问题?
    • 项目中使用过什么设计模式?
    • 你觉得你们系统有什么问题/有什么地方可以优化?
  5. 作者:微信公众号:Java技术栈 对原文“全部回答对了月薪5w+没问题”的表述不敢苟同,只是专心于技术即可。(待总结回答2019年5月20日)

    • 一张表里面有ID自增主键,当insert了17条记录之后,删除了第15,16,17条记录,再把mysql重启,再insert一条记录,这条记录的ID是18还是15 ?
      答:
    • mysql的技术特点是什么?
    • Heap表是什么?
    • mysql服务器默认端口是什么?
    • 与Oracle相比,mysql有什么优势?
    • 如何区分FLOAT和DOUBLE?
    • 区分CHAR_LENGTH和LENGTH?
    • 请简洁描述mysql中InnoDB支持的四种事务隔离级别名称,以及逐级之间的区别?
    • 在mysql中ENUM的用法是什么?
    • 如何定义REGEXP?
    • CHAR和VARCHAR的区别?
    • 列的字符串类型可以是什么?
    • 如何获取当前的mysql版本?
    • mysql中使用什么存储引擎?
    • mysql驱动程序是什么?
    • TIMESTAMP在UPDATE CURRENT_TIMESTAMP数据类型上做什么?
    • 主键和候选键有什么区别?
    • 如何使用Unix shell登录mysql?
    • myisamchk是用来做什么的?
    • mysql数据库服务器性能分析的方法命令有哪些?
    • 如何控制HEAP表的最大尺寸?
    • MyISAM Static和MyISAM Dynamic有什么区别?
    • federated表是什么?
    • 如果一个表有一列定义为TIMESTAMP,将发生什么?
    • 列设置为AUTO INCREMENT时,如果在表中达到最大值,会发生什么情况?
    • 怎样才能找出最后一次插入时分配了哪个自动增量?
    • 你怎么看到为表格定义的所有索引?
    • LIKE声明中的%和_是什么意思?
    • 如何在Unix和mysql时间戳之间进行转换?
    • 列对比运算符是什么?
    • 我们如何得到受查询影响的行数?
    • mysql查询是否区分大小写?
    • LIKE和REGEXP操作有什么区别?
    • BLOB和TEXT有什么区别?
    • mysql_fetch_array和mysql_fetch_object的区别是什么?
    • 我们如何在mysql中运行批处理模式?
    • MyISAM表格将在哪里存储,并且还提供其存储格式?
    • mysql中有哪些不同的表格?
    • ISAM是什么?
    • InnoDB是什么?
    • mysql如何优化DISTINCT?
    • 如何输入字符为十六进制数字?
    • 如何显示前50行?
    • 可以使用多少列创建索引?
    • NOW()和CURRENT_DATE()有什么区别?
    • 什么样的对象可以使用CREATE语句创建?
    • mysql表中允许有多少个TRIGGERS?
    • 什么是非标准字符串类型?
    • 什么是通用SQL函数?
    • 解释访问控制列表
    • mysql支持事务吗?
    • mysql里记录货币用什么字段类型好?
    • mysql数据表在什么情况下容易损坏?
    • mysql有关权限的表都有哪几个?
    • mysql中有哪几种锁?
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页