Java常见面试题(系列1)

蚂蚁花呗面试题

1.Java容器有哪些?哪些是同步容器,哪些是并发容器?

Java容器主要分:Collection和Map

Collection划分为:List,Set,Queue

List接口常见有:ArrayList,LinkedList,AbstractList, CopyOnWriteArrayList, Vector,Stack

Set接口常见有:HashSet,TreeSet,LinkedHashSet,AbstractSet,CopyOnWriteArraySet,EnumSet

Queue接口常见有:(阻塞队列)ArrayBlockQueue、PriorityBlockingQueue、LinkedBlockingQueue(双端队列)ArrayDeque、LinkedBlockingDeque、LinkedList

Map接口常见有:Hashmap、Treemap、Hashtable、AbstractMap、ConcurrentHashMap、 LinkedHashMap、WeakHashMap
  • 同步容器:
    • 在Java中,同步容器主要包括2类:
        1)Vector、Stack、HashTable
        2)Collections类中提供的静态工厂方法创建的类
  • 并发容器:
    • ConcurrentHashMap:线程安全的HashMap的实现(重要
    • CopyOnWriteArrayList:线程安全且在读操作时无锁的ArrayList
    • CopyOnWriteArraySet:基于CopyOnWriteArrayList,不添加重复元素
    • ArrayBlockingQueue:基于数组、先进先出、线程安全,可实现指定时间的阻塞读写,并且容量可以限制
    • LinkedBlockingQueue:基于链表实现,读写各用一把锁,在高并发读写操作都多的情况下,性能优于ArrayBlockingQueue

2.ArrayList和LinkedList的插入和访问的时间复杂度?

ArrayList和LinkedList的大致区别:
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
时间复杂度:

ArrayList :
get() 直接读取第几个下标,复杂度 O(1)
add(E) 添加元素,直接在后面添加,复杂度O(1)
add(index, E) 添加元素,在第几个元素后面插入,后面的元素需要向后移动,复杂度O(n)
remove()删除元素,后面的元素需要逐个移动,复杂度O(n)

LinkedList :
get() 获取第几个元素,依次遍历,复杂度O(n)
add(E) 添加到末尾,复杂度O(1)
add(index, E) 添加第几个元素后,需要先查找到第几个元素,直接指针指向操作,复杂度O(n)
remove()删除元素,直接指针指向操作,复杂度O(1)

3.java反射原理,注解原理?

反射机制: 在运行时(Run-Time),对于任何一个对象都知道其所有属性及方法,并能够调用。

反射原理: 每一个类都有一个Class对象。所有类都是在第一次使用时,动态加载到JVM中,当程序创建第一个对类的静态成员引用时,会加载这个类。一旦你一个类的Class对象被载入到内存,它便被用来创建这个类的所有对象。Java使用Class对象来执行其RTTI(Run-Time Type Identification),这也是反射的基础。

JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中

一、类对象的获取
1、通过对象获取,obj.getClass();
2、通过类路径名获取,Class.forName("com.whut.User");
3、通过类名获取,Object.class;
二、常用API
getField、getMethod和getCostructor方法可以获得指定名字的域、方法和构造器。
getFields、getMethods和getCostructors方法可以获得类提供的public域、方法和构造器数组,其中包括超类的共有成员。
getDeclatedFields、getDeclatedMethods和getDeclaredConstructors方法可以获得类中声明的全部域、方法和构造器,其中包括私有和受保护的成员,但不包括超类的成员。

注解: 为某一固定的处理方法提供坐标,使得处理方法可以通过反射机制获取到注解的方法或其他属性。

注解原理: 获取到某个类的Class对象后,使用反射机制获取到该类的属性、方法等,判断对应的属性、方法是否使用了特定的注解,如果有则调用该类注解的处理器来处理。

4. 新生代分为几个区?使用什么算法进行垃圾回收?为什么使用这个算法?

(1)新生代分区:Eden、From Survivor、To Survivor,大小比例为:8:1:1;
To Survivor:保留的是MinorGC的幸存者;
From Survivor:保留的是上次GC的幸存者,在这次作为被扫描者;
(2)使用标记-复制算法;
(3)因为复制算法的实现,导致复制算法适用于对象较少的情况下,当Eden区的内存被填满,会触发minorGC ,Eden区对象会从Eden转移到Survivor区,随着年龄的增加再到老年代。

抛几个问题:

>> 1.什么是空间分配担保?

在发生Minor GC之前,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象的总空间,

如果大于,则此次Minor GC是安全的

如果小于,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果HandlePromotionFailure=true,那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代的对象的平均大小,如果大于,则尝试进行一次Minor GC,但这次Minor GC依然是有风险的;如果小于或者HandlePromotionFailure=false,则改为进行一次Full GC。

>> 2.为什么要进行空间担保?

是因为新生代采用复制收集算法,假如大量对象在Minor GC后仍然存活(最极端情况为内存回收后新生代中所有对象均存活),而Survivor空间是比较小的,这时就需要老年代进行分配担保,把Survivor无法容纳的对象放到老年代。老年代要进行空间分配担保,前提是老年代得有足够空间来容纳这些对象,但一共有多少对象在内存回收后存活下来是不可预知的,因此只好取之前每次垃圾回收后晋升到老年代的对象大小的平均值作为参考。使用这个平均值与老年代剩余空间进行比较,来决定是否进行Full GC来让老年代腾出更多空间。

问题:Minor Gc后的对象太多无法放入Survivor区怎么办?

假如在发生gc的时候,eden区里有150MB对象存活,而Survivor区只有100MB,无法全部放入,这时就必须把这些对象全部直接转移到老年代里。

问题: 接着上面的问题,如果这时老年代的可用内存小于新生代全部对象大小,万一Minor gc后新生代的对象都存活下来,然后需要全部转移到老年代,但是老年代空间不够,怎么办?

理论上有这个可能。

这时如果设置了 "-XX:-HandlePromotionFailure"的参数,就会尝试判断,看老年代内存大小是否大于之前每一次Minor gc后进入老年代的对象的平均大小。

比如说,之前Minor gc 平均10M左右的对象进入老年代,此时老年代可用内存大于10MB,那么大概率老年代空间是足够的。

如果上面那个判断失败,或者是根本没设置这个参数,那就直接触发"Full GC",对老年代进行垃圾回收,腾出些空间,再Minor gc。

如果判断成功了,那么大概率老年代内存是够的,就冒风险尝试Minor gc。这时有以下几种可能。

Minor Gc 后,剩余的存活对象大小,小于Survivor区,那就直接进入Survivor区。
MInor Gc 后,剩余的存活对象大小,大于Survivor区,小于老年代可用内存,那就直接去老年代。
Minor Gc后,大于Survivor,老年代,很不幸,就会发生"Handle Promotion Failure"的情况 ,触发"Full GC"。
Full gc 就是对老年代进行垃圾回收,同时也一般会对新生代进行垃圾回收。

如果 Full gc后老年代还是没有足够的空间存放剩余的存活对象,那么就会导致 OOM(out of memory )内存溢出。

所以Minor gc 触发要先对老年代空间做检查看看老年代空间够不够。 检查失败的时候触发"Full Gc"给老年代腾空间,或者Minor gc 后剩余对象太多放入老年代内存都不敢,也要触发"Full Gc"。

GC流程图
在这里插入图片描述
注意:

当程序运行时,至少会有两个线程开启启动,一个是我们的主线程,一个时垃圾回收线程,垃圾回收线程的priority(优先级)较低
垃圾回收器会对我们使用的对象进行监视,当一个对象长时间不使用时,垃圾回收器会在空闲的时候(不定时)对对象进行回收,释放内存空间,程序员是不可以显示的调用垃圾回收器回收内存的,但是可以使用System.gc()方法建议垃圾回收器进行回收,但是垃圾回收器不一定会执行。
Java的垃圾回收机制可以有效的防止内存溢出问题,但是它并不能完全保证不会出现内存溢出。例如当程序出现严重的问题时,也可能出现内存溢出问题。

5.HashMap在什么情况下会扩容,或者有哪些操作会导致扩容?

HashMap是由我们常用的数组+链表+红黑树(JDK1.8增加了红黑树)组合构成的数据结构。

HashMap扩容的条件:
新建的HashMap容量默认初始容量为16,负载因子为0.75,
当HashMap的key-value达到13个时,会第一次扩容,每次扩容后容量为原来容量的2倍,并重新计算旧数组中结点的存储位置。结点在新数组中的位置只有两种,原下标位置或原下标+旧数组容量的大小。
最大个数为Integer.MAX_VALUE即2147483648。
造成HashMap扩容的操作:
putMapEntries():插入
putVal()
put()
treeifyBin()
merge():合并

6.HashMap put方法的执行过程?

HashMap1.8版本 put方法流程图
在这里插入图片描述

7.HashMap检测到hash冲突后,将元素插入在链表的末尾还是开头?

1.7版本是头插法
1.8版本是尾插法(因为需要遍历节点个数,判断是否需要数组扩容还是链表转红黑树)

8.jdk1.8还采用了红黑树,讲讲红黑树的特性,为什么人家一定要用红黑树而不是AVL、B树之类的?

红黑树(R-B Tree)一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。

红黑树的特性:
(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

在这里插入图片描述

二叉排序树(又称二叉查找树):
1)若左子树不为空,则左子树上所有结点的值均小于根结点的值。
2)若右子树不为空,则右子树上所有结点的值均大于根节点的值。
3)左右子树也为二叉排序树。
②平衡二叉树(AVL树):是一种二叉查找树,当且仅当两个子树的高度差不超过1时,这个树是平衡二叉树。
③红黑树:是许多二叉查找树中的一种,它能保证在最坏的情况下,基本动态集合操作时间为O(lgn).

