Java面试题

Java面试题

Java基础

八种基本数据类型的大小,和它们的封装类

基本类型字节大小位数封装类默认值
byte18Byte0
short216Short0
int432Integer0
long864Long0l或0L
float432Float0.0F或0.0f
double864Double0.0
char216Characteru0000
boolean--Booleanfalse

引用数据类型(类)

1、Java提供好的类:

​ 如:Random类,Scanner类等

2、自定义类

Switch能否用string做参数

jdk1.7之前,switch仅支持多种数据类型: int byte float double 以及它们的封装类型。

​ 其对应的封装类型会自动转换为int,所以float、double等数据会出现失精的情况。

jdk1.7之后,switch是支持string的。

equals 和 == 的区别

== 对于基本类型来说是指的比较,对于引用类型来说引用的比较。

equals 本质上就是 == ,只不过 String 和 Integer 等重写了 equals 方法,把

​ equals 变成了值的比较。

*两个对面的hashCode()相同,则 equals()也一定为 true吗

​ 答:不一定,两个对象的的hashCode()相同,equals() 也不一定为 true

示例:

String str1 = "通话";
String str2 = "重地";
sout(String.format("str1:%d|str2:%d",str1.hashCode(),str2.hashCode()));
sout(str1.equals(str2));

//执行结果:

//str1: 1179395 | str2: 1179395

//false

自动装箱

​ 需要装箱、拆箱的类型

这里写图片描述

常量池

Object 有哪些公用方法

方法释义
clone保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出异常。 java里除了8种基本数据类型传参数是值传递,其他的类对象传参数都是引用传递,如果不希望将方法里的参数改变,就需要在类中复写clone方法
toString该方法用的比较多,一般子类都有覆盖
getClassfinal方法,获得运行时类型
equals该方法是非常重要的方法,一般equals和 == 是不一样的,但是在做Object中两者是一样的。子类一般都要重写这个方法
hashCode该方法用于哈希查找,可以减少在重找中使用equals的次数,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection 中用到。 如果不重写hashCode(),在HashSet中添加两个equals的对象,会将两个对象都加入进去
waitwait方法就是是当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait() 一直等待,知道获得锁或者被中断。wait(long timeout) 设定一个超时间隔,如果在规定时间内没有获得锁就返回。 调用该方法后,当前线程进入睡眠状态,直到以下事件发生:1、其他线程调用了该对象的notify方法 2、其他线程调用了该对象的notifyAll方法 3、其他线程调用了interrupt中断该线程 4、时间间隔到了。 此时该线程就可以被调度,如果是被中断的话,就抛出一个InterruptedException异常。
notify该方法唤醒在改对象上等待的某个线程
notifyAll该方法唤醒在改对象上等待的所有线程
finalize该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用

Java 中的四种引用

引用释义
StrongReference(强引用)强引用是醉经常使用的一种引用,如new 操作创建对象就属于强引用。无论如何JVM都不会去回收其内存 如:Obejct obj =new Object();
SoftReference(软引用)JVM内存不足时才会去回收该对象,可以用来做内存预警
WeakReference(弱引用)对于弱引用 JVM会回收仅被弱引用所关联的对象 ,也就是说,弱引用对象会在一次 gc 之后被回收
PhantomReference(虚引用)虚引用对其原对象的生命周期毫无影响,其可以作为一种标记,档期所引用对象被会收拾其会自动加入到引用队列中,也就是说可以通过虚引用得到哪些对象已被回收

HashCode 的作用

该方法返回对象的哈希值

*当equals方法被重写的时候,通常有必要重写hashCode方法,以维护hashCode方法的常规协定,即相等对象必须具有相等的哈希值

HashMap中hashCode的作用

  1. 用于查找的便利性,hashCode是用来在散列表中确定对象的存储位置的
  2. 如果两个对象相同,就是使用于 equals(java.lang.Object)方法,那么这两个对象的hashCode一定要相同
  3. 如果对象的 equals 方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和 equals方法中使用的一致,否则就会违法上面提到的第2点。
  4. 两个对象的hashCode相同,并不一定表示两个对象就相等,也就是不一定使用于 equals(java.lang.Object)方法,只能说明这两个对象在散列存储结构中, 如Hashtable,他们“存放在同一个篮子里”。

hashCode什么时候需要重载?

