2022 java 精简面试题

1. JDK 和 JRE 有什么区别?

        jre为java runtime enviroment 即java运行时环境,当只需要运行java程序时有jre环境即可满足。jdk为java develomen kit java开发工具包,内置除了包含jre环境之外,还包含java开发环境。

2. == 和 equals 的区别是什么?

        == 对于基本类型(byte short char float double int long boolean )为值比较;对于应用类型比较的是是否为同一个引用地址,即内存中开辟的是否为同一个对象。

        在java Object 类中 equals 函数使用的 ==进行判断,但是基本大多数对象都对equals进行了重写,比如String类型,equals内部为判断两个字符串是否相等,内存中两个相同的字符串equals为true。

3. 两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?

        hashcode 和 equals 都可以进行复写,两者并没有直接关系。在hashMap,hashTable ,HashSet 中即便hashcode值一样,也会进行碰撞处理,同一hashcode 值会进行转换链表或者超过8个转换红黑树。

4. final 在 Java 中有什么作用?

        fianl 修饰的类不能被继承,没有子类;修饰的方法不能被复写,修饰的变量必须初始化,且值不能被修改。

5.String 属于基础的数据类型吗?

不属于,属于引用类型。八种基础类型包括byte boolean char short int float long double。

6. Java 中操作字符串都有哪些类?它们之间有什么区别?

        String,StringBuffer,StringBuilder。String 对象值的频繁更新每次都在内存中会开辟新的空间指向不同的对象。而其他两个会在初始化的对象上进行修改,内存地址为同一个;

        StringBuffer 为线程安全的,StringBuilder为非线程安全的。

7. String str="i"与 String str=new String("i")一样吗?

        =“i”的还在常量池中查找有没有存在值一样的有指向该常量,没有新开辟一个;而new String("i") 会直接在堆内存中直接开辟一个空间。

8. 普通类和抽象类有哪些区别?

        普通类可以直接new操作,抽象类不可以;普通类不能有抽象方法,抽象类可以有抽象方法和普通方法。

9. 抽象类能使用 final 修饰吗?

        不能,抽象类是需要有子类进行继承的,而final 则表示该类不能被继承,编辑器会提示非法修饰符组合错误。

10.接口和抽象类有什么区别?

        接口是定义一些子类通用的一些共有方法。抽象类是java类的一种 类被abstract修饰,方法可以有正常方法和抽象方法。抽象类里面的方法修饰符可以是任意的,接口类的方法修饰符都是public的。

11. BIO、NIO、AIO 有什么区别?

        BIO是Block IO缩写及同步阻塞IO,特点模式简单使用方便,并发处理能力低。有一个写数据的,就对应唯一一个读数据的。

        NIO是Non-Blocking IO缩写,即同步非阻塞IO,特点通过Channe(通道)通讯,实现了多路复用。并发性比BIO好。

        AIO 是 异步非阻塞IO,异步IO的实现基于事件和对调机制来实现。

举例:BIO类似下五子棋 一个棋盘上有两个人 一对一,一个人在下棋的时候,另一个人必须坐在那里等着这个人落子后在进行自己出棋。而NIO的话类似一个高手和三个菜鸟同时下棋,高手在轮询看那个棋桌上该自己下了去下一子,然后去其他棋桌看有没有对方下了的该自己下棋的,没有就继续轮询看那个桌子上有可以自己下棋的任务一样。AIO的话则是在NIO的基础上 高手在一旁忙自己的事情,当三个菜鸟谁下完了谁喊一声,高手听到了 过去到谁棋桌上下一子,在然后忙自己事情,然后等有人再喊他去下棋。

容器篇

12. Java 容器都有哪些?

        java容器大的分为存储对象的集合Collection和存储兼职对的Map两大类。集合下面又分为存储有序的元素可重复的List和存储无序元素不可重复的Set。List主要的实现有ArrayList和LinkedList以及Vector和Stack。Set主要实现有Hashset和TreeSet;Map的实现主要有HashMap、LinkedHashMap、TreeMap、Hashtable(保留类,不建议用)、ConcurrentHashMap。

 13. Collection 和 Collections 有什么区别?

        Collection 为以及和接口类,Collections为集合工具类。与Collections 相似的类还有Arrays。

