跳槽者、应届生必看JAVA面试题系列(二)

简介: 跳槽者、应届生必看JAVA面试题系列(二)

文章标题

一: 前言

二: 面试挑战

三: 后端基础知识篇(二)

一: Java中的队列和它们的区别

二: 简单描述下JVM内存模型以及它们的作用

三: 常见的GC算法和它们的差异

四: 反射的优缺点

五: 多继承的弊端和解决方案

六: 抽象类和接口的区别

七: 继承、封装、多态的作用

八: ClassNotFoundException知道?遇到的场景是什么?如何解决?

九: NoClassDefError错误的常见场景

十: hashcode和equals方法的特点

十一: hashcode的作用

十二: 为什么需要重写hashcode方法

十二: java.util包和java.awt包的区别

十三: 项目中常用的包有哪些

十四: fail-fast和fail-safe的区别

十五: Bean工厂和Appcation Context的区别

十六: 垂直拆分和水平拆分

十七: 保证线程安全的方式

十八: 重写equals方法需要注意的事项

十九: JAVA中哪些属性不能被序列化

二十: JRE和JDK的区别

四: 面试题目大纲

五: 总结

六: 热门推荐

一: 前言


JAVA面试必看系列第一章出来后,许多朋友的反馈都还不错,这让我激动万分,想着趁热打铁,继续编写第二章的内容,反馈你们的热情。



二: 面试挑战

 在开始第二章题目之前,还是先案例下"面试挑战": 凡是满足下面的挑战条件的,如果一个月内没有拿到一个Offer的,免费提供简历封装建议和相关面试题目解答。


 如果面试通过的,截图分享,让大家一起见证,具体条件如下:


 1、计算机相关专业或者经过计算机相关专业的培训(不少于3个月,正常来说培训机构培训时间不会少于三个月),准备从事JAVA开发人员。


  2、从事的工作是JAVA开发,年限是1-3年(大神的话就忽略我说的,可以直接退出了)或者是符合计算机相关专业,准备从学校出来就业的。


  3、持续学习本人《面试大全》至少两个月且对其中的内容基本掌握的。


 4、需要提供相关面试证据或者是面试题目。


 如果大家对这个感兴趣的,可以关注【IT学习日记】回复【面试挑战】即可参与,现在参与还免费赠送一份面试资料。



三: 后端基础知识篇(二)


一: Java中的队列和它们的区别

 1、定义

   队列是一个先进先出的数据结构,Queue是JDK1.5引入的。


 2、用途

   将大量的请求转换成服务器能够处理的队列请求,可以保证有序性,如秒杀系统


 3、分类


   第一类: 没有实现阻塞接口,但是实现了Queue和AbstractQueue接口


   (1)、LinkedList:: 实现了Deque接口,双向有序队列


   (2)、PriorityQueue: 有限队列,维护一个有序列表,可以自然排序也可以传递Comparator构造函数实现自定义排序


   (3)、ConcurrentLinkedQueue: 基于链表、线程安全的队列,并发访问不需要同步,它是从尾部添加元素从头部删除元素,对公共的集合访问效率做得很不错,添加删除O(1),查询O(n)。


   第二类: 实现了阻塞接口,concurrent包中引入了BlockQueue接口和五个阻塞队列,他们不是操作就立即向队列中添加或者删除元素,而是线程执行阻塞操作,直至队列有空间可以添加或者有元素可以删除。


   (1)、ArrayBlockingQueue: 数组型有界队列


   (2)LinkedBlockingQueue: 链接节点,支持可选的有界队列


   (3)PriorityBlockingQueue: 一个优先级堆,支持的无界队列


   (4)DelayQueue: 一个优先级堆,支持基于时间的无界队列


   (5)SynchronousQueue: 可以用来在线程间安全的交换单一元素


   三: 关于阻塞队列的操作


   1、add、remove、element: 操作一个已满或者为空的队列时,如果操作的集合为空或者已满时,remove或者add则会抛出异常。


   2、Offer、poll、peek: 在无法完成操作时,只会返回true或者null,不会抛出异常


   3、Take操作: 队列为空的时候阻塞。put操作:队列满时阻塞



二: 简单描述下JVM内存模型以及它们的作用


   注: 该图是jdk1.7时对应的JVM内存模型

image.png

