JavaSE面试总结

一.基础

  1. 什么是正则表达式?
    记录文本转换规整的代码。Java中的String类提供了支持正则表达式的方法,如:matches()、replaceAll()、replaceFirst()、split()等。

  2. int和Interger的区别?
    Interger是int的包装类。为了能够将基本数据类型当成对象操作,故引入了包装类

  3. 什么是自动装箱和自动拆箱?
    自动装箱:将基本数据类型转化为对应的包装类型;
    自动拆箱:将包装类型转化为对应的基本数据类型。

  4. String、StringBuffer、StringBuilder的区别?
    · 由于String是被final修饰,故其修饰的字符串长度不可变。而其余二者修饰的字符串长度可变;
    · 由于StringBuffer被synchronized关键字修饰,故其线程安全,而StringBuilder是线程不安全的;
    · 执行效率:StringBuilder > StringBuffer > String

  5. Array和ArrayList的区别?
    · Array:大小是固定的,既可以存储基本类型,也可以存储对象类型;
    · ArrayList:大小是可以动态改变的,只能存储对象类型。

  6. 值传递与引用传递?
    · 值传递:是对基本变量而言,传递的是该变量的一个副本,改变副本不影响原变量;
    · 引用传递:是对对象变量而言,传递的是该对象地址的一个副本,改变引用对象会改变原对象。

  7. jdk1.8的有哪些新特性?
    请参考:https://blog.csdn.net/qq_29411737/article/details/80835658

二. 关键字

  1. synchronized关键字和Lock接口的区别?
    Synchronized:由内置语音实现的,在发生异常时,会自动释放锁,故不会导致死锁;
    Lock接口:在发生异常时,需在finally块中通过unlock()方法释放锁;可让等待锁的线程响应中断。

  2. Synchronized的原理是什么?
    A. 线程进入同步方法中;
    B. 如果进入monitor的线程数为0,则允许该线程进入到monitor中,并将进入数置为1,该线程获取锁成功
    C. 如果该线程已经占有锁,是重新进入,则进入数加1
    D. 该线程可调用wait()进入等待集合,释放监视锁,进入数减1,若进入数为0时则退出monitor
    E. 其他线程调用notify()、notifyAll(),唤醒等待集合中的线程,执行如上步骤

  3. volatile的原理是什么?
    参考1:https://mp.weixin.qq.com/s/MIsQv8ZWWBzfB-Qhg3l4lA
    参考2;https://blog.csdn.net/zezezuiaiya/article/details/81456060

  4. Synchronized锁住了什么?
    修饰普通同步方法:锁住当前实例对象
    修饰静态同步方法:当前类的class对象
    修饰同步方法块:锁住的是synchronized括号里配置的对象

三. 面向对象

  1. Query接口中的list()和iterate()的区别?
    A.List()直接查询数据库,无法利用一、二级缓存,对缓存只写不读,只有在开启缓存查询前提下使用查询缓存;iterate()会先到数据库中把id取出来,遍历时先到缓存中找(可充分利用缓存,如果目标数据只读或者读取频繁,使用其可减少性能开销),若找不到,则以id为条件再发一条SQL到数据库,故若缓存中没有数据,则查询数据库的次数为N+1;
    B.List返回list(对象本身),iterate返回iterator(代理对象)

  2. 什么是反射?
    java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性

  3. 如何通过反射获取和设置对象私有字段值?
    Field f = clazz.getDeclaredField(fs[i]); //通过getDeclaredField()方法获取Field对象
    f.setAccessible(true); //通过field对象的setAccessible(true)将其设置为可访问
    target = f.get(target);
    clazz = target.getClass(); //通过get()/set()方法获取/设置字段值

  4. 如何通过反射创建对象?
    法一:通过类对象调用newInstance()方法
    法二:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象,并调用其newInstance()方法创建对象

  5. 异常
    在这里插入图片描述

  6. 运行时异常和受检异常?
    运行异常:RuntimeException及其子类,即使没有try-catch捕获或者throws抛出,依旧能够编译通过;
    受检异常:除运行异常外的异常均为受检异常,若没有try-catch捕获或throws抛出,则编译无法通过。

  7. Comparable接口和Comparator接口的区别?
    Comparable接口:提供了compareTo()方法,可对两个对象进行排序,通过返回负数、0、正数来表明输入对象小于、等于、大于已经存在的对象。
    Comparator接口:提供了compare()和equals()。
    compare()方法用来给两个输入参数排序。
    equals()用来判断输入参数是否和comparator相等

  8. 什么是泛型?
    即参数化类型。通过类型擦除来实现泛型,如List在运行时只用List表示。

  9. 什么是限定通配符和非限定通配符?
    · <? extends T> : 通过确保类型必须是T的子类来限定类型的上界;
    · <? super T> : 通过确保类型必须是T的父类来限定类型的下界

  10. 多态
    · 什么是多态?
    不同类的对象对同一消息作出响应

    · 多态的分类?
    编译时多态:主要是方法的重载
    运行时多态:也叫动态绑定。即在执行期间判断引用对象的类型,根据实际类型调用相应的属性和方法。

    · 多态的作用?
    消除类之间的耦合关系

    · 多态存在的条件?
    继承、重写、父类引用指向子类对象

    · Java中实现多态的方式?
    接口的实现
    继承父类进行方法重写
    方法的重载