​ 一般的地方不需要重载hashCode,只有当类需要放在Hashtable、HashMap、HashSet 等等 hash 结构的集合时才会重载hashCode 。HashMap就是一个大内存块,里面有很多小内存块,小内存块里面是一系列的对象,可以利用hashCode来查找小内存块 hashCode%size(小内存块数量), 所以当 equals 相等时,hashCode 必须相等,而且如果是 object 对象。必须重载hashCode 和 equals 方法。

ArrayList、LinkedList、Vector的区别

​ 相同点: 三者都是实现集合框架中的List,也就是所谓的 有序集合

释义 :

Vector是java早起提供的线程安全的动态数组 ,如果不需要线程安全,并不建议选择,毕竟同步是有额外开销的。Vector内部是使用对象数组来保存数据的,可以根据需要自动的增加容量,当数组满了,会创建新的数组,并拷贝数组数据。

ArrayList 是应用更加广泛的动态数组实现,它本身不是线程安全 ,所以性能要好很多。与 Vector 近似。ArrayList也是根据需要调整的容量,不过两者的天正逻辑是有所区别的。Vector在扩容时会提高一倍,而 ArrayList 则是增加 50% 。

LinkedList是 Java提供的双向链表 ,它不需要像上面两种那样调整容量,它也不是线程安全的。

ArrayListVectorLinkedList
底层实现方式Object数组Vector是基于 synchronized实现的线程安全ArrayList双向循环链表(jdk1.6之前),双向链表(jdk1.7)
读写机制插入:超过当前数组预定的最大值时,数组需要扩容,扩容过程需要调用底层System.arraycopy() 方法进行数组赋值操作
删除:删除元素并不会减少数组的容量,如需缩小容量,可调用trimToSize()方法,在查找元素时要遍历数组,对非 null 的元素采取 equals 的方式查找
插入: 需创建一个新的Entry对象,并更新相应元素的前后元素的引用
查询 :遍历链表
删除:遍历链表再删除
读写效率ArrayList 对元素的增加和删除都会引起数组的内存分配空间动态发生变化,对其进行插入和删除速度较慢,但检索速度快LinkedList 是基于链表方式存放数据,增加和删除元素的速度比较快,但是检索速度比较慢
线程安全非线程安全非线程安全
三者适合的应用场景
  • Vector 和 ArrayList 作为动态数组,其内部元素以数组形式 顺序存储 的,所以非常 适合随机访问的场合 。除了尾部插入和删除元素,往往性能会相对较差,如: 数组中间位置插入一个元素,需要移动后续所有的元素
  • LinkedList 进行节点插入、删除却要高效得多 ,但是随机访问性能则要比动态数组
  • 在用用开发中,如果事先可以估计到, 应用操作是偏向于插入、删除,还是随机查询较多 ,就可以针对性的进行选择
链表和数组的对比
数组链表
最好用于索引有语意的情况,例如 scores[2]不适合用于索引有语意的情况
最大的优点: 支持快速查询(随机访问)优点:动态数据结构,不需要处理固定容量的问题。
缺点:丧失了随机访问能力
物理存储单元上连续物理存储单元上不连续

String 、 StringBuffer 和 StringBuilder 的区别

StringStringBufferStringBuilder
执行速度最差其次最高
线程安全线程安全线程安全线程不安全
使用场景少量字符串操作多线程环境下的大量操作单线程环境下的大量操作

*StringBuffer : 效率不如 StringBuilder ,但远比 String 要高

Map、Set、List、Queue和Stack的特点和用法

MapSetListQueueStack
特点保存映射关系的数据(key-value)
不包含重复的key
TreeMap保证其顺序
HashMap不可保证其顺序
不包含重复元素的Collection
最多包含一个 null 元素
可随机访问包含的元素
元素是有序的
可在任意位置增删元素
允许重复元素
先进先出
后进先出
继承自Vector(可增长的对象数组),也是同步的
用法keySet() ,抽取 key 序列,将 map 中所有的key 生成一个Set
values() ,抽取 value 序列,将map 中所有的values 生成一个Collection
只能使用Iterator 实现单向遍历
没有同步方法
可用Iterator 实现单向遍历
也可用 ListIterator 实现双向遍历
使用时应尽量避免使用 Collection 的add() 和 remover() 方法,而是使用 offer() 来加入元素,使用 poll() 来获取并移出元素。
如果不需要移出该元素,可以使用 element() 或者 peek() 方法
LinkedList 实现了Queue 接口
Queue通常不允许插入 null 元素,因为poll() 方法的一个特殊返回值是 null ,表名的是该队列不包含元素
提供了 push() 和 pop() 操作,以及取堆栈顶点的 peek 方法、堆栈是否为空的 empty 方法、堆栈中查找项并确定到堆栈顶距离的 search 方法
适合的场景涉及到堆栈、队列的操作用List
涉及到快速随机访问元素的用ArrayList
涉及到快速插入、删除元素的应该使用 LinkedList

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cT0xVD8O-1639138588204)(C:\Users\西法\AppData\Roaming\Typora\typora-user-images\image-20211210134107030.png)]

