Java-八股文

发布时间 2023-07-07 20:48:36作者: 356a
  1. hashcode()、equals()
  2. 1.如果hashcode()不相同,两个对象一定不是同一个对象
    2.如果hashcode()相同,两个对象不一定上同一个对象,需要进一步判别equals
    3.如果equals相同,应当认为两个对象就是相同对象
    由于hashcode方法仅返回一个值,equals里面有若干逻辑,因此,部分集合类的判断中,会优先判断hashcode,如果相同再继续equals判断
    结论:如果改写了equals方法,则必须改写hashcode方法,以便于逻辑一致
    
  3. string、stringbuffer、stringbuilder
  4. string:常量,每次修改都会创建新的字符串常量
    stringbuffer:线程安全的字符串变量
    stringbuilder:不安全的字符串变量
    
  5. extends、super
  6. <? extends T>:?是T的子类
    <? super T>:?是T的基类
    
  7. == 、 equals
  8. ==:基本类型-看值;引用类型-看引用地址
    euqals:看各种类的重写逻辑[逻辑里面也有可能复用==]
    
  9. 重载、重写
  10. 重载:针对单一类中,相同方法名,不同方法签名
    重写:针对父子类,相同方法名,相同方法签名
    重写:返回值类型、抛出异常都必须小于等于父类;访问修饰符大于等于父类
    
  11. list、set
  12. list:有序,可重复,允许多个null,支持下标随机访问
    set:无序,不可重复,单一null,必须遍历访问
    
  13. arraylist、linkedlist
  14. arraylist:基于数组实现,有利于查找、修改,不利于插入、删除[适用场景不同]
    linkedlist:基于链表实现,有利于插入、删除,不利于查找、修改[适用场景不同]
    
  15. concurrenthashmap扩容机理
  16. 1.7之前:基于segment分段hashmap存储实现的,segment分段存储部分不扩容,仅内部的hashmap进行扩容[哪个线程对应的内部hashmap需要扩容,哪个线程就负责做这个事情]
    1.8之后:不是基于segment分段存储实现的,所有的K-V对都包含在一个map中,只是扩容的时候,那就每个子线程都参与扩容
    
  17. JDK版本变迁,hashmap的主要变更
  18. 1.7:底层是数组+链表,哈希算法复杂
    1.8:底层是数组+链表+红黑树,由于引入红黑树,哈希算法得到简化,从而优化hashmap的插入、查询效率
    
  19. hashmap的put方法
  20. 大体流程:
    1.依据key和哈希算法计算下标
    2.如果下标位置为空,则封装成对象(1.7:entry对象,1.8:node对象),放置该位置
    3.如果下标位置不空,
    3.1 JDK1.7:判断是否需要扩容,然后,头插法插入到对应位置的链表中
    3.2 JDK.8:判断是红黑树节点还是链表节点,然后插入到hashmap里面,最后判断扩容
    3.2.1 红黑树节点:将KV对封装成红黑树节点,加入到红黑树中
    3.2.2 链表节点:尾插法插入到对应位置的链表中,如果多于等于8个节点,将链表转为红黑树
    
  21. 深拷贝与浅拷贝
  22. 浅拷贝:基本数据类型拷贝了第二份,引用类型的变量全部都是拷贝了一份引用地址,指向了原来的地方。
    深拷贝:所有数据类型都拷贝了第二份,不仅仅拷贝引用地址。
    
  23. hashmap扩容机理
  24. 1.7:生成新数组,遍历原数组上的每个链表,将内部数据逐个转移至新数组
    1.8:生成新数组,遍历原数组上的每个链表与红黑树
    ①如果原数组上是链表,遍历每个元素,重新计算下标并转移
    ②如果原数组上是红黑树,遍历每个元素,重新计算下标并转移,有冲突再购建链表与红黑树
    
  25. copyonwriteArrayList
  26. 线程安全的arrayList,底层也是用数组实现的,主要集中在读与写操作上
    读:由于读写分别在老新数组上,因此,互相不干扰,也因此,读的性能不会受写的性能影响[适用于读多写少]
    写:写操作会生成新数组,在完成之前,其他线程无法进行写操作[上了锁,线程安全];在完成之前,读的是原数组,写的是新数组,两者是不会互相干扰的。
    
  27. 字节码
  28. 定义:字节码文件是Java源码编译过后的一种格式,各个平台上相同的源码编译出的字节码是相同的,但是,字节码转化的机器码不相同,这个转化上JDK(JRE)做的,因此,Java上跨平台语言
    相当于编译过程所指的,中间代码[前有词法分析、语法分析、语义分析][后有代码优化、目标代码生成]
    优点:实现了语言的跨平台;编译过程可以做代码优化,提高执行效率
    
  29. Java异常体系
  30. graph TD; Throwable --> Exception Throwable --> Error Exception --> RuntimeException Exception --> 非RuntimeException

    error是非常严重的错误,程序已无法正常运行,没必要捕获
    运行时异常,一般是逻辑问题,应尽量避免
    非运行时异常,不处理无法正常运行,必须处理

  31. 什么时候抛异常?什么时候捕获异常?
  32. 抛:自身无法处理就往上抛,由上级处理
    捕获:自身能处理就捕获,捕获走既定处理流程

  33. 类加载器
  34. graph TD; bootstrapClassLoader负责加载JAVA_HOME下lib里面的jar包与类文件 --> ExtClassLoader负责加载JAVA_HOME下lib下ext里面的jar包与类文件 --> AppClassLoader负责加载classpath路径下的类文件
  35. 类加载器的双亲委派模型
  36. 由16可知,类加载器共三个,AppClassLoader有两个父类
    当AppClassLoader加载时,会优先调用父类的加载器,这种JVM机制叫做双亲委派模型
    AppClassLoader.loadClass(){
      ExtClassLoader.loadClass(){
        bootstrapClassLoader.loadClass();
      }
    }
    
  37. 线程共享区
  38. ![](https://img2023.cnblogs.com/blog/3090785/202306/3090785-20230628171602882-13131299.png)
    堆区与方法区是所有线程共享的
    栈区:主要存放基本数据类型与对象引用(仅限局部变量,成员变量不管是不是基本数据类型都存放于堆)
    堆区:主要存放对象实例与数组[我的理解就是,由代码操作生成的对象或者说引用类型存放于堆]
    方法区:类信息(class文件)、静态变量与静态方法
    本地方法栈:非静态方法
    
  39. 如何排查JVM问题-※
  40. 空间:jmap 查看 JVM各个区域的占用情况,查看是否栈区过大?是否堆区过大?
    时间:jstack 查看线程的运行情况,是否存在死锁或者阻塞?
    OOM:
    查看: jstat 查看垃圾回收情况,fullgc 与 younggc 的运行情况
    记录: JVM启动参数 --> -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/base,发生OOM的时候记录下当时的情况-dump文件,便于回溯定位问题
    分析:jvisualvm 可以针对dump文件进行分析异常对象,异常线程
    
  41. 从加载JVM到GC清理,一共经历什么过程-√
  42. 1.方法区加载字节码,加载静态方法、静态成员变量
    2.堆区创建实例化对象,保存至 年轻代 Eden 区
    3.将引用传回栈区
    4.经过minor GC,对象每次存活,年龄加一,并迁移至survival区-存活区,年龄大于等于15的时候,对象进入老年代
    5.栈区的引用被移除以后,对象最终被GC回收
    
  43. 如何确定对象是否需要回收
  44. 根可达算法:所有对象都是基于一个根对象上的,从根对象开始遍历,能找到引用的就是还需要的对象,否则就是不需要的对象。
    
  45. JVM垃圾回收机制
  46. 总共三种算法:
    标记:将所有对象判断是否根可达,将不可达对象标记并进行删除
    缺点:会有碎片空间出现
    
    复制法:申请一块与当前存储空间相同的空间,根可达算法标记所有存活对象,将存活对象迁移至新申请空间,迁移完毕以后,原空间统一清空
    缺点:需要的空间较大
    
    标记优化法:根可达算法标记所有存活对象,并将存活对象重新排列至连续空间,标记以及迁移排列完毕以后,将存活对象连续空间以外的空间统一清除
    
  47. 什么是STW
  48. STW,stop the world,即,在GC运行过程中,要将所有Java进程冻结,以便于GC进程进行垃圾回收。
    
  49. arraylist
  50. arraylist
  51. arraylist
  52. arraylist

参考:

  1. https://blog.csdn.net/liwenxiang629/article/details/109508530
  2. https://blog.csdn.net/weixin_43235210/article/details/90444710?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-90444710-blog-109508530.235%5Ev38%5Epc_relevant_sort&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-90444710-blog-109508530.235%5Ev38%5Epc_relevant_sort&utm_relevant_index=2