四. 集合

  1. hashMap原理
    hashMap是一个k-v结构,是线程不安全的,底层是数组+链表实现的,使用put(k,v)存储对象到hashMap中,使用get(k,v)从hasMap中获取对象。当我们通过put()方法传递键值对时,键先调用hashCode(),并返回一个hash值,再散列一次,通过hash值对数组长度取余找到数组对应的位置,然后通过遍历链表判断链表中是否有此k,如果链表中已有此k则用新v代替旧v,若没有则插入键值对到链表头。当获取对象时,通过键对象的equals()找到正确的键值对,然后返回值对象。

  2. Hashmap 、cocurrenthsahmap Jdk1.7和jdk1.8的改变?
    Hashmap:
    JDK1.7中HashMap采用了数组+链表的数据结构,有线程安全问题(统计不准确,丢失数据,死循环cpu100%),1.8中HashMap的实现就变成了数组+链表或数组+红黑树。添加元素时,若桶中链表个数超过8,链表会转换成红黑树
    1.8中优化了hash算法(1.7:hash值 & length-1 1.8:扩容前的原始位置+扩容的大小值),并且每次扩容不需要重新计算hash值。

    Cocurrenthsahmap:
    JDK1.7版本的ReentrantLock+Segment+HashEntry,
    JDK1.8版本中synchronized+CAS+HashEntry+红黑树。

  3. hash冲突的解决方法?
    A.开放地址法
    通过探测算法,当某个位置已经被占时,会继续寻找下一个可使用的位置
    B.链地址法
    将hash值相同的对象以链表的形式存放在hash值对应的位置

  4. hashMap出现死循环的原因?
    在并发情况下,发生扩容,可能会产生循环链表,在执行put时,会触发死循环,引起CPU的100%问题,

  5. Cocurrenthashmap和hashmap锁的区别?
    因为cocurrenthashmap将数据分段,分成一段一段的,每一段都加锁,锁分离技术,访问的时候,访问第一段数据,第一段加锁,第二段没有锁,其他线程还是可以访问第二段的数据的,所以比hashmap加锁的效率要高

  6. 什么是Hashtable?
    把所有方法都加上synchronized关键字来实现线程安全。所有的方法都同步这样造成多个线程访问效率特别低

  7. hashMap和hashtable的区别?
    hashMap和是非synchronized的,且允许null值

  8. cocurrentHashMap原理?
    用一个数组存放hashMap,每个数组单元存放一个hashMap,且对每个数组单元进行加锁

