没有合适的资源?快使用搜索试试~ 我知道了~
首页Java面试精华:理解跨平台性与运算符差异,深入解析构造器
Java面试精华:理解跨平台性与运算符差异,深入解析构造器
需积分: 9 0 下载量 52 浏览量
更新于2024-07-09
收藏 2.9MB PDF 举报
"Java面试宝典涵盖了Java编程的基础概念,帮助求职者准备面试。首先,章节深入浅出地解释了Java的跨平台性,这是Java的一大特性,其原理基于Java虚拟机(JVM),使得编写在Java上的程序可以在不同的操作系统上运行,只需对应JVM即可。理解这一点对于面试者来说至关重要,因为它展示了Java的灵活性和广泛适用性。 章节中对比了&和&&这两个运算符,&用于按位与运算,而&&则是逻辑与,具有短路性质。在实际编程中,比如用户登录验证时,应使用&&来避免NullPointerException,因为当左侧表达式为false时,右侧表达式不会执行。这种区别在面试中经常被问及,考察的是程序员对运算符的理解和正确运用。 关于构造器(Constructor),面试者需要知道它们是用于创建类实例并初始化的特殊方法,尽管不能被继承和重写(Override),但可以通过重载(Overload)提供多种初始化方式。Java在创建对象时,会先执行默认或显式指定的构造器,包括分配内存、初始化成员变量、调用父类构造器等步骤。理解构造器的工作机制有助于面试者解答关于类实例化和继承的相关问题。 此外,还涉及到了Java对象生命周期中的一些关键环节,如对象空间的分配、初始状态、参数绑定以及调用父类构造器的过程。这些基础知识不仅在面试中起着关键作用,也是日常编程中不可或缺的部分。掌握这些细节,求职者可以更好地展示自己的技术实力和对Java编程的深入理解。"
资源详情
资源推荐
的链表,这个时候 HashMap 就相当于一个单链表,假如单链表有 n 个元素,遍历的时间复
杂度就是 O(n),完全失去了它的优势。针对这种情况,JDK 1.8 中引入了 红黑树(查找时
间复杂度为 O(logn))来优化这个问题。
4. IO
4.1. Java 中如何实现序列化,有什么意义?
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对
流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象
流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。
要实现序列化,需要让一个类实现 Serializable 接口,该接口是一个标识性接口,标
注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过
writeObject(Object obj)方法就可以将实现对象写出(即保存其状态);如果需要反序列化
则可以用一个输入流建立对象输入流,然后通过 readObject 方法从流中读取对象。序列化
除了能够实现对象的持久化之外,还能够用于对象的深度克隆
4.2. Java 中流类的超类主要有那些?
java.io.InputStream
java.io.OutputStream
java.io.Reader
java.io.Writer
4.3. Java 中有几种类型的流?
两种流分别是字节流,字符流。
字节流继承于 InputStream、OutputStream,字符流继承于 Reader、Writer。在 java.io
包中还有许多其他的流,主要是为了提高性能和使用方便。
4.4. 说明缓冲流的优点和原理
不带缓冲的流的工作原理:
它读取到一个字节/字符,就向用户指定的路径写出去,读一个写一个,所以就慢了。
带缓冲的流的工作原理:
读取到一个字节/字符,先不输出,等凑足了缓冲的最大容量后一次性写出去,从而提
高了工作效率
优点:减少对硬盘的读取次数,降低对硬盘的损耗。
4.5. BIO、NIO、AIO 有什么区别?
BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方
便,并发处理能力低。
NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)
通讯,实现了多路复用。
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的
操作基于事件和回调机制。
5. 线程与并发
5.1. 创建线程的方式及实现
1.继承 Thread 类(优点:代码简单 ; 缺点:该类无法集成别的类)
2.实现 Runnable 接口(优点:继承其他类,同一实现该接口的实例可以共享资源;缺点:代码
复杂)
3.实现 Callable 接口(优点:可以获得异步任务的返回值)
4.线程池方式(实现自动化装配,易于管理,循环利用资源)
5.2. 线程池的几种方式
newFixedThreadPool(int nThreads)
创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程
池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而
结束时,线程池会补充一个新的线程
newCachedThreadPool()
创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收 空闲线程,而
当需求增加时,则可以自动添加新线程,线程池的规模不存在任何 限制
newSingleThreadExecutor()
这是一个单线程的 Executor,它创建单个工作线程来执行任务,如果这个线 程异常结
束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的 顺序来串行执行
newScheduledThreadPool(int corePoolSize)
创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似 于 Timer。
5.3. 线程的生命周期
生命周期的五种状态
新建(new Thread)
当创建 Thread 类的一个实例(对象)时,此线程进入新建状态(未被启动)。
例如:Thread t1=new Thread();
就绪(runnable)
线程已经被启动,正在等待被分配给 CPU 时间片,也就是说此时线程正在就 绪队列中
排队等候得到 CPU 资源。例如:t1.start();
运行(running)
线程获得 CPU 资源正在执行任务(run()方法),此时除非此线程自动放弃 CPU 资源或
者有优先级更高的线程进入,线程将一直运行到结束。
死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能 再进入就
绪状态等待执行。
自然终止:正常运行 run()方法后终止
异常终止:调用 stop()方法让一个线程终止运行
堵塞(blocked)
由于某种原因导致正在运行的线程让出 CPU 并暂停自己的执行,即进入堵塞状态。
正在睡眠:用 sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程 在指定
的时间过去可进入就绪状态。
正在等待:调用 wait()方法。(调用 motify()方法回到就绪状态)
被另一个线程所阻塞:调用 suspend()方法。(调用 resume()方法恢复)
5.4. 悲观锁 乐观锁
乐观锁 悲观锁
是一种思想。可以用在很多方面。
悲观锁
悲观锁是指假设并发更新冲突会发生,所以不管冲突是否真的发生,都会使用锁机制。悲观
锁会完成以下功能:锁住读取的记录,防止其它事务读取和更新这些记录。其它事务会一直
阻塞,直到这个事务结束.悲观锁是在使用了数据库的事务隔离功能的基础上,独享占用的
资源,以此保证读取数据一致性,避免修改丢失。悲观锁可以使用 Repeatable Read 事务,
它完全满足悲观锁的要求。
乐观锁
乐观锁不会锁住任何东西,也就是说,它不依赖数据库的事务机制,乐观锁完全是应用系统
层面的东西。如果使用乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数
据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数
据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更
新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息
进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期
数据。
5.5. ThreadLocal 作用和原理分析
ThreadLocal 主要为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部
的副本变量。要理解 ThreadLocal 需要理解下面三个问题:
①、每个线程的变量副本是存储在哪里的?
每个线程都有一个 threadLocals 成员,引用类型是 ThreadLocalMap,以 ThreadLocal 和
ThreadLocal 对象声明的变量类型作为参数。这样,我们所使用的 ThreadLocal 变量的实际
数据,通过 get 函数取值的时候,就是通过取出 Thread 中 threadLocals 引用的 map,然后
从这个 map 中根据当前 threadLocal 作为参数,取出数据。也就是说其实不同线程取到的变
量副本都是由线程本身的提供的,存储在线程本身,只是借助 ThreadLocal 去获取,不是存
放于 ThreadLocal。
②、变量副本【每个线程中保存的那个 map 中的变量】是怎么声明和初始化的?
当线程中的 threadLocals 成员是 null 的时候,会调用 ThreadLocal.createMap(Thread t,
T firstValue)创建一个 map。同时根据函数参数设置上初始值。也就是说,当前线程的
threadlocalmap 是在第一次调用 set 的时候创建 map 并且设置上相应的值的。
在每个线程中,都维护了一个 threadlocals 对象,在没有 ThreadLocal 变量的时候是 null
的。一旦在 ThreadLocal 的 createMap 函数中初始化之后,这个 threadlocals 就初始化了。
以后每次 ThreadLocal 对象想要访问变量的时候,比如 set 函数和 get 函数,都是先通过
getMap(Thread t)函数,先将线程的 map 取出,然后再从这个在线程(Thread)中维护的
map 中取出数据或者存入对应数据。
③、不同的线程局部变量,比如说声明了 n 个(n>=2)这样的线程局部变量 threadlocal,那
么在 Thread 中的 threadlocals 中是怎么存储的呢?threadlocalmap 中是怎么操作的?
在 ThreadLocal 的 set 函 数 中 , 可 以 看 到 , 其 中 的 map.set(this, value) 把 当 前 的
threadlocal 传入到 map 中作为键,也就是说,在不同的线程的 threadlocals 变量中,都
会有一个以你所声明的那个线程局部变量 threadlocal 作为键的 key-value。假设说声明了
N 个这样的线程局部变量变量,那么在线程的 ThreadLocalMap 中就会有 n 个分别以你的线
程局部变量作为 key 的键值对。
5.6. ThreadLocal 如何防止内存泄漏
每次使用完 ThreadLocal,都调用它的 remove()方法,清除数据。
在使用线程池的情况下,没有及时清理 ThreadLocal,不仅是内存泄漏的问题,更严重的是
可能导致业务逻辑出现问题。所以,使用 ThreadLocal 就跟加锁完要解锁一样,用完就需要
清理。
5.7. synchronized 用在静态和非静态方法的区别
当 synchronized 修饰一个 static 方法时,多线程下,获取的是类锁(即 Class 本身,注意:
不是实例),作用范围是整个静态方法,作用的对象是这个类的所有对象。
当 synchronized 修饰一个非 static 方法时,多线程下,获取的是对象锁(即类的实例对
象), 作用范围是整个方法,作用对象是调用该方法的对象
简单说 synchronized 关键字加到 static 静态方法上是给 Class 类上锁,简称类锁(锁的事
当前类的字节码)而加到非 static 静态方法是给对象加锁
6. 网络编程
6.1. 三次握手与四次挥手
第一次握手:
剩余126页未读,继续阅读
JavaCherryTree
- 粉丝: 0
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- C语言快速排序算法的实现与应用
- KityFormula 编辑器压缩包功能解析
- 离线搭建Kubernetes 1.17.0集群教程与资源包分享
- Java毕业设计教学平台完整教程与源码
- 综合数据集汇总:浏览记录与市场研究分析
- STM32智能家居控制系统:创新设计与无线通讯
- 深入浅出C++20标准:四大新特性解析
- Real-ESRGAN: 开源项目提升图像超分辨率技术
- 植物大战僵尸杂交版v2.0.88:新元素新挑战
- 掌握数据分析核心模型,预测未来不是梦
- Android平台蓝牙HC-06/08模块数据交互技巧
- Python源码分享:计算100至200之间的所有素数
- 免费视频修复利器:Digital Video Repair
- Chrome浏览器新版本Adblock Plus插件发布
- GifSplitter:Linux下GIF转BMP的核心工具
- Vue.js开发教程:全面学习资源指南
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功