找工作好难呀之Java面试题总结(不断总结中)

Posted 可乐好哇!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了找工作好难呀之Java面试题总结(不断总结中)相关的知识,希望对你有一定的参考价值。

什么是面向对象?

  • 面向过程注重事情的每一个步骤

  • 面向对象注重事情有哪些参与者以及各自需要干什么

  • 封装:明确标识允许外部使用的所有成员函数和数据项

  • 继承:继承基类的方法,并且自己做出扩展或改变

  • 多态:继承、方法重写、父类引用子类对象(便于开发扩展新的功能)

    父类类型 变量名 = new 子类对象();
    变量名.方法名(); // 调用的是子类的方法,但是没办法调用子类独有的功能
    

重载和重写的区别?

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

接口和抽象类的区别?

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

JDK、JRE、JVM三者区别和联系?

  • JDK:Java开发工具

  • JRE:Java运行时环境

  • JVM:Java虚拟机

  • JDK(JRE(JVM))

== 和 equals(笔试)

  • == :对比栈中的值,基本数据类型是变量的值,引用类型是堆中内存对象的地址
  • equals:可以重写

final的作用?

  • 修饰类时,类不可以被继承
  • 修饰方法时,方法不可被子类覆盖,但是可以重载
  • 修饰变量时,变量一旦被赋值就不可以更改它的值

String、StringBuffer、StringBuilder区别及使用场景?

  • String:是final修饰的,不可变,每次操作都会产生新的String对象
  • StringBuffer:在原对象上操作,是线程安全的,它的方法都是synchronize修饰
  • StringBuilder:在原对象上操作,是线程不安全的
  • 性能:StringBuilder > StringBuffer > String
  • 场景:优先使用 StringBuilder,多线程使用共享变量时使用StringBuffer(解决并发问题)

List 和 Set 的区别?

  • List:有序,按对象进入的顺序保存对象,可重复,允许多个Null元素对象,可以用iterator取出所有的元素,再逐一遍历,还可以使用get(int index)获取指定的下标元素
  • Set:无序,不可重复,最多允许一个Null元素对象,取元素时只能用iterator接口取得所有元素,再逐一遍历各个元素

hashCode 与 equals?

  • equals:默认是object中的方法相等与“==”,也可以重写它的方法
  • hashCode:两个对象相等,则hashCode一定相同;两个对象相等,对两个对象分别调用equals方法都返回true;两个对象有相同的hashCode值,他们也不一定是相等的;equals方法被覆盖过,则hashCode方法也必须被覆盖;hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等

ArrayList 和 LinkedList的区别?

  • ArrayList:基于动态数组,连续内存存储的,适合下标访问,有自己的扩容机制,如果数组空间足够,尾插法效率可能比LinkedList的更高效
  • LinkedList:基于链表,可以存储在分散的内存中,适合做数据插入及删除操作,不适合查询

HashMap 和 HashTable 的区别?其底层实现是什么?

  • 区别:

    1. HashMap 方法没有synchronize修饰,线程不安全;HashTable是线程安全的
    2. HashMap允许key和value为null,而HashTable不允许
  • 底层实现:(数组 + 链表实现)

    1. jdk8开始链表高度到8,数组长度超过64,链表转变为红黑树,元素以内部Node节点存在

      • 计算key的hash值,二次hash然后对数组长度取模,对应到数组下标
      • 如果没有产生hash冲突,则直接创建Node存入数组
      • 如果产生hash冲突,先进行equals比较,相同则取代该元素,不同则判断链表高度插入链表,链表高度达到8,并且数组长度到64则转变为红黑树,长度低于6则将红黑树转回链表
      • key为null,存在下标0的位置
    2. 数组扩容

Java中的类加载器

  • BootStrapClass
  • ExtClassLoader
  • AppClassLoader

什么是双亲委派模型?好处?

  1. 向上委派:实际上就是查找缓存,是否加载了该类,有就直接返回,没有继续向上
  2. 向下查找:查找加载路径,有就加载返回,没有就继续向下查找
  • 主要为了安全性,避免用户自己编写的类动态替换Java的核心类
  • 避免类的重复加载,因为JVM中区分不同类,不仅仅是根据类名,相同的class文件被不同的ClassLoader加载就是不同的两个类

线程的生命周期

  1. 线程通常有五种状态:创建,就绪,运行,阻塞和死亡状态

    • 新建状态(New):新创建了一个线程
    • 就绪状态(Runnable):线程对象创建后,其他线程调用该对象的start方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权
    • 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码
    • 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态
    • 死亡状态(Dead):线程执行完了或者因为异常退出了run方法,该线程结束生命周期

  2. 阻塞的情况分为三种:

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

