Java常用面试题及答案(贴近实战版).docx

Java常用面试题及答案(贴近实战版).docx

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多

Java常用面试题及答案(贴近实战版)

1.说下Java面向对象的三大特性?实际开发中怎么用?

三大特性是封装、继承、多态。

封装:把属性藏起来(用private修饰),只通过get/set方法暴露操作,避免数据被随意修改。比如实体类User,id、name设为private,要改name必须走setName(),还能在方法里加校验(比如name不能为空)。

继承:用extends抽共性,减少重复代码。比如AdminUser和普通User都有id/name,就让AdminUser继承User,再加个role属性就行,不用重复写get/set。

多态:同一个方法在不同对象上有不同实现,常用接口或抽象类实现。比如定义Pay接口有pay()方法,支付宝、微信支付分别实现它,调用时不管是Alipay还是WechatPay,直接用Pay类型调用pay(),后续加新支付方式也不用改调用代码。

2.String、StringBuffer、StringBuilder有啥区别?实际选哪个?

核心差在可变性和线程安全:

String:不可变(底层char数组是final的),每次拼接都会新生成对象。比如循环里拼字符串,用String会产生一堆临时对象,容易OOM,实际开发里绝对要避免。

StringBuffer:可变,加了synchronized锁,线程安全,但效率低。一般只有多线程共享字符串拼接(比如日志收集)才用,单线程别用。

StringBuilder:可变,没锁,效率高。单线程场景(比如业务逻辑里拼SQL、拼返回信息)优先用,日常开发中90%的字符串拼接都是它。

3.ArrayList和LinkedList怎么选?实际场景举例

底层结构决定用法,别死记“查多用ArrayList,改多用LinkedList”,要懂原理:

ArrayList:底层是动态数组,查数据(get(index))直接算下标,快;但插/删数据(比如在中间插)要移动后面的元素,慢。

实际场景:比如做商品列表展示,大部分时候是查列表,偶尔增删末尾元素,用ArrayList。

LinkedList:底层是双向链表,查数据要从头/尾遍历,慢;但插/删只改前后节点的指针,快。

实际场景:比如做消息队列,频繁在头部取消息、尾部加消息,用LinkedList更高效。

另外注意:ArrayList默认初始容量10,满了会扩容1.5倍,实际用的时候如果知道大概大小,最好初始化时指定(比如newArrayList(100)),减少扩容开销。

4.synchronized和volatile有啥区别?分别用在哪?

两者都是解决线程安全问题,但侧重点不同:

synchronized:是“锁”,能保证原子性、可见性、有序性。比如卖票场景,多线程抢票,用synchronized修饰卖票方法,能保证同一时间只有一个线程执行,不会超卖。但它是重量级锁(JDK1.6后有锁优化),效率比volatile低。

volatile:是“内存可见性”关键字,只能保证可见性和有序性,不能保证原子性。比如一个线程改了变量,另一个线程能立刻看到最新值,避免缓存不一致。用在单线程写、多线程读的场景,比如状态标记(booleanisStop),主线程改isStop=true,子线程能立刻看到并停止,比用synchronized轻量。

举个坑:别用volatile修饰i++,因为i++是“读-改-写”三步,volatile管不了原子性,多线程下会算错,得用AtomicInteger或者synchronized。

5.线程池的核心参数有哪些?实际怎么配置?

核心参数有5个,得结合业务场景配,不是固定值:

核心线程数(corePoolSize):线程池长期维持的线程数,忙完也不销毁。

最大线程数(maximumPoolSize):线程池最多能创建的线程数。

空闲时间(keepAliveTime):非核心线程空闲多久后销毁。

阻塞队列(workQueue):任务满了先存这,等线程空闲再处理。

拒绝策略(handler):队列和线程都满了,怎么处理新任务(比如抛异常、丢弃oldest任务)。

实际配置举例:

CPU密集型任务(比如计算):核心线程数设为CPU核心数+1(比如4核CPU设5),因为CPU满负荷跑,多1个线程能应对偶尔的阻塞。

IO密集型任务(比如查数据库、调接口):核心线程数设为2*CPU核心数(比如4核设8),因为线程大部分时间在等IO,多开线程能提高

文档评论(0)

151****9429 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档