14. HashMap 和 Hashtable 有什么区别?

        HashMap运行key和value为空,而Hashtable都不允许。HashMap为线程不安全的,Hashtable为线程安全的,不过现在不建议使用Hashtable,推荐使用ConcurrentHashMap。

15. 如何决定使用 HashMap 还是 TreeMap?

        由于HashMap底层key使用的数组存储,通过计算key的hash值来进行确定存入的位置,所以插入,删除,查询效率比较高。TreeMap的key使用红黑树结构存储所以进行有序遍历时效率能高一些,当需要进行有序遍历是选择TreeMap。其他可以选择HashMap。

16. 说一下 HashMap 的实现原理?

        通过源码分析 HashMap底层使用数组存储,默认长度为16。当存入对象时通过对key进行计算出Hash值。再根据hash值计算出在数组中的index位置。当数组中容量超过默认的负载因子0.75时会进行数量2倍方式进行扩容,扩容后会重新计算存储位置。当两个元素的存储位置相同后 当同一位置元素的个数少于8个时,这八个元素以链表形式存储,当超过八个时 则结构改为以红黑树结构存储。

17. 说一下 HashSet 的实现原理?

        hashSet 基于HashMap中对key的操作原理实现。其存储数据为HashMap,key即为添加的值,Value为虚拟固定的对象Object。当有添加add操作时 调用的为HashMap的add方法。删除remove调用的为HashMap的remove方法。HashSet不允许添加重复的key值。
18. ArrayList 和 LinkedList 的区别是什么?

        arrayList 底层使用动态数组实现,LinkedList基于双向链表实现,在查询效率上ArrayList效率高于LinkedList,在新增删除操作上链表效率高于ArrayList。

19. 如何实现数组和 List 之间的转换?

        数组转list使用Arrays.asList(array)进行转换,list转array 使用List自带的toArray()方法。

20. ArrayList 和 Vector 的区别是什么?

        arrayList是线程不安全的,vector是线程安全的,arrayList的性能高于vector。当需要扩容时ArrayList一次扩容当前容量的50%,而vector扩容1倍。

21. 数组 和 ArrayList 有何区别?

        数组可以存储基本类型数据,而ArrayList只能存储对象类型。array是固定长度大小的,ArrayList是动态扩容的。

22. 哪些集合类是线程安全的?

        vector,Stack,HashTable,ConcurrentHashMap(HashTable的代替对象) 为线程安全的。(字符串操作类StringBuffer为线程安全的)

23. 迭代器 Iterator 是什么?

        Iterator 为集合类中的一个迭代器对象,通过集合.iterater()方法返回。可以通过 it.hasNext() 以及it.next()方法进行获取元素迭代,可以通过it.remove()方法删除最后获取到的对象。当在迭代过程中 如果进行添加删除时会抛出ConcurrentModificationException异常。

24. Iterator 和 ListIterator 有什么区别?

        iterator可以遍历所有list和set集合,而ListIterrator只能遍历List集合。iterator只能单向遍历,而listiterator可以双向遍历,以及添加元素,替换元素,获取前后元素的索引位置。

25. 怎么确保一个集合不能被修改?

        可以使用Collections.unmodifiiableCollection(Collection c)方法将集合转换返回一个只读集合,这样修改集合任何操作都会抛出Java.lang.UnsupportedOperationException异常。

多线程

26. 线程和进程的区别?

        一个程序可以包含多个进程。每个进程可以有多个线程。

27. 守护线程是什么?

        守护线程是也是线程的一种,与普通线程不同的是JVM程序在退出时不会考虑是否有运行中的守护线程。反过来讲就是当最后一个非守护线程退出后JVM进行退出(此时即便有守护线程赵照样进行退出)。java创建守护线程方式为在start方法前通过thread.setDaemon(true);

28. 创建线程有哪几种方式?

        创建线程有三种实现方式。

        1,继承Thread类重写run方法;

        2,实现Runnable接口;

        3,实现Callable接口;

29. 说一下 runnable 和 callable 有什么区别?

        实现runnable接口需要实现run方法,实现callable接口需要实现call方法。run方法无返回值,call方法有返回值。实现call方法后使用  线程池类方法 <T> Future<T> java.util.concurrent.ExecutorService#submit(java.util.concurrent.Callable<T>)

