Java基础面试题

巩固基础,砥砺前行 。
只有不断重复,才能做到超越自己。
能坚持把简单的事情做到极致,也是不容易的。

Java基础面试题

什么是面相对象?谈谈对面向对象的理解?

jdk jre jvm他们的关系是什么?

==和equal ?

==比较的是栈中的值。基本类型比较的是数值(在栈中初始化),对象比较的是堆中对象的地址.

ArrayList和LinkedList区别

ArrayList:基于动态数组,连续内存存储,适合下标访问(随机访问),扩容机制:因为数组长度固定,超出长度存数据时需要新建数组,然后将老数组的数据拷贝到新数组,如果不是尾部插入数据还会涉及到元素的移动(往后复制一份,插入新元素),使用尾插法并指定初始容量可以极大提升性能、甚至超过linkedList(需要创建大量的node对象)

LinkedList:基于链表,可以存储在分散的内存中,适合做数据插入及删除操作,不适合查询:需要逐一遍历遍历LinkedList必须使用iterator不能使用for循环,因为每次for循环体内通过get()取得某一元素时都需要对list重新进行遍历,性能消耗极大。另外不要试图使用indexOf等返回元素索引,并利用其进行遍历,使用indexlOf对list进行了遍历,当结果为空时会遍历整个列表。

1.首先,他们的底层数据结构不同,ArayList底层是基于数组实现的,LinkedList底层是基于链表实现的

2.由于底层数据结构不同,他们所适用的场景也不同,ArrayList更适合随机查找,LinkedList更适合删除和添加,查询、添加、删除的时间复杂度
不同

3.另外ArrayList和LinkedList都实现了List接口,但是LinkedList还额外实现了Deque接口,所以LinkedList还可以当做队列来使用

String、StringBuffer、StringBuilder的区别

1.String是不可变的,如果尝试去修改,会新生成一个字符串对象,StringBuffer和StringBuilder是可变的
2.StringBuffer是线程安全的,StringBuilder是线程不安全的,所以在单线程环境下StringBuilder效率会更高

HashMap的扩容机制原理

1.7版本
1.先生成新数组
2.遍历老数组中的每个位置上的链表上的每个元素
3.取每个元素的key,并基于新数组长度,计算出每个元素在新数组中的下标
4.将元素添加到新数组中去
5.所有元素转移完了之后,将新数组赋值给HashMap对象的table属性

1.8版本
1.先生成新数组
2.遍历老数组中的每个位置上的链表或红黑树
3.如果是链表,则直接将链表中的每个元素重新计算下标,并添加到新数组中去
4.如果是红黑树,则先遍历红黑树,先计算出红黑树中每个元素对应在新数组中的下标位置
a.统计每个下标位置的元素个数
b.如果该位置下的元素个数超过了8,则生成一个新的红黑树,并将根节点的添加到新数组的对应位置c.如果该位置下的元素个数没有超过8,那么则生成一个链表,并将链表的头节点添加到新数组的对应位
5.所有元素转移完了之后,将新数组赋值给HashMap对象的table属性

CopyOnWriteArrayList的底层原理是怎样的?

1.首先CopyOnWriteArrayList内部也是用过数组来实现的,在向CopyOnWriteArrayList添加元素时,会复制一个新的数组,写操作在新数组上进行,读操作在原数组上进行
2.并且,写操作会加锁,防止出现并发写入丢失数据的问题
3.写操作结束之后会把原数组指向新数组
4.CopyOnWriteArrayList允许在写操作时来读取数据,大大提高了读的性能,因此适合读多写少的应用场景,但是CopyOnWriteArrayList会比较占
内存,同时可能读到的数据不是实时最新的数据,所以不适合实时性要求很高的场景。

ThreadLocal的底层原理?

1.ThreadLocal是Java中所提供的线程本地存储机制,可以利用该机制将数据缓存在某个线程内部,该线程可以在任意时刻、任意方法中获取缓存的数据
2. ThreadLocal底层是通过ThreadLocalMap来实现的,每个Thread对象(注意不是ThreadLocal对象)中都存在一个ThreadLocalMap,Map的key为ThreadLocal对象,Map的value为需要缓存的值
3.如果在线程池中使用ThreadLocal会造成内存泄漏,因为当ThreadLocal对象使用完之后,应该要把设置的key,value,也就是Entry对象进行回收,但线程池中的线程不会回收,而线程对象是通过强引用指向ThreadLocalMap,ThreadLocalMap也是通过强引用指向Entry对象,线程不被回收,Entry对象也就不会被回收,从而出现内存泄漏,解决办法是,在使用了ThreadLocal对象之后,手动调用ThreadLocal的remove方法,手动清楚Entry对象
4.ThreadLocal经典的应用场景就是连接管理(一个线程持有一个连接,该连接对象可以在不同的方法之间进行传递,线程之间不共享同一个连接)

浏览器发出一个请求到收到响应经历了哪些步骤?

1.浏览器解析用户输入的URL,生成一个HTTP格式的请求
2.先根据URL域名从本地hosts文件查找是否有映射IP,如果没有就将域名发送给电脑所配置的DNS进行域名解析,得到IP地址
3.浏览器通过操作系统将请求通过四层网络协议发送出去
4.途中可能会经过各种路由器、交换机,最终到达服务器
5.服务器搜到请求后,根据请求所指定的端口,将请求传递给绑定了该端口的应用程序,比如8080被tomcat占用了
6.tomcat接收到请求数据后,按照http协议的格式进行解析,解析得到所要访问的servlet
7.然后servlet来处理这个请求,如果是SpringMVC中的DispatchServlet,那么则会找到对应的Controller中的方法,并执行该方法得到结果
8.Tomcat得到响应结果后封装成HTTP响应的格式,并再次通过网络发送给浏览器所在的服务器
9.浏览器所在的服务器拿到结果后再传递给浏览器,浏览器则负责解析并渲染

【临渊羡鱼不如退而结网】

你可能感兴趣的:(java,开发语言)