HashMap 和 HashTable 的区别

HashMap 简介

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l57XRB9z-1639138588205)(C:\Users\西法\AppData\Roaming\Typora\typora-user-images\image-20211210140142824.png)]

jdk1.7之前,hashmap由数组和链表组成

​ 在jdk1.7中,只是单纯的数组+链表的结构,但是如果散列表中的hash碰撞过多时,会造成效率的降低,

所以在JKD1.8中对这种情况进行了控制,当一个hash值上的链表长度大于8时,该节点上的数据就不再以链表进行存储,而是转成了一 个红黑树。

map.put 操作

​ map.put(“tom”,203)

​ 立即调用值(“tom”)的hashCode的方法计算key的hash值,然后这个值会再次经过运算得出最终的哈希值,根据哈希值计算出在 Node数组的存储下标

​ 1、 如果该下标位置没有存储值,那么key-value直接存入

​ 2、 如果该下标位置有值(一个单向链表,可能有多个Node节点),调用equals方法和链表中每个节点的key做判断,如果都返回 false,那么key-value存入,如果返回true,则将要存入的value替换之前已经存入的value

HashTable 简介
				 Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足			(超过了阀值)时,同样会自动增长。

				Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中。

​ Hashtable同样实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆。

区别

HashMapHashTable
线程安全不安全,如果想要线程安全,可以通过 Collections 类的静态方法 synchronizedMap 获取线程安全的 HashMap
Map map =Collections.synchronizedMap(new HashMap());
安全
所继承父类AbstractMap类Dictionary类 (一个被废弃的类)
包含的方法没有 contains 方法,有 containsValue 和 containsKey 方法有 contains 方法, 有 containsValue, 还有 containsKey 方法
是否允许 null 值允许不允许
计算hash值的方式
扩容方式必须为原容量的 2倍,一定是 2 的幂次倍的扩容结果,原数组内的元素依次重新计算存放位置扩容为原容量的 2倍 +1

JDK7 和 JDK8 中 hashMap 的实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-euOR76jr-1639138588206)(C:\Users\西法\AppData\Roaming\Typora\typora-user-images\image-20211210140142824.png)]

jdk1.7之前,hashmap由数组和链表组成

​ 在jdk1.7中,只是单纯的数组+链表的结构,但是如果散列表中的hash碰撞过多时,会造成效率的降低,

所以在JKD1.8中对这种情况进行了控制,当一个hash值上的链表长度大于8时,该节点上的数据就不再以链表进行存储,而是转成了一 个红黑树。

Hashmap和currentHashmap的区别

HashmapcurrentHashmap
本质数组+链表HashMap 的基础上将数据分为多个segment(段),默认16个(concurrency level),每次操作对一个 segment(段)加锁,避免多线程锁的几率,提高并发效率

currentHashTable 可以完全替代 Hashtable吗

不能,hashtable 大小增加到一定的大小,性能会急剧下降,因此在迭代的时候,需要被锁定很长的时间。 currentHashTable 引入了 segment 的结构(segmentation), 无论变得多大,仅仅需要锁定 map 的某个部分。

| HashMap 的基础上将数据分为多个segment(段),默认16个(concurrency level),每次操作对一个 segment(段)加锁,避免多线程锁的几率,提高并发效率 |

currentHashTable 可以完全替代 Hashtable吗

不能,hashtable 大小增加到一定的大小,性能会急剧下降,因此在迭代的时候,需要被锁定很长的时间。 currentHashTable 引入了 segment 的结构(segmentation), 无论变得多大,仅仅需要锁定 map 的某个部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值