2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Java面试题参考答案I

Java面试题参考答案I

时间:2022-07-05 11:59:56

相关推荐

Java面试题参考答案I

1. 简单说一下面向对象的特征和六大原则:

①面向对象的特征:

封装、继承、多态

1)封装:将信息隐藏,利用抽象数据,将一段逻辑以及数据保护起来,并且对外开放接口

2)继承:个性对共性属性与方法的接受,并加入个性特有的属性和方法。

3)多态:程序中定义的引用变量,所指向的具体类型和具体调用方法,在编译期不能确定,而是在程序运行期确定。

②六大原则:

1)单一职责原则:一个类只负责一项职责

2)里氏替换原则:只要弗雷出现的地方,子类也可出现

3)依赖倒置原则:程序依赖抽象,而不依赖具体实现,减少程序间的耦合性

4)接口隔离原则:客户端不应该依赖他不需要的接口,一个类对另一个类的依赖应建立在最小接口上

5)迪米特原则:一个对象应该对其他对象保持最小的了解

6)开闭原则:类、实体、模块应该对扩展开放,对修改关闭

2. 谈谈final、finally、finalize的区别:

①final:一种修饰词,用来修饰类、方法、变量

final修饰的类,不可继承

final修饰的方法,不可重写

final修饰的变量,不可修改

②finally:Java关键字,用于Java异常捕捉中,与try-catch同用,表示 在捕获异常时,无论如何都会执行的代码块,大多用于释放资源, 保证解锁等工作

③finalize:一个方法,属于Object类,属于GC运行机制中的一部分,当 GC清除他所从属的对象时被调用的,如果执行它的过程中跑出 无法捕获的异常,GC将终止对该对象的清理,并且该异常会被 忽略,知道下次GC开始清理这个对象,该方法会再次被调用

3. Java中的==、equals与hashCode的区别和联系:

①==:用于比较两个数据是否相等

1) 若对比的为基本数据类型,比较的是数值的大小

2) 若对比的引用数据类型,比较的是引用地址是否相等,即两个对象 是否为同个对象

3) 若为Integer类的对比,若数值在[-128,127]区间,可用来对比, 因为在此区间创建Integer对象时jvm会进行缓存,因此是同一个 对象,所以Integer要用equals方法进行对比

②equals:存在于Object的方法,用于两个对象按用户定义的方法判断是 否相等,若是类中未重写此方法,则与==用法相同

③hashcode:存在于Object的方法,用于提高查找的快捷性,因为hashCode 也是在Object对象中就有的,所以所有Java对象都有hashCode, 在HashTable和HashMap这一类的散列结构中,都是用HashCode来 查找在散列表中的位置的

P.S:如果两个对象equals,他们的hashCode必定相等

如果两个对象hashCode相等,equals不一定会相等

4. 谈谈Java容器ArrayList、LinkedList、HashMap、HashSet的理解:

①ArrayList:

ArrayList是一个数组队列,相当于动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List,RandomAccess,Cloneable,java.io.Serializable这些接口。

ArrayList继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。

ArrayList实现了RandmoAccess接口,即提供了随机访问的功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。

ArrayList实现了Cloneable接口,即覆盖了函数clone(),能被克隆。

ArrayList实现了java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。

②LinkedList:

LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。

LinkedList 实现 List 接口,能对它进行队列操作。

LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。

LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。

LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。

LinkedList 是非同步的。

③HashMap:

HashMap是用于存储Key-Value键值对的集合(每一个键值对也叫做一个Entry)(无顺序)。

HashMap是根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值。

HashMap是键key为null的记录至多只允许一条,值value为null的记录可以有多条。

HashMap是非线程安全。

HashMap是由数组+链表+红黑树实现的。

④HashSet:

HashSet 是一个没有重复元素的集合。

它是由HashMap实现的,不保证元素的顺序,而且HashSet允许使用 null 元素。

HashSet是非同步的。如果多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它必须保持外部同步。这通常是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装” set。

5. 谈谈线程的基本状态,其中的wait()、sleep()、yield()方法的区别:

①线程的基本状态:

