Java 经典面试题答案解析

一、String,StringBuffer, StringBuilder 的区别

(1)String是不可变的,其为final的类,具体表现为

String s1 = new String("a");  //从栈中新建变量s1指向堆中新建的"a"

String s2 = new String("b"); //从栈中新建变量s2指向堆中新建的"b"

s1 += s2;//堆中新建一个更大size的“ab”,栈中s1指向"ab"

(2)StringBuffer和StringBuilder在(1)中示例则是通过append在原数组上扩展

前者是同步的,后者不是同步的

public static void fun() {
    for (i = 0; i < 1000; i++){
        System.out.println(i);
    }
}
假设有两个人(线程)同时调用这个方法,

如果线程同步,那么后调用的人,在前人调用没结束前,必须等待,等待前人

调用结束后方可调用。结果可能是:
1
2
3
4
5
...
1000
1
2
3
4
...
1000

不同步的话,这个方法就可以同时被调用了。结果可能是:
1
2
3
1
2
3
4
4
5
6
5
6
7
...
99
100
100
就是结果是交叉的。
二、VECTOR,ARRAYLIST, LINKEDLIST的区别
Vector是同步的,性能很差
ArrayList类似于数组,获得索引快,插入数据效率低;不同步的
LinkedList是双向链表,按序号索引数据需要进行向前或向后遍历
插入比较快;不同步的

HASHTABLE, HASGMAP,TreeMap区别
(1)Hashmap 根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。
最多只允许一条记录的键为Null;允许多条记录的值为Null
不支持线程的同步如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力
(2)Hashtable 不允许记录的键或者值为空;
支持线程的同步,即任一时刻只有一个线程能写Hashtable,     因此也导致了Hashtale在写入时会比较慢
(3)LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢
(4)TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的

四、j2ee容器组成

Web容器:包括Jsp与Servlet组件,可使用EJB中的组件完成复杂的商务逻辑;
EJB容器:包含组件EJB, EJB规范定义了一个开发和部署分布式 商业逻辑的框架;
Applet容器 包含组件Applet,即可使用J2SE开发Applet;
Application Client容器:包含组件Application Client。

EJB容器负责管理EJB组件。容器的最主要职责是为EJB组件提供安全、事务性、分布式的环境。EJB组件不能显示地使用EJB容器API来请求容器提供的中间件服务,可以隐式地让EJB容器知道它们的需求,比如在基于XML的部署描述符中制定所需的配置信息,在Bean类中使用部署注释请求中间件服务。EJB容器为EJB组件隐式地提供中间件服务。EJB容器提供的中间件服务有:

1 事务管理:EJB容器提供了事务服务,是事务管理和协调的底层实现,以保证操作的健壮性、确定性。事务服务时通过Java事务API(Java Transaction API,JTA)暴露出来的。

2 安全性:EJB能够透明地安全使用。比如,通过设置安全性属性便能够保护客户对EJB方法的访问。

3 资源和生命周期管理:EJB容器为EJB组件管理了大量资源,比如线程、套接字、数据库连接等。EJB容器还管理EJB组件的生命周期,负责创建Bean实例和销毁Bean实例,将Bean实例的状态信息序列化到辅助存储器中,从而实现Bean实例的挂起操作。还能够从辅助存储器中恢复Bean实例的状态,从而实现Bean实例的激活操作。

4 远程可访问能力:容器将不具有网络使能的EJB组件转换成具有分布式网络使能的对象。

5 支持并发请求:EJB容器内置了线程管理支持。通过实例池的形式维护实多个Bean实例,并且能够基于这个池来有效服务并发的客户请求。同一个Bean实例同时只能服务一个客户。

6 集群和负载均衡:集群和负载均衡不是EJB规范规定的标准中间件服务,因此不同容器的配置都不相同。

Web容器实际上是一个Java运行时(Runtime), 提供了Java Servlet API的一个实现, 并且简化了JSP网页.Web容器负责初始化, 调用以及管理Java Servlet和 JavaServer Pag的存活期.



五、Tomcat,apache,jboss的区别

  (1)Apache全球应用最广泛的http服务器,免费,出自apache基金组织  
  (2)Tomcat应用也算非常广泛的web服务器,支持部分j2ee,免费,出自apache基金组织  
  (3)JBoss开源的应用服务器,比较受人喜爱,免费(文档要收费)支持j2ee  
  (4)weblogic应该说算是业界第一的app   server,全部支持j2ee1.4, 

  JBoss和WebLogic都含有Jsp和Servlet容器,也就可以做web容器,
  JBoss和WebLogic也包含EJB容器,是完整的J2EE应用服务器

  tomcat 只能做jsp和servlet的container