并发的三大特性

  1. 原子性:不被中断操作,要不全部执行完成,要不都不执行
  2. 可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值
  3. 有序性:虚拟机在进行代码编译时,对那些改变顺讯之后不会对最终结果造成影响的代码,虚拟机不一定惠安张我们写的代码顺序来执行,有可能将他们重排序

为什么用线程池?解释下线程池参数

  1. 降低资源消耗;提高线程利用率,降低创建和销毁线程的消耗
  2. 提高响应速度;任务来了,直接有线程可用可执行,而不是先创建线程,再执行
  3. 提高线程的可管理性;线程是稀缺资源,使用线程池可以统一分配调优监控

线程池处理流程

  • 线程池执行任务
  • 判断线程是否已满,未满就创建核心线程,满了就继续下面流程
  • 判断任务队列是否已满,未满就将任务放入队列中,满了就继续下面流程
  • 判断线程数是否达到,未达到就创建临时线程执行,达到就执行下面流程
  • 根据拒绝策略处理任务

线程池中阻塞队列的作用?为什么是先添加队列而不是先创建最大线程?

  1. 阻塞队列通过阻塞可以保留住当前想要继续入队的任务;它可以保证任务队列中没有任务是阻塞获取任务的线程,使得线程进入wait状态,释放CPU资源;它自带阻塞和唤醒功能,不需要额外处理,无任务执行时,线程池利用阻塞队列的take方法挂起,从而维持核心线程的存活、不至于一直占用CPU资源
  2. 在创建新线程的时候,是要获取全局锁的,这个时候其他的就得阻塞,影响了整体效率

线程池中线程复用原理

  • 线程池将线程和任务进行解耦,线程是线程,任务是任务,摆脱之前通过Thread创建线程时的一个线程必须对应一个任务的限制
  • 在线程池中,同一个线程可以从阻塞队列中不断获取新任务来执行,其核心在于线程池对Thread进行了封装,并不是每次执行任务都会调用Thread.start()来创建新线程,而是让每个线程去执行一个“循环任务”,在这个“循环任务中”不停检查是否有任务需要被执行,如果有则直接执行,也就是调用任务中的run方法,将run方法当成一个普通的方法执行,通过这种方式只使用固定的线程就将所有的任务run方法串联起来

索引的基本原理

  • 索引用来快速地寻找那些具有特定值的记录。如果没有索引,一般说执行查询时遍历整张表
  • 索引的原理:就是把无序的数据变成有序的查询
    1. 把创建了索引的列的内容进行排序
    2. 对排序结果生成倒排表
    3. 在倒排表内容上拼上数据地址链
    4. 在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据

索引设计原则

  • 查询更快、占用空间更小

mysql锁的类型有哪些?

  1. 基于锁的属性:共享锁,排他锁
  2. 基于锁的粒度分类:行级锁(INNODB)、表级锁(INNODB、MYISAM)、页级锁(BDB引擎)、记录锁、间隙锁、临键锁
  3. 基于锁的状态:意向共享锁、意向排他锁

事务的基本特性和隔离级别

  • 事务的基本特性ACID分别是:(用户微信转账场景)
    1. 原子性:一个事务中的操作要么全部成功,要么全部失败
    2. 一致性:数据库总是从一个一致性的状态转换到另一个一致性的状态
    3. 隔离性:一个事务的修改在最终提交前,对其他事务是不可见的
    4. 持久性:一旦事务提交,所做的修改就会永久保存到数据库中
  • 隔离性有4个隔离级别:
    1. ru读未提交,可能会读到其他事务未提交的数据,也叫脏读
    2. rc读已提交,两次读取结果不一致,叫做不可重复读
    3. rr可重复读,MySQL默认级别,每次读取的结果都一样,但是可能产生幻读
    4. 串行,一般不会使用,它会给每一行读取的数据加锁,会导致大量超时和锁竞争的问题

如何实现IOC容器

  • 配置文件配置包扫描路径
  • 递归包扫描获取的.class文件
  • 反射、确定需要交给IOC管理的类
  • 对需要注入的类进行依赖注入

以上是关于找工作好难呀之Java面试题总结(不断总结中)的主要内容,如果未能解决你的问题,请参考以下文章

Java面试题总结(不断更新中)

拥有社交牛逼症的我,还是觉得字节面试好难呀

2019滴滴java面试总结 (包含面试题解析)

2021阿里Java高级面试题总结,工作感悟

Java后台开发面试题总结

最全Java面试题+超详细总结(上)