进行提交后返回 Future对象,通过对象的get方法(阻塞方法)进行等待返回结果。

30. 线程有哪些状态?

        7中状态分别为 1新建状态(New),2就绪状态(Runnable),3运行状态(Running),4阻塞状态(Blocked),5等待状态(Waiting),6睡眠等待状态 (timed Waiting),7终止状态(treminated)

过程:新创建一个线程后,处于新建状态。当启动线程后,线程进入到就绪状态。当线程获取到资源后进入到运行状态,在线程等待锁的过程处于阻塞状态获取到锁后进入到就绪状态。当线程执行了wait操作有进入到等待状态,在被其他线程唤醒后或wait时间到后有进入到就绪状态获取资源后进入到运行状态,当执行了sleep操作后线程进入到睡眠等待中。当线程运行结束后进入到终止状态。

31. sleep() 和 wait() 有什么区别?

        sleep为线程对象的方法,执行后进入到睡眠等待状态,睡眠时间结束后进入到就绪状态。wait为Object对象的方法,执行后线程处于等待状态。需要被 notify()/notifyAll()进行唤醒。

        sleep不释放锁,wait释放锁。

32. 线程的 run() 和 start() 有什么区别?

        start方法用于启动线程,而run方法用于执行线程运行时代码。 run方法可以重复调用,而start方法只能调用一次。

33. 创建线程池有哪几种方式?

        使用ThreadPoolExecutor 根据不同参数可以创建直接提交任务队列、有界任务队列、无界任务队列、优先任务队列。

        另外可以使用上面创建方式的封装好的方法Executors.newSingleThreadExecutor()、newCachedThreadPool()、newFixedThreadPool(int nThreads)、newSingleThreadScheduledExecutor()、newScheduledThreadPool()、newWorkStealingPool(int parallelism)进行创建;

34. 线程池都有哪些状态?

        Running,Shutdown、Stop、Tidying、Terminated

35. 线程池中 submit() 和 execute() 方法有什么区别?

        execute只能执行Runnable类型任务,submit可以执行Runnable的还可以执行Callable的。

36. 在 Java 程序中怎么保证多线程的运行安全?

        使用锁机制,如synchronized的自动锁,或者手动添加锁Lock对象。以及多使用java.util.concurrent下的类对象。

36. 在java中强软弱虚引用类型的区别

强引用:一般代码中写的 new对象 即为强引用,除非对对象赋值null,才会被垃圾回收机制回收。即使OOM也不会被回收。

软引用(SoftReference): SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]); 使用softReference.get() 获取。当内存不足时会进行回收。

弱引用(WeakReference):写法与软引用一样,只不过当垃圾回收器发现为弱引用后都会进行回收。

虚引用(PhantomReference):任何时候都可能会被垃圾回收机制回收。

37. 什么是死锁?怎么防止死锁?

        两个线程相互持有对方所等待释放的锁资源时,并且都在等待对方释放锁时,两个线程都进入到死锁状态。为防止死锁,可以使用代码进行同步代码管理如Lock接口。并尽量在加锁时设置失效时间。

38. ThreadLocal 是什么?有哪些使用场景?

       threadLocal 是在每个线程上面创建的一个线程私有容器。在线程的整个声明周期中都可以进行设置和获取变量信息的一个线程变量工具,用户每个线程内部不同地方进行参数传递获取,以及防止多线程操作同一数据引起的线程安全问题。

        场景:多线程操作数据库时,每个线程都有自己的connection连接信息;web中session的管理。

39. synchronized 和 volatile 的区别是什么?

        synchronized可以修饰方法,代码块。volatile只能修饰变量。synchronized可以保证可见性原子性,而volatile只能保证可见性。

 40.synchronized 和 Lock 有什么区别?

        synchronizd 可以给方法(普通方法与静态方法)代码块加锁,Lock只能给代码块加锁(使用lock在方法首尾加效果呵和给方法加一样),synchronized 不用考虑释放锁,Lock需要手动去释放解锁。

41. synchronized 和 ReentrantLock 区别是什么?

        synchronized是一个自动控制加锁的修饰符,而ReentrantLock是Lock的一个实现类,需要手动进行代码加锁解锁。

42. 说一下 atomic 的原理?

       atomic 主要利用 CAS (Compare And Wwap) 和 volatile 和 native 方法来保证原子操作,从而避免 synchronized 的高开销,执行效率大为提升。