问题1:为什么不使用二叉排序树?
问题主要出现在二叉排序树在添加元素的时候极端情况下会出现线性结构。
举例说明:由于二叉排序树左子树所有节点的值均小于根节点的特点,如果我们添加的元素都比根节点小,会导致左子树线性增长,这样就失去了用树型结构替换链表的初衷,导致查询时间增长。所以这是不用二叉查找树的原因。

问题2:为什么不使用AVL或者B树呢?
引入RB-Tree是功能、性能、空间开销的折中结果:
①红黑树不追求"完全平衡",任何不平衡都会在三次旋转之内解决,而AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多。
②红黑树的查询性能只略微逊色于AVL树,但红黑树在插入和删除上优于AVL树,AVL树每次插入删除会进行大量的平衡度计算,而红黑树为了维持红黑性质所做的红黑变换和旋转的开销,相较于AVL树为了维持平衡的开销要小得多
而不用B/B+树的原因:
B和B+树主要用于数据存储在磁盘上的场景,比如数据库索引就是用B+树实现的。这两种数据结构的特点就是树比较矮胖,每个结点存放一个磁盘大小的数据,这样一次可以把一个磁盘的数据读入内存,减少磁盘转动的耗时,提高效率。而红黑树多用于内存中排序,也就是内部排序。

9.https和http区别,有没有用过其他安全传输手段?

HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

HTTPS和HTTP的区别主要如下:
  1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
  2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
  3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

常见协议有:Telnet(远程登录协议)、FTP(文件传输协议)、SMTP(邮件传输协议)、HTTP(超文本传输协议)、DNS(域名系统)等。

————————————————
版权声明:本文为CSDN博主「xyx」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011863024/article/details/114684428

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值