五. 线程

  1. 什么是线程?进程?
    线程:线程是CPU调度的最小单位。同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),切换线程开销小。
    进程:进程是资源分配的最小单位。一个进程包含1–n个线程,每个进程都有独立的代码和数据空间,切换进程开销大。

  2. 什么是多线程?多进程?
    多线程:同一程序中有多个顺序流在执行
    多进程:操作系统能够同时运行多个任务(程序)

  3. 线程和进程有哪些状态?
    创建、就绪、运行、阻塞、终止

  4. 创建多线程的方式?
    A.继承Tread类
    B.实现Runable接口
    C.实现callable接口,且与线程池、Future结合使用

  5. Runable和Callable的区别?
    Callable的call()可以返回值和抛出异常,可返回装载有计算结果的Future对象;
    Runable的run()则没有这些功能

  6. 多线程的作用?
    A.发挥多核CPU的优势
    B.防止阻塞
    C.便于建模

  7. 如何保证线程安全?
    A.通过合理时间调度,避开共享资源的存取冲突
    B.并行任务设计时,尽可能保证任务与任务间不存在共享资源
    C.客户的计算工作和数据访问尽可能让一个线程独立完成

  8. 线程间的通信方式?
    A.Volatile和synchronized
    B.等待/通知机制
    C.管道输入/输出流
    D.Tread.join()

  9. start()和run()?
    start():start()方法让一个线程进入就绪队列等待分配cpu,分到cpu后才调用实现的run()方法。
    run(): 不同线程里面的run()交替执行,若只调用run(),则代码还是同步执行,必须等待一个线程执行完run()方法体代码,另一个线程才能执行此方法体代码

  10. sleep()和yeild()的区别?
    sleep():给其他线程运行机会时不考虑优先级;执行该方法后进入阻塞状态
    yeild():只给相同或者更高优先级的线程;执行该方法后进入就绪状态

  11. 为什么要用join()?
    若主线程需要用到子线程的处理结果,则需保证子线程结束后,主线程才能结束

  12. 多线程的上下文切换?
    CPU的控制权由一个正在运行的线程切换到另一个就绪并等待获取CPU执行权的线程

  13. 一个线程运行时发生异常会怎样?
    如果异常没有被捕获该线程将会停止执行。Thread.UncaughtExceptionHandler是用于处理未捕获异常造成线程突然中断情况的一个内嵌接口。当一个未捕获异常将造成线程中断的时候JVM会使用Thread.getUncaughtExceptionHandler()来查询线程的UncaughtExceptionHandler并将线程和异常作为参数传递给handler的uncaughtException()方法进行处理。

  14. Java中线程调度算法是什么?
    抢占式。一个线程用完CPU后,操作系统会根据线程的优先级、饥饿情况等算出一个总的优先级,并分配一个时间片给某个线程

  15. Tread.sleep(0)?
    为了让优先级较低的线程也能够获得CPU的控制权

  16. 什么是自旋?
    因synchronized里的代码执行很快,故不必让等待锁的线程直接进入阻塞,而是在synchronized的边界做忙循环,即为自旋。若多次忙循环后依旧未获得锁,再进入阻塞。

  17. 什么是CAS?
    Compare and Swap,即比较-替换。假设有三个数:内存值V,旧的预期值A,要修改的值B,当且仅当A、V相同时,才能将V修改为B,返回true,反之则反之

  18. 什么是AQS?
    Abstract Queued Sychronizer,即抽象队列同步器。

    重要组成:同步队列、用int成员变量state表示同步状态

    核心思想: 若请求的共享资源空闲,则将当前请求的线程设置为有效的工作线程,并将共享资源设置为锁定状态。
    若请求的共享资源被占用,则将该线程加入到队列中。

    实现思路:
    a. 首节点是获取同步状态成功的节点
    b. 未获取到锁的线程,将在尾部创建一个节点,将此线程放到尾节点
    c. 首节点的线程释放锁时,将唤醒后继节点

    在这里插入图片描述

  19. 什么是semaphore?
    即信号量。限制某段代码块的并发数。它有一个构造函数,可传入一个int的n,表示最多只能有n个线程可同时访问,若大于此线程数n,则需要等待。当n=1时,相对于一个synchronized。

  20. Hashtable中的size()方法中只有一句“return count”,为什么还要同步?
    A.若线程A访问put()时,完成了数据的添加,但还没执行size++,此时线程B调用了还未更新的size(),导致size不正确。
    B.CPU执行代码,执行的不是java代码。假设return count被翻译成三句汇编代码,则有可能只执行一句,线程就切换了。

发布了25 篇原创文章 · 获赞 1 · 访问量 427

猜你喜欢

转载自blog.csdn.net/qq_44837912/article/details/103793952