1、程序计数器


     用来标识下一条需要执行指令的位置,它是线程私有的。


 2、虚拟机栈


   线程私有,声明周期和线程相同,它描述了Java方法执行的内存模型。每个方法在执行的同时会创建一个栈帧(Stack Frame),用于存储局部变量表,动态链接等信息。从调用到调用完成对应的是一个栈帧从虚拟机栈入栈到出栈的过程。


   局部变量表存放了编译器可知的基本类型、独享引用。Long、Double占用了2个局部变量控件slot,故为非原子性,它在编译时便完成了内存的分配,运行时不会进行修改。


   当申请的栈深度大于虚拟机允许的宽度时会抛出:StackoverFlowError,如虚拟机自动拓展、但申请不到足够的内存时,则抛出OutofMemeryError


 3、本地方法栈


   线程私有、为本地方法(native)服务,如:hotspot是将它和虚拟机栈合并在一起。可能抛出的错误有:StackoverFlowError和OutofMemeryError。


 4、堆


   线程共享、JVM中占用内存最大的一块区域,VM启动时创建,主要目的是: 存放对象实例。当实例没有申请到足够的空间时,堆大小也无法拓展时,会抛出OutofMemeryError错误,它也是GC主要进行收集的地方。(jdk1.8后,常量池也是存放在堆中,因为永久代废除了)


 5、方法区


   线程共享用于存储被虚拟机加载的类信息、变量、静态变量既即时编译的代码,JVM规范是将它和堆进行分开。永久代和元空间其实都是方法区的一种实现。



三: 常见的GC算法和它们的差异


 知识小贴士:


   Hotspot将堆划分为新生代(Young Generation)和年老代(Tetured Generation),新生代又分为Eden去和Survivor区,它们的比例是:8:2。所有新建的对象存放在新生代,其中survivor区又划分为from区和to区,比例是1:1。



 1、标记-清除(Mark Sweap)


   主要的步骤: 标记回收对象,回收被标记的对象


   标记方式有两种: 1、引用计数算法(Reference Counting), 2、可达性分析法(Rechability Analysis)


 缺点:


   回收后会出现大量非连续内存,且需要扫描两次内存,效率低



 2、复制算法(coping)


   思路: 将内存划分为等大的两块区域,一次只用一块,用完将存活的对象复制到另一块,然后清空自己。


   特点:


   解决了标记-清楚算法效率和内存碎片问题,但是需要浪费一块内存空间,利用率不高,主要是用于回收新生代(因为新生代的对象基本是”朝生暮死”,存活的时间很短)



 3、标记-整理(Mark - Compact)算法


   思路:


   从根节点开始对所有可达对象进行一次标记、之后,不是简单的清除未标记的对象,而是将所有存活的对象压缩到内存的一端,之后,清理边界外的所有空间。


   特点:


   避免了内存碎片的产生、同时又不需要两块相同的内存空间,相对来说性价比较高。多适用于老年代的区域回收,因为老年代的对象存活率大。


 4、分代收集算法


   分代收集算法是目前虚拟机使用的回收算法。它解决了标记清除算法不使用于老年代的问题。在不同年代中使用不同的收集方式,新生代存活率低,可以使用复制算法。老年代对象存活率高,没有额外的控件对它进行分配担保,可以使用标记清除或者标记整理算法。



四: 反射的优缺点


 优点:


   体现了灵活性、降低了类之间的耦合性、体现了多态的作用。


 缺点:


   性能存在一定问题。反射本身算是一种解释操作,告诉JVM我们想要做什么并让它满足我们的要求,它会比直接执行操作更慢一些。



五: 多继承的弊端和解决方案


 弊端: 如果有多个父类,有相同的功能时,子类调用,会产生不确定性,所以JAVA中类的只有单继承。


 解决: 通过”实现”解决,因为接口中的功能都是未实现的,需要子类明确。接口的出现避免了单继承的局限性,所以,一般是父类中定义的事物的基本功能,接口定义的是事物的拓展功能。



六: 抽象类和接口的区别


 一: 相同点


   都不能直接实例对象,都可以包含抽象方法



 二: 不同点


   1、接口中除了静态方法和默认方法外只能存在抽象方法,但是抽象类中既可以存在抽象方法也可以存在非抽像方法。


   2、接口可以多实现,但是类只能单继承


   3、接口中只能定义常量,抽象类中可以定义常量和变量


   4、接口中没有构造函数,抽象类中有构造函数