1)新建状态(New):当线程对象对创建后,即进入了新建状态

如:Thread t = new MyThread();

2)就绪状态(Runnable):当调用线程对象的start()方法(t.start();), 线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经 做好了准备,随时等待CPU调度执行,并不是说执行了t.start() 此线程立即就会执行;

3)运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时 线程才得以真正执行,即进入到运行状态。注:就绪状态是 进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执 行,首先必须处于就绪状态中;

4)阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放 弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到 就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞 产生的原因不同,阻塞状态又可以分为三种:

4.1)等待阻塞:运行状态中的线程执行wait()方法,使本线程进入 到等待阻塞状态;

4.2)同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被 其它线程所占用),它会进入同步阻塞状态;

4.3)其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O 请求时,线程会进入到阻塞状态。当sleep()状态超时、join() 等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就 绪状态。

5)死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该 线程结束生命周期。

6. JVM性能调优的监控工具有哪些:

①jps

②jstack

③jmap

④jstat

7. 简单谈谈JVM内存模型,以及volatile关键字:

虽然java程序所有的运行都是在虚拟机中,涉及到的内存等信息都是虚拟机的一部分,但实际也是物理机的,只不过是虚拟机作为最外层的容器统一做了处理。虚拟机的内存模型,以及多线程的场景下与物理机的情况是很相似的,可以类比参考。

Java内存模型的主要目标是定义程序中变量的访问规则。即在虚拟机中将变量存储到主内存或者将变量从主内存取出这样的底层细节。需要注意的是这里的变量跟我们写java程序中的变量不是完全等同的。这里的变量是指实例字段,静态字段,构成数组对象的元素,但是不包括局部变量和方法参数(因为这是线程私有的)。这里可以简单的认为主内存是java虚拟机内存区域中的堆,局部变量和方法参数是在虚拟机栈中定义的。但是在堆中的变量如果在多线程中都使用,就涉及到了堆和不同虚拟机栈中变量的值的一致性问题了。

主内存:java虚拟机规定所有的变量(不是程序中的变量)都必须在主内存中产生,为了方便理解,可以认为是堆区。可以与前面说的物理机的主内存相比,只不过物理机的主内存是整个机器的内存,而虚拟机的主内存是虚拟机内存中的一部分。

工作内存:java虚拟机中每个线程都有自己的工作内存,该内存是线程私有的为了方便理解,可以认为是虚拟机栈。可以与前面说的高速缓存相比。线程的工作内存保存了线程需要的变量在主内存中的副本。虚拟机规定,线程对主内存变量的修改必须在线程的工作内存中进行,不能直接读写主内存中的变量。不同的线程之间也不能相互访问对方的工作内存。如果线程之间需要传递变量的值,必须通过主内存来作为中介进行传递。

Volatile:

volatile是一个特征修饰符.volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略(比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问),且要求每次直接读值。

volatile对应的变量可能在你的程序本身不知道的情况下发生改变比如多线程的程序,共同访问的内存当中,多个程序都可以操纵这个变量

一般说来,volatile用在如下的几个地方:

1、中断服务程序中修改的供其它程序检测的变量需要加volatile;

2、多任务环境下各任务间共享的标志应该加volatile;

3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义;

8. 谈谈垃圾收集器与内存分配策略:

①Serial收集器

串行收集器是最古老,最稳定以及效率高的收集器,可能会产生较长的停顿,只使用一个线程去回收。新生代、老年代使用串行回收;新生代复制算法、老年代标记-压缩;垃圾收集的过程中会Stop The World(服务暂停)。

②ParNew收集器

ParNew收集器其实就是Serial收集器的多线程版本。新生代并行,老年代串行;新生代复制算法、老年代标记-压缩。

③Parallel收集器

Parallel Scavenge收集器类似ParNew收集器,Parallel收集器更关注系统的吞吐量。可以通过参数来打开自适应调节策略,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或最大的吞吐量;也可以通过参数控制GC的时间不大于多少毫秒或者比例;新生代复制算法、老年代标记-压缩。

④Parallel Old 收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。这个收集器是在JDK 1.6中才开始提供。