六、GET POST区别
1.get是从服务器上获取数据,post是向服务器传送数据。
2.在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放置在HTML HEADER内提交。
3.对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
4.GET方式提交的数据最多只能有1024字节,而POST则没有此限制。
5.安全性问题。正如在(1)中提到,使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。

七、SESSION, COOKIE区别
Session为服务器端的技术,而Cookie是客户端通过浏览器来保存少量的用户信息。
Session的能在多次请求/响应中有效,但是一旦关闭浏览器,Session将失效,而Cookie则会根据setMaxAge函数来控制有效时间,0则立即删除该Cookie,<0保存在内存中,>0则保存在磁盘文件上。

八、Servlet的生命周期
init -> service -> destroy
init和destroy只会执行一次,而service会根据请求多次调用

九、HTTP 报文包含内容
Content-type, ip地址,端口,主机信息,请求类型,请求内容等。

十、Statement与PreparedStatement的区别,什么是SQL注入,如何防止SQL注入
PreparedStatement可以利用setter方法来防止sql注入,而Statement也不行。

十一、redirect, foward区别
redirect为重定向,重定向的地址可以任意,可以是服务器内部的页面,也可以是任意的网站,请求地址会显示在浏览器地址栏。
forward是转发的意思,即一次任务还没有处理完毕,将任务转发给另一web组件继续完成任务,forward会共享request/response,而请求的地址不会显示在地址栏。

十二、关于JAVA内存模型,一个对象(两个属性,四个方法)实例化100次,现在内存中的存储状态,几个对象,几个属性,几个方法。
不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的。其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改。总结java的内存模型,要解决两个主要的问题:可见性和有序性
我们都知道计算机有高速缓存的存在,处理器并不是每次处理数据都是取内存的。JVM定义了自己的内存模型,屏蔽了底层平台内存管理细节,对于java开发人员,要清楚在jvm内存模型的基础上,如果解决多线程的可见性和有序性。
       那么,何谓可见性? 多个线程之间是不能互相传递数据通信的,它们之间的沟通只能通过共享变量来进行。Java内存模型(JMM)规定了jvm有主内存,主内存是多个线程共享的。当new一个对象的时候,也是被分配在主内存中,每个线程都有自己的工作内存,工作内存存储了主存的某些对象的副本,当然线程的工作内存大小是有限制的。当线程操作某个对象时,执行顺序如下:
 (1) 从主存复制变量到当前工作内存 (read and load)
 (2) 执行代码,改变共享变量值 (use and assign)
 (3) 用工作内存数据刷新主存相关内容 (store and write)

可见性:JVM规范定义了线程对主存的操作指令:read,load,use,assign,store,write。当一个共享变量在多个线程的工作内存中都有副本时,如果一个线程修改了这个共享变量,那么其他线程应该能够看到这个被修改后的值。
有序性:线程在引用变量时不能直接从主内存中引用,如果线程工作内存中没有该变量,则会从主内存中拷贝一个副本到工作内存中,这个过程为read-load,完成后线程会引用该副本。当同一线程再度引用该字段时,有可能重新从主存中获取变量副本(read-load-use),也有可能直接引用原来的副本 (use),也就是说 read,load,use顺序可以由JVM实现系统决定。
        线程不能直接为主存中中字段赋值,它会将值指定给工作内存中的变量副本(assign),完成后这个变量副本会同步到主存储区(store- write),至于何时同步过去,根据JVM实现系统决定.有该字段,则会从主内存中将该字段赋值到工作内存中,这个过程为read-load,完成后线程会引用该变量副本


