Java面试题总结二

来源:互联网 发布:知乎 不能修改提问 编辑:程序博客网 时间:2024/05/16 03:22

基础题

1.final,finally,finalize的区别

    a.final修饰类,类不可被继承。修饰方法,方法不可被重写。修饰变量,变量值不能改变。    b.finally是异常处理语句的一部分,finally语句中的内容一定会被执行。    c.finalizefinalize方法来自于java.lang.Object,用于回收资源。可以为任何一个类添加finalize方法。finalize方法将在垃圾回收器清除对象之前调用。在实际应用中,不要依赖使用该方法回收任何短缺的资源,这是因为很难知道这个方法什么时候被调用。

2.写出XMLHttpRequest对象与服务器交互的五种状态?如何判断此次请求成功?

XMLHttpRequest是Ajax的核心对象,用于后台与服务器的交互,以下为交互的五种状态:
这里写图片描述
判断请求成功的标志:

//xhr表示XMLHTTPRequest对象if(xhr.status==200 && xhr.readyState==4){}

3.js中的onload加载有哪些特征?

window.onload 回调函数其实是在页面加载完成后(包括图片内容的显示)才会执行,并不是页面加载的等待过程中就执行,load方法的执行标志着页面所有元素都已经加载好了,可以使用了。

4.jsp有哪些内置对象,都有哪些作用?

jsp有9大内置对象:request、response、session、application、config、page、pagecontext、exception、out。
各自的作用:
request对象:代表客户端请求的信息,该对象封装了用户提交的信息,通过调用该对象相应的方法要以获取封装的信息。另外一次请求产生一个request对象。
response对象:代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。另外一次响应产生一个response对象。
session对象:是由服务器自动创建的与用户请求相关的对象。服务器为每个用户都生成一个session对象,用于保存该用户的信息,跟踪用户的操作状态。
application对象:可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应用中都有效。
out对象:用于在Web浏览器内输出信息,并且管理应用服务器上的输出缓冲区。
config对象:取得服务器的配置信息。
pageContext 对象:取得任何范围的参数,通过它可以获取 JSP页面的out、request、reponse、session、application 等对象。pageContext对象的创建和初始化都是由容器来完成的,在JSP页面中可以直接使用 pageContext对象。
page 对象:代表JSP本身,只有在JSP页面内才是合法的。
exception:显示异常信息,只有在包含 isErrorPage=”true” 的页面中才可以被使用,在一般的JSP页面中使用该对象将无法编译JSP文件。

5.jsp:include动作标记和include指令标记的区别??

include指令标记读入指定页面的内容并把这些内容和原来的页面内容融合到一起。这个过程发生在JSP转化成Servlet的阶段,最终所合成的JSP文件被Servlet容器转化成servlet。如果一个JSP页面使用include指令包含了另一个JSP页面,最终也只产生一个Servlet的Java源文件和一个class文件。
使用<jsp:include>动作标记包含其他JSP页面,其本质是调用了被包含文件所转化的Servlet对象的jspService()方法。也就是说,所被包含的JSP文件也对应有生成的Servlet源文件和class文件。如果一个JSP页面使用include动作包含了另一个JSP页面,一共会产生两个Servlet源文件和两个class文件。
简单的概括一下,主要有两个方面的不同:
一:执行时间上:

//是在翻译阶段执行<%@ include file=”relativeURI”%>// 在请求处理阶段执行.<jsp:include page=”relativeURI” flush=”true” /> 

二:引入内容的不同:

//引入静态文本(html,jsp),在JSP页面被转化成servlet之前和它融和到一起.<%@ include file=”relativeURI”%>//引入执行页面或servlet所生成的应答文本.<jsp:include page=”relativeURI” flush=”true” />

6.char类型的变量能不能存储一个中文汉字?为什么?

可以的。Java默认使用的是Unicode编码字符集,一个Unicode码元占两个字节,Java中char类型的变量用来存储Unicode字符的,而汉字也是用Unicode表示的,所以可以存储一个汉字。

7.谈一谈你对静态存储区,堆,栈的理解?

栈stack:是一种先进后出(或后进先出)的数据结构,Java中栈的大小和生存期是确定的,在执行方法时,方法体的局部变量的存储单元在栈中被创建,方法调用执行结束这些存储单元会被自动释放掉。因为栈内存分配运算是置于CPU指令集中的,栈的存取速度比较快。栈中一般存放的是局部变量、基本数据类型本变量和对象的引用变量,栈中的数据可以共享(与常量池有关)。
堆heap:是一个运行时的数据区,类的对象在其中分配内存,堆的内存大小是通过new等方式来动态分配的,生存期不需要预先设定,当对象不再被使用时会变成垃圾对象,程序通过垃圾回收器进行回收这些占用内存而无效的数据。Java中的所有创建的对象在堆中被分配内存空间,在栈上会有一个指向堆对象的引用。
静态存储区:用来存放全局数据和用static修饰的变量,内存在编译的时候已经分配好,在程序的整个生命周期都存在。

8.Java多线程中的wait()方法是对象方法还是线程方法?区分一下与sleep()方法的区别?

wait()属于object的final native方法。
多线程中常见的基础面试题如下,仅供参考!
简单说一下多线程:多线程运行机制是一种抢占形式的,即多个线程处于可运行状态时只有其中一个线程在运行。
———-
1.sleep()与wait()的区别?
程序中二者都会使线程进行某种形式的暂停。wait()解决的事线程同步问题,属于object方法,在等待条件为真并且线程被唤醒才释放锁,只能用于同步方法或者同步控制块中,不需要捕获异常。而sleep()仅仅释放CPU资源或用于线程暂停一段时间,没有释放锁,可以用在任何地方但需要捕获异常InterruptedException。

