Java基础面试(一)
Java基础
1、Java中的几种基本数据类型是什么,各自占用多少个字节。
Boolean(1位,只有true和false)、byte(8位,1字节)、char(16位,2字节)、short(16位,2字节)、int(32位,4字节)、long(64位,8字节)、float(32位,4字节)、double(64位,8字节)。
long型整数在内存中占用8字节共64位,它表示的数值有2的64次方,平分正负,数值范围是-2^63~2^63-1。
而float在内存中占4字节32位。数值表示为:
2、String类能被继承吗,为什么。
不能,public final class String { }。
3、Array List和LinkedList的区别。
(1)ArrayList是基于动态数组实现的,LinkedList是基于链表的数据结构。
(2)相对于Array List,LinkedList插入更快,因为LinkedList不像ArrayList一样,不需要改变数组大小,也不需要在数组装满时将所有数据重新装入一个新的数组,ArrayList插入最坏的时间复杂度是O(n),而LinkedList中插入或删除的时间复杂度仅为O(1)。
(3)ArrayList是基于索引的数据结构,它使用索引在数组中搜索和读取更快,时间复杂度是O(1)。
4、IO模型有哪些,NIO是什么。
5、中断和异常是什么?有什么区别?
中断是CPU暂停当前工作,有计划的去处理其他的事情。系统停止当前正在执行的程序而转向其他服务,可能是因为优先级高的请求。中断的发生一般是可以预知的,处理过程也是事先制定好的。处理中断时程序是正常运行的。
异常是CPU遇到了无法响应的工作,而后进入一种非正常的状态,异常的出现表明程序有缺陷。异常是软件运行过程中的一种开发过程中没有考虑到的程序错误。
中断是CPU所具备的功能,属于硬件层面。而异常属于软件层面。
6、虚拟内存和虚拟地址是什么?
虚拟地址:程序访问存储器所使用的逻辑地址称为虚拟地址,虚拟地址是4G虚拟地址空间中的地址程序中使用的都是虚拟地址。每一个进程都分配有一个4G的虚拟地址。通过虚拟地址访问内存的形式称为保护模式。
虚拟内存:通常是再系统物理内存用完时,才会使用到。所谓的虚拟内存其实就是内存的一种管理方式,实现对于逻辑上对于内存容量的扩展,使用硬盘(文件)来模拟的内存空间。
数据结构(红黑数、B+Tree)
1、synchronized的原理?
synchronized是Java中解决并发问题的一种常用方法,作用主要有3个:(1)确保线程互斥的访问同步代码;(2)确保共享变量的修改能够即时可见;(3)有效的解决重排序问题。
Java中每个对象都可以作为锁,(1)普通同步方法,锁是当前实例对象;(2)静态同步方法,锁是当前类的class对象;(3)同步方法块,锁是括号里面的对象。
synchronized是通过一个monitor(监视器锁)对象来完成。
同步指令执行到monitorenter时,(1)每个对象都有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,,过程如下:(1)如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者;(2)如果线程已经占有了该monitor,只是重新进入,则进入monitor的进入数加1;(3)如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
同步指令执行到monitorexit时,执行monitor exit的线程必须是objectref所对应的monitor的所有者。指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者,其他被这个monitor阻塞的线程可以尝试去获取这个monitor的所有权。
2、红黑树的定义?为什么是平衡树?怎么维护平衡?
RB Tree又称为红黑树,是一种特殊的二叉查找树,每个节点上的存储位表示节点的颜色,可以是红(Red)或黑(Black)。是通过旋转保持平衡的。
红黑树的五个特性:
(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点是黑色(叶子节点指为空或null的叶子节点)。
(4)如果一个节点是红色的,则它的两个儿子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
红黑树的时间复杂度为: O(lgn)
(1)左旋伪代码如下:
LEFT-ROTATE(T, x)
y ← right[x] // 前提:这里假设x的右孩子为y。下面开始正式操作
right[x] ← left[y] // 将 “y的左孩子” 设为 “x的右孩子”,即 将β设为x的右孩子
p[left[y]] ← x // 将 “x” 设为 “y的左孩子的父亲”,即 将β的父亲设为x
p[y] ← p[x] // 将 “x的父亲” 设为 “y的父亲”
if p[x] = nil[T]
then root[T] ← y // 情况1:如果 “x的父亲” 是空节点,则将y设为根节点
else if x = left[p[x]]
then left[p[x]] ← y // 情况2:如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子”
else right[p[x]] ← y // 情况3:(x是它父节点的右孩子) 将y设为“x的父节点的右孩子”
left[y] ← x // 将 “x” 设为 “y的左孩子”
p[x] ← y // 将 “x的父节点” 设为 “y”
(2)插入操作
①将红黑树当作一棵二叉查找树,将节点插入。红黑树本身是一棵二叉查找树,将节点插入后,仍然是一棵二叉查找树。
②将插入的节点着色为红色。