43. 什么是反射?

        在程序运行的过程中,可以通过代码获取一个类的所有属性和方法,以及相关注解信息,以及通过类对象进行创建出一个对象实例来。以及通过实例对象来设置属性或执行方法。这种通过代码来操作类以及对象实例的方式称为java语言的反射机制。

44. 什么是 Java 序列化?什么情况下需要序列化?

        序列化指的将一个对象中的数据信息以及对象数据类型,以及对象的类型信息被转换为一个字节序列,这个过程称为序列化。一般字节序列化后可以被写入文件或者通过网络传输。讲序列化后的字节信息反向生成对象,反向生成过程称为反序列化。

写入文件中,以及网络传输时需要被序列化(socket)。(http请求也会进行序列化(RestTemplate 使用的为jackson进行了序列化))

45. 动态代理是什么?有哪些应用?

         在运行过程中对被代理对象生成一个代理类。spring aop 的切面实现就是通过动态代理实现(不同对象使用不同的处理方式,jdk动态代理或者CGLib代理)。

46. 怎么实现动态代理?

        通过接口方式实现的JDK原生动态代理(Proxy.newProxyInstance)。或者通过继承当前类子类实现的CGLib方式的动态代理

47. 为什么要使用克隆?

        new出来的对象所有属性值都是初始化值,当我们需要创建一个新的对象的时候并且让其属性与当前一个对象属性都一致时,则可以通过克隆的方式实现。

48. 如何实现对象克隆?

        1,通过实现Cloneable接口,然后重写接口中的clone()接口。2通过序列化和反序列化实现克隆。

49. 深拷贝和浅拷贝区别是什么?

         深拷贝为复制对象后 改对象中的引用对象也被重新开辟空间进行复制。而浅拷贝只复制了他本身和基本类型的属性,而引用类型的属性仍和被拷贝对象中属性指向同一个引用对象。 

       JavaWeb

50. session 和 cookie 有什么区别?

        session是服务器技术存储于服务端,而cookie是客户端技术,存储于浏览器上。cookie为浏览器在请求网站时会携带当前网站之前设置存在在浏览器端的cookie信息。session为用户使用浏览器第一次请求到网站后会创建一个session信息,之后可以在服务端session中进行读写存储信息。

cookie的容量和大小都有限制而session不存在大小限制。

cookie安全性一般,存在被伪造和修改,常见的csrf请求跨站点伪造问题。

51.说一下 session 的工作原理?

当用户第一次访问某网站时,页面发起请求到后台后,后台判断是有包含有session_id,当没有时,则会创建一个session_id存放在用户的cookie中。当下次请求在进来的时候会携带之前返回存储在cookie中的session_id。后台会在内存或者配置的其他存储session的存储区中根据session_id获取之前的session信息,进行读写操作。

52. 如果客户端禁止 cookie 能实现 session 还能用吗?

        可以,当用户禁用了浏览器cookie后,只要前台在发送请求的时候在请求的参数中添加sessionid参数也可以后台识别进行session的读写操作。

53. 如何避免 SQL 注入?

        使用预处理 PreparedStatement,如mybatis的#{}编译后的实现方式。在后台代码逻辑层进行特殊字符过滤。

54. 什么是 XSS 攻击,如何避免?

        xss为跨站点脚本攻击。用户通过表单等方式将一些脚本等内容插入到后台数据库中,在页面显示用户的输入内容时解析了恶意代码导致页面结构破坏或者执行js脚本进行重定向或者进行其他危险操作。预防XSS需要在后端接口内对用户传入的内容做过滤处理。

55. 什么是 CSRF 攻击,如何避免?

        csrf全程为跨站金请求伪造,一般为用户登录了存在漏洞的网站A,在打开了危险网站B,在B网站页面上存在恶意请求A网站的请求,当在B网站发起A网站后台的请求时会携带A网站的cookie信息,A网站根据cookie信息无法知晓当前请求为B网站页面所发起,构成了请求伪造操作。

避免CSRF可以在后台校验发起请求的来源referer.或者在实现前后台交互时增加token信息校验。

猜你喜欢

转载自blog.csdn.net/liuhenghui5201/article/details/125902584
今日推荐