七: 继承、封装、多态的作用


 继承: 子类自动拥有父类所有可以继承的属性和方法



 封装: 隐藏对象的属性和方法的细节实现,提供一些公共访问的方式



 多态: 配合继承与方法的重写提高代码的重用性和拓展性,如无方法重写,则多态同样无意义。



八: ClassNotFoundException知道?遇到的场景是什么?如何解决?


 场景:


   1、调用Classs.forName(“类的全限路径”)加载类时



   2、ClassLoader.findSystemClass方法调用时



   3、ClassLoader.loadClass方法时


 解决:


   检查类名是否正确或者是否真的存在需要加载的类



九: NoClassDefError错误的常见场景


 场景:


   1、类依赖的class或者jar包不存在



   2、类文件存在,但是存在于不同的域中



   3、大小写问题,javac编译时是无视大小写的,可能编译出的class文件和想要的不一样



十: hashcode和equals方法的特点


 1、重写equals方法则必须同时重写hashCode方法



 2、如果两个对象的equals方法相等,则两个对象的hashCode也一定相等



 3、如果两个对象的hashCode相等,那么两个对象的equals方法不一定相等,只能说明两个对象在散列存储结构中,存放在相同的一个位置



十一: hashcode的作用


 用于快速定位对象在散列表的位置。在JVM中new一个对象时,会将这个对象丢到Hash表中,下次再进行对象的比较或者取该丢向时,根据该对象的hashCode从hash表中获取,目的,提高获取对象的效率。



 若HashCode相同则再去调用equals方法,所以hashCode是用于查找的,而equals方法是用于判断两个对象是否相等。



十二: 为什么需要重写hashcode方法


 HashMap或者HashSet中如果不重写会导致存对象进去了,但是取对象的时候却取不到正确的。重写hashCode时为了保证相同的对象有相同的hashCode。



十二: java.util包和java.awt包的区别


 Java,util包中存放的是常用的工具包,如集合。



 Java.awt包存放的是: 包含用于创建用户界面和绘制图形图像的所有类。



十三: 项目中常用的包有哪些


 Java.lang: 提供利用 Java 编程语言进行程序设计的基础类。



 java.util: 包含集合框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类



 java.io.*: Java的核心库java.io提供了全面的IO接口。包括:文件读写、标准设备输出等。



 java.net.*: 包含与网络相关的一些类库。



 java.sql.*: 包含了与数据库相关的一些类库。



 此外还有如果java.util.concurrent等与线程安全相关的包。



十四: fail-fast和fail-safe的区别


 并发修改: 当一个线程或者多个线程在遍历集合时,另外的线程对该集合进行了内容变动(添加、删除、修改)。


 Fail-fast-快速失败: java.util下的集合都是这种模式


   在遍历集合的时候,如果进行了并发修改,会抛出concurrentModificationException异常,因为它所有的操作都是在原来的集合中进行的,在遍历的时候判断是否存在下一个元素时会进行:expectModcount和modCount的判断,如果不相等,则直接抛出异常。


 Fail-Safe-安全失败: java.util.concurrent下的集合都是这种模式


   属于这种机制的集合,任何对集合的操作(添加、修改、删除)都会在当前集合的复制出来的集合上操作,不会直接在当前的集合上进行,所以不会抛出异常,但是会存在以下的问题:


   1、需要复制集合,产生无效对象,开销较大


   2、无法保证读取的数据是目前原始数据结构中的最新数据



十五: Bean工厂和Appcation Context的区别


 Bean工厂:


   是Spring的原始接口,Bean工厂实现的容器特点是:每次获取对象的时候才会去创建对象,而不是在容器启动的时候去加载所有的对象。这是因为早期机器的容量和资源都是比较稀缺的,如果在启动时一次加载完所有的对象,资源可能全被占用,程序无法正常运行。


 Bean工厂的优缺点:


 优点:

   1、项目启动速度快,且资源占用少


 缺点:

   因为对象是在获取的时候才进行创建,所以无法在启动时检查出对象配置是否存在问题,需要在获取的时候才知道.


 ApplicationContext:

   它是继承了Bean工厂,同时拓展了许多功能,每次容器启动的时候会创建所有的对象。


 优点:

   可以及时发现对象配置的问题,因为在容器启动的时候会创建所有的对象。


 缺点:

   项目启动速度较慢,且资源占用较多。



