JAVA高频面试题目集锦(1)

简介: JAVA高频面试题目集锦(1)

一、equals()和==,以及HashCode()


=号 如果是值引用,比较值是否相等; 如果是对象引用,比较对象内存地址是否相同

equals()方法中,默认使用等号,如果说我们想要判断对象是否相等需要重写equals方法

HashCode()


Object 的 hashcode 方法是本地方法,也就是用 c 语言或 c++ 实现的,该方法通常用来将对象的 内存地址 转换为整数之后返回。


一般情况下重写equals方法的同时需要重写HashCode,假如不重写HashCode会发生什么情况呢?

以HashSet为例子,我们放入new 相同对象放到HashSet中,会出现重复值。


因为对象在堆中存放在不同的地址上,hashCode是根据对象地址生成的,所以也不同,就存放到不同的位置


所以对于散列表,HashMap,HashSet,HashTable,如果用自定义的对象做key,需要重写hashcode和equals方法;

判断过程是这样的,比较equals中先比较Hashcode是否相等,再比较对象的属性是否相等。


二、String,StringBuffer,StringBuilder

String是被final修饰的不可变字符串

StringBuffer、StringBuilder是可变字符串,


StringBuffer是线程安全的,使用synchronized关键字修饰

StringBuilder是非线程安全的,StringBuilder 是没有对方法加锁同步的,所以毫无疑问,StringBuilder 的性能要远大于 StringBuffer


StringBuffer 适用于用在多线程操作同一个 StringBuffer 的场景,如果是单线程场合 StringBuilder 更适合。


三、反射及应用的场景


反射机制是在运行状态中,对于任意一个类(指的是.class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。


反射应用的场景: 动态代理设计模式也采用了反射机制


JDBC 的数据库的连接,Class.forName


Spring 框架的 IOC(动态加载管理 Bean)创建对象以及 AOP(动态代理)功能都和反射有联系;


四、静态代理,JDK动态代理与Cglib动态代理


静态代理:


静态代理实现步骤:


定义一个接口及其实现类;


创建一个代理类同样实现这个接口


将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情。


**总结:**静态代理中,我们对目标对象的每个方法的增强都是手动完成的(后面会具体演示代码),非常不灵活(比如接口一旦新增加方法,目标对象和代理对象都要进行修改)且麻烦(需要对每个目标类都单独写一个代理类)。 实际应用场景非常非常少,日常开发几乎看不到使用静态代理的场景。


动态代理实现的目的和静态代理一样,都是对目标方法进行增强,而且让增强的动作和目标动作分开,达到解耦的目的


JDK动态代理产生的代理类和目标类实现了相同的接口;cglib动态代理产生的代理类是目标对象的子类。


五、HashSet、HashMap、HashTable、concurrentHashMap

HashMap是存储的是键值对,通过数组+链表的结构存储,结合了数据和链表这两种数据结构的特点,能够快速的定位以及插入删除。HashSet是基于HashMap实现的,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,HashSet不允许元素有重复的。HashTable的实现基本上与HashMap相同,它通过synchronized关键字实现了线程安全,HashTable的操作是无论是get还是put都会锁定整张表,


concurrentHashMap降低了锁的粒度,JDK1.7之前使用分段锁,JDK1.8对数组的每个元素加锁。


HashMap与HashTable的区别:


HashMap 和 Hashtable 都实现了 Map 接口。主要的区别有:线程安全性,同步 (synchronization),以及速度。


由于 HashMap 非线程安全,在只有一个线程访问的情况下,效率要高于 HashTable

HashMap 允许将 null 作为一个 entry 的 key 或者 value,而 Hashtable 不允许。


HashMap 把 Hashtable 的 contains 方法去掉了,改成 containsValue 和

containsKey。因为 contains 方法容易让人引起误解。


Hashtable 继承自陈旧的 Dictionary 类,而 HashMap 是 Java1.2 引进的 Map 的一个实现。


Hashtable 和 HashMap 扩容的方法不一样,HashTable 中 hash 数组默认大小 11,扩容方式是 old*2+1。HashMap 中 hash 数组的默认大小是 16,而且一定是 2 的指数,增加为原来的 2 倍,没有加 1。


两者通过 hash 值散列到 hash 表的算法不一样,HashTbale 是古老的除留余数法,直接使用 hashcode,而后者是强制容量为 2 的幂,


新根据 hashcode 计算 hash 值,在使用 hash 位与 (hash 表长度 – 1),也等价取膜,但更加高效,取得的位置更加分散,偶数,奇数保证了都会分散到。前者就不能保证。


另一个区别是 HashMap 的迭代器 (Iterator) 是 fail-fast 迭代器,而 Hashtable 的 enumerator 迭代器不是 fail-fast 的。所以当有其它线程改变了 HashMap 的结构(增加或者移除元素),将会抛出 ConcurrentModificationException,但迭代器本身的 remove() 方法移除元素则不会抛出 ConcurrentModificationException 异常。但这并不是一个一定发生的行为,要看 JVM。这条同样也是 Enumeration 和 Iterator 的区别。

HashMap的get和put,插入和获取原理?


image.png


判断数组是否为空,为空进行初始化;
不为空,计算 k 的 hash 值,通过(n - 1) & hash计算应当存放在数组中的下标 index;
查看 table[index] 是否存在数据,没有数据就构造一个Node节点存放在 table[index] 中;
存在数据,说明发生了hash冲突(存在二个节点key的hash值一样), 继续判断key是否相等,相等,用新的value替换原数据
(onlyIfAbsent为false);
如果不相等,判断当前节点类型是不是树型节点,如果是树型节点,创造树型节点插入红黑树中;
如果不是树型节点,创建普通Node加入链表中;判断链表长度是否大于 8, 大于的话链表转换为红黑树;
插入完成之后判断当前节点数是否大于阈值,如果大于开始扩容为原数组的二倍。


微信图片_20220128171122.png


目录
相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
76 2
|
27天前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
66 14
|
1月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
1月前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
1月前
|
Java 编译器 程序员
Java面试高频题:用最优解法算出2乘以8!
本文探讨了面试中一个看似简单的数学问题——如何高效计算2×8。从直接使用乘法、位运算优化、编译器优化、加法实现到大整数场景下的处理,全面解析了不同方法的原理和适用场景,帮助读者深入理解计算效率优化的重要性。
36 6
|
1月前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
63 4
|
1月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
133 4
|
1天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
3天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
3天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。