⑤CMS收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用都集中在互联网站或B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器是基于“标记-清除”算法实现的。

G1收集器

G1是目前技术发展的最前沿成果之一,HotSpot开发团队赋予它的使命是未来可以替换掉JDK1.5中发布的CMS收集器。

9. 谈谈垃圾收集算法:

①标记-清除算法:

算法分为“标记”和“清除”两阶段,首先标记所有需要回收的对象, 在标记完成后,统一回收所有被标记的对象。

②复制算法:

将可用内存按容量划分为大小相等的两块,每次只使用其中的一块,当 这一块内存用完了,就将还存活的对象复制到另一块上面,再将已使 用的内存空间一次性清除。

③标记-整理算法:

标记过程和标记-清除算法一样,标记完成后,让所有存活的对象向一端 移动,然后直接清除边界之外的内存。

④分代收集算法:

根据对象存活周期的不同,将内存分为新生代和老年代,然后根据各个 年代的特点,采用最适当的收集算法。

例:新生代中,每次垃圾手机都有大量对象死去,选用复制算法。

老年代中,存活率较高,没有额外的空间对它进行分配担保,必须 使用“标记-清除算法”或者“标记-整理算法”回收

10. MySQL中常用的存储引擎区别:

①MyISAM:

MyISAM的锁级别为表锁,表锁优点是开销小,加锁快;缺点是锁粒度大,发生锁冲动概率较高,容纳并发能力低,这个引擎适合查询为主的业务。

此引擎不支持事务,也不支持外键。

MyISAM强调了快速读取操作。它存储表的行数,于是SELECT COUNT(*) FROM TABLE时只需要直接读取已经保存好的值而不需要进行全表扫描。

②InnoDB:

InnoDB 存储引擎最大的亮点就是支持事务,支持回滚。

锁级别为行锁,行锁优点是适用于高并发的频繁表修改,高并发是性能 优 于 MyISAM。缺点是系统消耗较大,索引不仅缓存自身,也缓存数据, 相 比 MyISAM 需要更大的内存。

InnoDB 中不保存表的具体行数,也就是说,执行 select count(*) from table时,InnoDB 要扫描一遍整个表来计算有多少行。

③Memory:

Memory 是内存级别存储引擎,数据存储在内存中,所以他能够存储的数 据量较小。

因为内存的特性,存储引擎对数据的一致性支持较差。锁级别为表锁, 不支持事务。但访问速度非常快,并且默认使用 hash 索引。

Memory存储引擎使用存在内存中的内容来创建表,每个Memory表只实 际对应一个磁盘文件,在磁盘中表现为.frm文件。

11. 数据库的事务隔离级别:

①SERIALIZABLE(串行化):

当数据库系统使用SERIALIZABLE隔离级别时,一个事务在执行过程中完全看不到其他事务对数据库所做的更新。当两个事务同时操作数据库中相同数据时,如果第一个事务已经在访问该数据,第二个事务只能停下来等待,必须等到第一个事务结束后才能恢复运行。因此这两个事务实际上是串行化方式运行。

②REPEATABLE READ(可重复读):

当数据库系统使用REPEATABLE READ隔离级别时,一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他事务对已有记录的更新。

③READ COMMITTED(读已提交数据):

当数据库系统使用READ COMMITTED隔离级别时,一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且还能看到其他事务已经提交的对已有记录的更新。

④READ UNCOMMITTED(读未提交数据):

当数据库系统使用READ UNCOMMITTED隔离级别时,一个事务在执行过程中可以看到其他事务没有提交的新插入的记录,而且还能看到其他事务没有提交的对已有记录的更新。

12. 这有5亿整数的大文件,怎么排序:

使用外部排序:

利用分治策略,利用外存保存中间结果,再用多路归并来排序;

内存中维护一个极小的核心缓冲区memBuffer,将大文件bigdata按行读入,搜集到memBuffer满或者大文件读完时,对memBuffer中的数据调用内排进行排序,排序后将有序结果写入磁盘文件

循环利用memBuffer直到大文件处理完毕,得到n个有序的磁盘文件,再采取多路归并排序进行排序

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。