2.sleep()与yiel()区别?
sleep()使当前线程转为阻塞状态,规定暂停时间(单位毫秒)后重新回到就绪状态,暂停期间该线程不可执行。yield()当前线程让出CPU的占有权给同级或更高等级的线程,但自己仍处于可执行状态。

3.notify()与notifyAll()区别?
notify()唤醒在对象监视器上等待的单个线程,在多线程中使用具有局限性,notifyAll()则是唤醒在对象监视器上等待的所有线程。

4.为什么wait和notify方法要在同步块中调用?
只有在调用线程拥有某个对象的独占锁时,才能够调用该对象的wait(),notify()和notifyAll()方法。这一点通常不会被程序员注意,因为程序验证通常是在对象的同步方法或同步代码块中调用它们的。如果尝试在未获取对象锁时调用这三个方法,那么你将得到一个”java.lang.IllegalMonitorStateException:current thread not owner”。
(一是API要求这样做,不然会抛IllegalMonitorStateException异常;二是为了避免wait和notify之间产生竞态条件。)

5.Thread类中的yield方法有什么作用?
Yield方法可以暂停当前正在执行的线程对象,让其它有相同优先级的线程执行。它是一个静态方法而且只保证当前线程放弃CPU占用而不能保证使其它线程一定能占用CPU,执行yield()的线程有可能在进入到暂停状态后马上又被执行。

6.什么是 daemon?
daemon Thread是守护线程,作用是为其他线程提供便利服务的,例如垃圾回收线程GC就是一个比较称职的守护者。

7.进程与线程的区别?
进程是操作系统进行调度和分配的独立单位,一个进程包含了一个或多个线程,进程之间的切换资源开销较大。
线程是CPU进行调度和分配资源的最小单位,是进程的子集,线程之间切换开销小。

8.为什么在执行wait, notify时,必须获得该对象的锁?
这是因为,如果没有锁,wait和notify有可能会产生竞态条件(Race Condition)。考虑以下生产者和消费者的情景:
1.1生产者检查条件(如缓存满了)-> 1.2生产者必须等待
2.1消费者消费了一个单位的缓存 -> 2.2重新设置了条件(如缓存没满) -> 2.3调用notifyAll()唤醒生产者
我们希望的顺序是: 1.1->1.2->2.1->2.2->2.3
但在多线程情况下,顺序有可能是 1.1->2.1->2.2->2.3->1.2。也就是说,在生产者还没wait之前,消费者就已经notifyAll了,这样的话,生产者会一直等下去。
所以,要解决这个问题,必须在wait和notifyAll的时候,获得该对象的锁,以保证同步。JVM通过在执行的时候抛出IllegalMonitorStateException的异常,来确保wait, notify时,获得了对象的锁,从而消除隐藏的Race Condition。
———-

9.谈谈对事务特性中的隔离性的理解?

事务:以可控的方式对数据资源访问的一组操作。

事务的四大属性:原子性Atomicity,一致性Consistency,隔离性Isolation和持久性Durability。其中的隔离性指的是对数据资源的并发访问时,各个事务之间相互影响的程度。

当多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性,如果不考虑事务的隔离会出现以下3种问题*
脏读Drity Read:在一个事务处理过程里读取了另一个未提交的事务中的数据。
例如:以转账为例,对应SQL语句如下所示:     

//1.A向B转帐500元update account set money=money+500 where name='B';    //2.B收入来自A的500元转账update account set money=money-500  where name='A';

当第1条SQL执行完,第2条还没执行(A未提交时),如果此时B查询自己的帐户,就会发现自己多了500元钱。如果A等B走后再回滚,B就会损失500元,这是很可怕的。 
 
不可重复读Non-repeatable read:在一个事务内读取表中的某一行数据,多次读取结果不同。
例如:B想查询A帐户余额,第一次查询A帐户为200元,此时A向帐户内存了100元并提交了,B接着又进行了一次查询,此时A帐户为300元了。B两次查询不一致,可能会怀疑人生了:不知道哪次查询是准的。

幻读Phantom Read:在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
例如:A存款100元未提交,这时银行做报表统计account表中所有用户的总额为500元,然后A提交了,这时银行再统计发现帐户为600元了,造成虚读同样会使银行不知所措,到底以哪个为准。

事务的4个隔离级别,以MySQL数据库为例,隔离级别从高到低有:
① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
② Repeatable read (可重复读):可避免脏读、不可重复读的发生。
③ Read committed (读已提交):可避免脏读的发生。
④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。

总结:隔离级别与系统并发性成反比,与数据一致性成正比。隔离级别越高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。

在MySQL数据库中操作事务的隔离级别:
一、查看事务的当前隔离级别:select @@tx_isolation;
二、设置事务的隔离级别: set transaction isolation level 隔离级别名称; 或者 set tx_isolation=’隔离级别名称’;
三、开启事务:start transaction
四、提交事务:commit
五、事务回滚:rollback
通过手动回滚事务,让所有的操作都失效,这样数据就会回到最初的初始状态。
参考博客:
http://www.cnblogs.com/xdp-gacl/p/3984001.html
http://blog.csdn.net/wenzhihui_2010/article/details/9180931

10.当多个用户请求同一个jsp页面时,服务器会为每个客户启动一个进程吗?

不是的,而是为每一个客户启动一个线程。servlet默认单例模式,但支持多线程请求,在servlet的生命周期中servlet只被实例化一次,在客户端有多个客户请求同一个servlet时,servlet容器会通过线程调度的方式调度容器下管理的线程池中等待的线程给请求的客户。

原创粉丝点击