- 1、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
Java笔试面试题及答案(实战版)
一、基础语法与API
问题:equals()和==的区别?举个实际开发中容易踩坑的例子。
答案:==是运算符,比较基本类型时比值(如inta=1和intb=1),比较引用类型时比内存地址;equals()是Object类的方法,默认实现就是==(比地址),但像String、Integer等类重写了equals(),改成比内容。
踩坑例子:比如用newString(abc)创建两个对象,s1==s2会返回false(地址不同),但s1.equals(s2)返回true(内容相同)。如果自己定义的实体类没重写equals(),用equals()比较两个对象时,其实还是比地址,容易误以为在比属性。
问题:String、StringBuilder、StringBuffer的区别?什么时候用哪个?
答案:核心是线程安全和可变性:
String不可变(底层char数组被final修饰),每次拼接都会新生成对象,频繁拼接时性能差,适合字符串不常变的场景(如定义常量);
StringBuilder可变,线程不安全,没有同步锁,拼接效率比String高,适合单线程下的字符串拼接(如循环里拼接日志内容);
StringBuffer可变,线程安全(方法加了synchronized),但效率低,适合多线程下的拼接(如多线程日志收集)。
二、集合框架
问题:HashMap的底层结构?JDK1.8做了哪些优化?为什么这么优化?
答案:JDK1.7是“数组+链表”,JDK1.8改成“数组+链表+红黑树”。
优化点:当链表长度超过8,且数组长度=64时,链表转红黑树;当树节点数少于6时,又转回链表。
原因:链表查询时间复杂度是O(n),红黑树是O(logn),数据量大时查询更快;但红黑树维护成本高(要旋转平衡),数据量小时用链表更轻量,所以设了8和6的阈值(这个阈值是基于泊松分布算的,实际开发中很少触发转树,但大数据量场景能明显优化性能)。
问题:ArrayList和LinkedList的区别?ArrayList的扩容机制是什么?
答案:区别主要在底层结构和操作效率:
ArrayList底层是动态数组,查改快(通过索引直接定位,O(1)),增删慢(尤其是中间位置,要移动元素,O(n));
LinkedList底层是双向链表,查改慢(要遍历链表,O(n)),增删快(只需改指针,O(1))。
扩容机制:ArrayList初始容量默认10(JDK1.8),当添加元素时发现容量不够,会扩容到原来的1.5倍(oldCapacity+(oldCapacity1)),然后把旧数组元素拷贝到新数组。如果一开始就知道大概要存多少元素,建议创建时指定容量(如newArrayList(1000)),避免频繁扩容浪费性能。
三、并发编程
问题:线程池的核心参数有哪些?用Executors创建线程池有什么问题?
答案:核心参数有5个:核心线程数(corePoolSize)、最大线程数(maximumPoolSize)、空闲线程存活时间(keepAliveTime)、时间单位(unit)、任务队列(workQueue)。
Executors的问题:比如Executors.newFixedThreadPool()用的是无界队列(LinkedBlockingQueue),如果任务提交太快,队列会一直堆积,最终导致OOM;newCachedThreadPool()最大线程数是Integer.MAX_VALUE,并发高时会创建大量线程,可能导致CPU耗尽。实际开发中要自己用ThreadPoolExecutor构造器定义参数,比如根据业务设置核心线程数,用有界队列(如ArrayBlockingQueue)+拒绝策略(如AbortPolicy抛异常提醒)。
问题:volatile关键字的作用?能保证原子性吗?举个例子。
答案:作用有两个:一是保证可见性(一个线程改了变量,其他线程能立刻看到必威体育精装版值,避免CPU缓存导致的脏读);二是禁止指令重排序(比如单例模式的双重检查,volatile能防止instance=newSingleton()被拆成“分配内存→赋值引用→初始化对象”的乱序执行,避免拿到未初始化的对象)。
不能保证原子性!比如intcount=0,1000个线程各执行1000次count++,最终结果肯定小于1000000,因为count++是“读-改-写”三步操作,volatile没
文档评论(0)