十六: 垂直拆分和水平拆分


 垂直拆分:

   把一个数据库中不同的业务单元的数据分配到不同的数据库中,如:用户信息存存储在库1,订单信息存储在库2。



 水平拆分:

   根据一定的规则,将同一个业务单元的数据分配存储在不同的数据库中,防止单表的数据量太大,导致查询速率降低。



十七: 保证线程安全的方式


 1、添加锁,如synchronized,Reentractlock



 2、使用ThreadLocal线程副本,每个线程独享一份数据,互不干扰



 3、使用阻塞队列,线性执行任务



 4、使用JDK提供的原子类如java.concurrent.atomic包下的类



十八: 重写equals方法需要注意的事项


 注: java规范中要求重写equals方法需要具有以下的特性:



 1、自反性: 针对非空的x,使用x.equals(x)应该返回true



 2、对称性: 针对x,y,如果x.equals(y)为true,那么y.equals(x)也应该为true



 3、传递性: 如有x,y,z,存在x.equals(y)和y.equals(z)都为True,那么x.equals(z)也应该为true



 4、一致性: 如果比较对象未发生改变,则反复调用equals方法应该返回同样的结果



 5、对于任意的非空x,x.equals(null)应该返回false



十九: JAVA中哪些属性不能被序列化


 1、被static修饰的属性,它是属于类级别的,序列化针对的是对象。序列化保存的是对象的状态,静态变量是以类的状态,因此序列化并不保存静态变量。这里的不能序列化的意思,是序列化信息中不包含这个静态成员域



 2、被transient修饰的属性



二十: JRE和JDK的区别


 JRE:

   核心的内容是JVM及相关的核心类库及支持文件。



 JDK:

   除了包含JRE外,还包含了JAVA工具(编译器、调试器等)和java的基础类库,开发者可以进行: 开发 -> 编译 -> 执行java应用程序。



四: 面试题目大纲


  注意: 题目不止这些,会一直持续不断更新最新的面试题和面试资料。

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

五: 总结

  由于文章篇幅的限制,面试大全的第二章暂时到这里就告一段落。如果有意见或者建议,可以在下方或者私信留言,看到会及时回复,也欢迎大家参加面试挑战和面试题投稿,希望大家早日获得心仪的Offer,如果觉得文字对你有帮助,欢迎关注和点赞。

相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
76 2
|
26天前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
66 14
|
1月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
1月前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
1月前
|
存储 缓存 Oracle
Java I/O流面试之道
NIO的出现在于提高IO的速度,它相比传统的输入/输出流速度更快。NIO通过管道Channel和缓冲器Buffer来处理数据,可以把管道当成一个矿藏,缓冲器就是矿藏里的卡车。程序通过管道里的缓冲器进行数据交互,而不直接处理数据。程序要么从缓冲器获取数据,要么输入数据到缓冲器。
Java I/O流面试之道
|
1月前
|
Java 编译器 程序员
Java面试高频题:用最优解法算出2乘以8!
本文探讨了面试中一个看似简单的数学问题——如何高效计算2×8。从直接使用乘法、位运算优化、编译器优化、加法实现到大整数场景下的处理,全面解析了不同方法的原理和适用场景,帮助读者深入理解计算效率优化的重要性。
35 6
|
1月前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
61 4
|
1月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
128 4
|
2月前
|
存储 安全 算法
Java面试题之Java集合面试题 50道(带答案)
这篇文章提供了50道Java集合框架的面试题及其答案,涵盖了集合的基础知识、底层数据结构、不同集合类的特点和用法,以及一些高级主题如并发集合的使用。
123 1
Java面试题之Java集合面试题 50道(带答案)
|
2月前
|
存储 Java 程序员
Java面试加分点!一文读懂HashMap底层实现与扩容机制
本文详细解析了Java中经典的HashMap数据结构,包括其底层实现、扩容机制、put和查找过程、哈希函数以及JDK 1.7与1.8的差异。通过数组、链表和红黑树的组合,HashMap实现了高效的键值对存储与检索。文章还介绍了HashMap在不同版本中的优化,帮助读者更好地理解和应用这一重要工具。
71 5