马上就要找工作了, 这段时间一直比较关注常见的java面试题(我以后想从事java软件开发工作),也做了一些总结,总结如下:
1.谈谈final, finally, finalize的区别(经常被问到)。
答:final是java中的关键字,修饰符用于声明属性,方法和类,分别表示属性不可改变,方法不可覆盖,类不可继承;
finally是异常处理语句结构的一部分,只能用在try/catch语句中并且附带着一个语句块,表示这段语句最终总是被执行。java的一种异常处理机制。finally是对Java 异常处理模型的最佳补充。finally 结构使代码总会执行,而不管有无异常发生。使用 finally 可以维护对象的内部状态,并可以清理非内存资源。特别是在关闭数据库连接这方面,如果程序员把数据库连接的close()方法放到finally中,就会大大降低程序出错的几率;
finalize是一个方法,Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。属于java.lang.Object类,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。注意:finalize不一定被jvm调用,只有当垃圾回收器要清除垃圾时才被调用。
2.HashMap和Hashtable的区别(http://blog.csdn.net/xaiomessi/article/details/45272539)
3.Collection 和 Collections的区别。
答:Collections是java.util下的类,它包含各种有关集合操作的静态方法;
Collection是java.util下的接口,它是各种结合结构的父接口(List、Set)。
4.short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
答:对于short s1 = 1; s1 = s1 + 1,由于s1 + 1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。对于short s1 = 1; s1 += 1,由于+=是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确解释。
5.java中sleep()和wait()方法的区别。
答:(1)wait()方法是Object类中的方法,而sleep()方法是Thread类中的静态方法;(2)最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。(3)使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用 。
6.Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
答: Override是方法覆盖,用在父子类中,是方法名字相同,参数列表也相同,声明形式都相同,但是子类方法的权限不允许小于父类,不允许抛出比父类更多的异常。调用子类的方法与父类的同名方法无关,在子类中完全覆盖了父类的方法。
Overload是方法重载,是几个方法的名字相同,返回值相同,但是参数列表不同,举例来说就像构造函数,可以有多个构造函数,并且每个的参数列表都不同,这样可以用多种方式构造对象。
Overloaded的方法是可以改变返回值的类型。
7.Erro和Exception的区别。
答:Error类和Exception类都继承自Throwable类。不同点在于,(1)Exception可以是可以被控制的或者不可被控制的,Erro类总是不可被控制;(2)Exception表示一个程序员而导致的错误,Erro经常用来用于表示系统错误或低层资源的错误;(3)Exception应该在应用程序级被处理,Erro如何可能的话,应该在系统级被捕捉。
class People{
public People(){
System.out.print(1);
}
public People(String name){
System.out.print(2);
}
}
class Child extends People{
People father;
public Child(String name){
System.out.print(3);
father=new People(name+":tom");
}
public Child(){
System.out.print(4);
}
}
public class Test{
public static void main(String[] args) {
Child c=new Child("mike");
}
}
结果是:132
要是不信,请看下图,当我把无参的构造函数注释掉后,程序就出现编译错误了
class Parent{
public void hello(){
System.out.println("a");
}
}
public class Child01 extends Parent{
public void hello(){
System.out.println("b");
}
public void hello(String a){
System.out.println(a);
}
public static void main(String[] args) {
Parent child=new Child01();
child.hello();//父类调用自己的方法
child.hello("jiang");//这里出现了编译错误,因为子类的方法对父类不可见
}
}
2、传值方式不同。在forward方式下,当前文件和目标文件属于同一次请求,共享request对象,所以可以使用request对象传值。在redirect方式下,当前文件和目标文件属于不同的请求,每次请求会单独创建request和response对象,这样就不能使用request对象来传值。在MVC模式下,通常在控制器中调用模型得到数据,然后保存到request中,然后forward到目标文件,目标文件从request中获取需要的信息。如果使用sendRedirect方式在控制器和视图之间传递信息,需要使用在目标文件之后加上“?名字=值”的方式传递。
3、客户端在地址栏中看到的地址不一样,对于forward,在地址栏中看到的是第1个文件的名字,对于sendRedirect,在地址栏中看到的是第2个文件的地址。有时候会影响目标文件中的相对路径,例如当前文件是aa文件夹中的a.jsp,目标文件是bb文件夹中的b.jsp,在b.jsp中要访问一个图片,使用相对路径,直接写face.jpg,这个文件与b.jsp放在一起。如果采用forward方式,地址栏中是a.jsp,这样系统会在aa文件夹中找face.jpg,这时候就会出错。
动态INCLUDE用jsp:include动作实现<jsp:include page=included.jsp flush=true />它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数 ;静态INCLUDE用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面<%@ include file=included.htm %>
17.jsp有哪些内置对象?作用分别是什么? 分别有什么方法?
JSP共有以下9个内置的对象:
request 用户端请求,此请求会包含来自GET/POST请求的参数
response 网页传回用户端的回应
pageContext 网页的属性是在这里管理
session 与请求有关的会话期
application servlet 正在执行的内容
out 用来传送回应的输出
config servlet的构架部件
page JSP网页本身
exception 针对错误网页,未捕捉的例外
request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie, header, 和session数据的有用的方法。
response表示HttpServletResponse对象,并提供了几个用于设置送回浏览器的响应的方法(如cookies,头信息等)
out对象是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果。
pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,并且包装了通用的servlet相关功能的方法。
session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息
applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息
config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。
page表示从该页面产生的一个servlet实例。
18.Http请求中GET和POST方式的区别
(1)get是从服务器上获取数据,post是想服务器传送数据。在客户端,get方式在通过URL提交数据,数据在URL可以看到;而Post方式。数据放置在HTML HEADER内提交;
(2)get方式提交的数据最多为1024个字节,而post理论上没有限制;
(3)get方式的安全性比post方式的安全性要低,理由是(1);安全性要求比较高的建议用post方式提交数据,不要求安全性的可以用post提交。
19.Java内存中堆和栈的区别
Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。
堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。
这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!
20 Servlet 的生命周期
在javax.servlet.Servlet接口中有3个重要的方法,分别是init()、destroy()和service()方法。这三个方法分别对应Servlet生命周期的三个阶段,加上Servlet是一个java类,所以还有加载过程。一共是四个阶段,分别是加载、初始化、提供服务和销毁。
1、加载
加载阶段指的是Servlet类加载到java虚拟机当中,并且实例化。在这个过程中,Web容器会调用Servlet类的公开的无参数构造器方法,产生一个Servlet类的实例对象,也就是由该对象来提供服务。默认情况下,servlet是在第一次请求时被加载,但是可以通过<load-on-startup>标签设置Servlet在web容器启动的时候加载。如果servlet类没有提供无参数的构造方法或者该构造方法不是公开的,将加载失败;
2.初始化
该阶段指的是为Servlet做初始化工作,Web容器在初始化Servlet的时候回调用init()方法,所以,一般的初始化代码会放在这个方法当中,如代开数据源等。
3.提供服务
这一个阶段指的是HTTP请求指向Servlet的时候。调用service()方法的过程。该方法体包含了该Servlet的业务逻辑,如果是继承自HttpServlet的话,根据HTTP请求类型的不同,业务逻辑代码会包含在doGet或者doPost方法中。
4.销毁
Servlet对象不可能长存,它总有销毁的时候,例如,重新部署Web应用、关闭Web容器等。它对应的回调方法是destory(),一般释放资源的代码会放在这个方法中。