十三、谈谈Hibernate的理解,一级和二级缓存的作用,在项目中Hibernate都是怎么使用缓存的
Hibernate的缓存包括Session的缓存和SessionFactory的缓存,其中SessionFactory的缓存又可以分为两类:内置缓存和外置缓存。Session的缓存是内置的,不能被卸载,也被称为Hibernate的第一级缓存。SessionFactory的内置缓存和Session的缓存在实现方式上比较相似,前者是SessionFactory对象的一些集合属性包含的数据,后者是指Session的一些集合属性包含的数据。SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的拷贝,而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来,SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此SessionFactory不需要进行内置缓存与映射文件的同步。SessionFactory的外置缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的拷贝,外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的第二级缓存。

  Hibernate的这两级缓存都位于持久化层,存放的都是数据库数据的拷贝,那么它们之间的区别是什么呢?为了理解二者的区别,需要深入理解持久化层的缓存的两个特性:缓存的范围和缓存的并发访问策略。

  持久化层的缓存的范围

  缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。

  1 事务范围:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。在此范围下,缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,缓存内的数据通常采用相互关联的的对象形式。

  2 进程范围:缓存被进程内的所有事务共享。这些事务有可能是并发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进程的生命周期,进程结束时,缓存也就结束了生命周期。进程范围的缓存可能会存放大量的数据,所以存放的介质可以是内存或硬盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据形式。松散的对象数据形式有点类似于对象的序列化数据,但是对象分解为松散的算法比对象序列化的算法要求更快。

  3 集群范围:在集群环境中,缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致性,缓存中的数据通常采用对象的松散数据形式。

  对大多数应用来说,应该慎重地考虑是否需要使用集群范围的缓存,因为访问的速度不一定会比直接访问数据库数据的速度快多少。

  持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据,还可以到进程范围或集群范围的缓存内查询,如果还是没有查到,那么只有到数据库中查询。事务范围的缓存是持久化层的第一级缓存,通常它是必需的;进程范围或集群范围的缓存是持久化层的第二级缓存,通常是可选的。

  持久化层的缓存的并发访问策略

  当多个并发的事务同时访问持久化层的缓存的相同数据时,会引起并发问题,必须采用必要的事务隔离措施。

  在进程范围或集群范围的缓存,即第二级缓存,会出现并发问题。因此可以设定以下四种类型的并发访问策略,每一种策略对应一种事务隔离级别。

  事务型:仅仅在受管理环境中适用。它提供了Repeatable Read事务隔离级别。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读和不可重复读这类的并发问题。

  读写型:提供了Read Committed事务隔离级别。仅仅在非集群的环境中适用。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读这类的并发问题。

  非严格读写型:不保证缓存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能,必须为该数据配置一个很短的数据过期时间,从而尽量避免脏读。对于极少被修改,并且允许偶尔脏读的数据,可以采用这种并发访问策略。   只读型:对于从来不会修改的数据,如参考数据,可以使用这种并发访问策略。

  事务型并发访问策略是事务隔离级别最高,只读型的隔离级别最低。事务隔离级别越高,并发性能就越低。

  什么样的数据适合存放到第二级缓存中?

  1、很少被修改的数据

  2、不是很重要的数据,允许出现偶尔并发的数据

  3、不会被并发访问的数据

  4、参考数据

  不适合存放到第二级缓存的数据?

  1、经常被修改的数据

  2、财务数据,绝对不允许出现并发

  3、与其他应用共享的数据。

  Hibernate的二级缓存

  如前所述,Hibernate提供了两级缓存,第一级是Session的缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。第一级缓存是必需的,不允许而且事实上也无法比卸除。在第一级缓存中,持久化类的每个实例都具有唯一的OID。

  第二级缓存是一个可插拔的的缓存插件,它是由SessionFactory负责管理。由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此第二级缓存是进程范围或者集群范围的缓存。这个缓存中存放的对象的松散数据。第二级对象有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。缓存适配器用于把具体的缓存实现软件与Hibernate集成。第二级缓存是可选的,可以在每个类或每个集合的粒度上配置第二级缓存。

  Hibernate的二级缓存策略的一般过程如下:

  1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。

  2) 把获得的所有数据对象根据ID放入到第二级缓存中。

  3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。

  4) 删除、更新、增加数据的时候,同时更新缓存。

  Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query缓存。

  Hibernate的Query缓存策略的过程如下:

  1) Hibernate首先根据这些信息组成一个Query Key,Query Key包括条件查询的请求一般信息:SQL, SQL需要的参数,记录范围(起始位置rowStart,最大记录个数maxRows),等。

  2) Hibernate根据这个Query Key到Query缓存中查找对应的结果列表。如果存在,那么返回这个结果列表;如果不存在,查询数据库,获取结果列表,把整个结果列表根据Query Key放入到Query缓存中。

  3) Query Key中的SQL涉及到一些表名,如果这些表的任何数据发生修改、删除、增加等操作,这些相关的Query Key都要从缓存中清空。

十四、反射讲一讲,主要是概念,都在哪需要反射机制,反射的性能,如何优化
http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html

十六、对Spring的理解,项目中都用什么?怎么用的?对IOC、和AOP的理解及实现原理

1、spring原理

spring的最大作用ioc/di,将类与类的依赖关系写在配置文件中,程序在运行时根据配置文件动态加载依赖的类,降低的类与类之间的藕合度。它的原理是在applicationContext.xml加入bean标记,在bean标记中通过class属性说明具体类名、通过property标签说明该类的属性名、通过constructor-args说明构造子的参数。其一切都是反射,当通过applicationContext.getBean(“id名称”)得到一个类实例时,就是以bean标签的类名、属性名、构造子的参数为准,通过反射实例对象,唤起对象的set方法设置属性值、通过构造子的newInstance实例化得到对象。正因为spring一切都是反射,反射比直接调用的处理速度慢,所以这也是spring的一个问题。

spring第二大作用就是aop,其机理来自于代理模式,代理模式有三个角色分别是通用接口、代理、真实对象。代理、真实对象实现的是同一接口,将真实对象作为代理的一个属性,向客户端公开的是代理,当客户端调用代理的方法时,代理找到真实对象,调用真实对象方法,在调用之前之后提供相关的服务,如事务、安全、日志。其名词分别是代理、真实对象、装备、关切点、连接点。

2、动态代理:不用写代理类,虚拟机根据真实对象实现的接口产生一个类,通过类实例化一个动态代理,在实例化动态代理时将真实对象及装备注入到动态代理中,向客户端公开的是动态代理,当客户端调用动态代理方法时,动态代理根据类的反射得到真实对象的Method,调用装备的invoke方法,将动态代理、Method、方法参数传与装备的invoke方法,invoke方法在唤起method方法前或后做一些处理。

1、产生动态代理的类:

java.lang.refect.Proxy

2、装备必须实现InvocationHandler接口实现invoke方法

3、反射

通过类说明可以得到类的父类、实现的接口、内部类、构造函数、方法、属性并可以根据构造器实例化一个对象,唤起一个方法,取属性值,改属性值。

如何得到一个类说明?

Class cls=类.class;

Class cls=对象.getClass();

Class.forName(“类路径”);

如何得到一个方法并唤起它?

Class cls=类.class;

Constructor cons=cls.getConstructor(new Class[]{String.class});

Object obj=cons.newInstance(new Object[]{“aaa”});

Method method=cls.getMethod(“方法名”,new Class[]{String.class,Integer.class});

method.invoke(obj,new Object[]{“aa”,new Integer(1)});

4、spring的三种注入方式是什么?

setter

interface

constructor

十八、描述struts的工作流程
Struts是一个基于J2EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的。他是属于一个表示层的开发框架。
现在最常用的是Struts 1.x,也有Struts2.x(前身为webwork)。同类型做表示层的框架也有很多例如sun公司的JSF(java serverface)等等。
 

  Struts的底层用的技术大致有:1,JSP 2,servlet 3,自定义标记 4,XML java解析技术 5,OOAD6,反射。
                              Struts的工作流程(如图所示)

Struts工作流程

 

 

第一步:应用程序启动后,先将struts-config.xml 的文件加载到内存中。

 

第二步:当客户端浏览器提交一个请求时,他会根据提交的请求中的路径,在struts-config.xml的下的Action节点中,寻找和提交的*.do(*为某个特定名称)相匹配的Path属性。

第三步:和这个匹配的Path一组的有name这一属性。根据这个name属性的值在这一节点下寻找一个中name和他一样的节点。

第四步:根据同一节点下的type属性会找到一个类。这个类如上图在紫色块。他是一个JAVABEAN。他继承自ActionForm这个类。他里面提供的一组字段,找到这个类后他会利用java的反射机制自动创建一个类的对象,并将客户提交的数据进行封装。这里需要注意的是,里面提供的字段必须和form表单中的控件名称一致。

第五步:执行完以上步骤后,会接着寻找刚才在下的Action节点下的type属性,根据这一属性也会寻找到一个类,这个类就是上图中的第二行右边红色的块。这个类继承自Action类。在这一类中需要重写父类的Excute();方法。参数共4个。后面会有叙述。找到这个类后会自动调用重写过的这个方法。这个方法会返回值为ActionForward。

   参数共4个:ActionMapping,ActionForm,HttpServletRequest,HttpServletResponse。后面两个好理解,第二个是ActionForm。其实就是前面提到过的javabean,第一个是一个ActionMapping,他能得到刚才前面Action接点下的子接点。

第六步:通过Excute();方法处理完业务后回返回一个ActionForward对象,根据返回值会在和Action接点中的 中的name自动匹配 并根据该接点中Path属性进行跳转页面。这里的跳转默认是请求转发,如果需要重定向的话 需要配置Redirect属性为true。

到此这里就详细的描述了一个简单的struts工作流程。后面在配一示例的struts-config.xml 的图。

Struts工作流程


十九、Tomcat的session处理,如果让你实现一个tomcatserver,如何实现session机制
http://blog.csdn.net/zhongweijian/article/details/7798337
二十、关于Cache(Ehcache,Memcached)
二一、sql的优化相关问题
http://www.cnblogs.com/wxj1020/archive/2008/04/27/1173638.html

二二、oracle中 rownum与rowid的理解,一千条记录我查200到300的记录怎么查?
二四、 DB中索引原理,种类,使用索引的好处和问题是什么?
http://blog.csdn.net/sdl_ok/article/details/5492955

二五、JVM垃圾回收实现原理。垃圾回收的线程优先级。
二六、jvm 最大内存设置。设置的原理。结合垃圾回收讲讲。

http://blog.csdn.net/s_ongfei/article/details/5051014








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值