1、下面有关JVM内存,说法错误的是?
程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,是线程隔离的
虚拟机栈描述的是Java方法执行的内存模型,用于存储局部变量,操作数栈,动态链接,方法出口等信息,是线程隔离的
方法区用于存储JVM加载的类信息、常量、静态变量、以及编译器编译后的代码等数据,是线程隔离的
原则上讲,所有的对象都在堆区上分配内存,是线程之间共享的
正确答案: C 解析:
方法区在JVM中也是一个非常重要的区域,它与堆一样,是被 线程共享 的区域。 在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。
大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟机栈,也有翻译成JAVA 方法栈的),Native Method Stack ( 本地方法栈 ),其中Method Area 和 Heap 是线程共享的 ,VM Stack,Native Method Stack 和Program Counter Register 是非线程共享的。为什么分为 线程共享和非线程共享的呢?请继续往下看。
首先我们熟悉一下一个一般性的 Java 程序的工作过程。一个 Java 源程序文件,会被编译为字节码文件(以 class 为扩展名),每个java程序都需要运行在自己的JVM上,然后告知 JVM 程序的运行入口,再被 JVM 通过字节码解释器加载运行。那么程序开始运行后,都是如何涉及到各内存区域的呢?
概括地说来,JVM初始运行的时候都会分配好 Method Area(方法区) 和Heap(堆) ,而JVM 每遇到一个线程,就为其分配一个 Program Counter Register(程序计数器) , VM Stack(虚拟机栈)和Native Method Stack (本地方法栈), 当线程终止时,三者(虚拟机栈,本地方法栈和程序计数器)所占用的内存空间也会被释放掉。这也是为什么我把内存区域分为线程共享和非线程共享的原因,非线程共享的那三个区域的生命周期与所属线程相同,而线程共享的区域与JAVA程序运行的生命周期相同,所以这也是系统垃圾回收的场所只发生在线程共享的区域(实际上对大部分虚拟机来说知发生在Heap上)的原因。
方法区域存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,当开发人员在程序中通过Class对象中的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域,同时方法区域也是全局共享的,在一定的条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
二、下面有关jdbc statement的说法错误的是?
JDBC提供了Statement、PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程
对于PreparedStatement来说,数据库可以使用已经编译过及定义好的执行计划,由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象”
PreparedStatement中,“?” 叫做占位符,一个占位符可以有一个或者多个值
PreparedStatement可以阻止常见的SQL注入式攻击
正确答案:C 解析:
2.Statement继承自Wrapper、PreparedStatement继承自Statement、
CallableStatement继承自PreparedStatement。
3.
Statement接口提供了执行语句和获取结果的基本方法;
PreparedStatement接口添加了处理 IN 参数的方法;
CallableStatement接口添加了处理 OUT 参数的方法。
4.
a.Statement:
普通的不带参的查询SQL;支持批量更新,批量删除;
b.PreparedStatement:
可变参数的SQL,编译一次,执行多次,效率高;
安全性好,有效防止Sql注入等问题;
支持批量更新,批量删除;
c.CallableStatement:
继承自PreparedStatement,支持带参数的SQL操作;
支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持;
Statement每次执行sql语句,数据库都要执行sql语句的编译 ,
最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement。
PreparedStatement是预编译的,使用PreparedStatement有几个好处
1. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。
2. 安全性好,有效防止Sql注入等问题。
3. 对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;
4. 代码的可读性和可维护性。
3、下面有关SPRING的事务传播特性,说法错误的是?
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行
PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就抛出异常
PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起
PROPAGATION_NESTED:支持当前事务,新增Savepoint点,与当前事务同步提交或回滚
正确答案:B 解析:
事务属性的种类: 传播行为、隔离级别、只读和事务超时
a) 传播行为定义了被调用方法的事务边界。
传播行为 | 意义 |
PROPERGATION_MANDATORY | 表示方法必须运行在一个事务中,如果当前事务不存在,就抛出异常 |
PROPAGATION_NESTED | 表示如果当前事务存在,则方法应该运行在一个嵌套事务中。否则,它看起来和 PROPAGATION_REQUIRED 看起来没什么俩样 |
PROPAGATION_NEVER | 表示方法不能运行在一个事务中,否则抛出异常 |
PROPAGATION_NOT_SUPPORTED | 表示方法不能运行在一个事务中,如果当前存在一个事务,则该方法将被挂起 |
PROPAGATION_REQUIRED | 表示当前方法必须运行在一个事务中,如果当前存在一个事务,那么该方法运行在这个事务中,否则,将创建一个新的事务 |
PROPAGATION_REQUIRES_NEW | 表示当前方法必须运行在自己的事务中,如果当前存在一个事务,那么这个事务将在该方法运行期间被挂起 |
PROPAGATION_SUPPORTS | 表示当前方法不需要运行在一个是事务中,但如果有一个事务已经存在,该方法也可以运行在这个事务中 |
b) 隔离级别
在操作数据时可能带来 3 个副作用,分别是脏读、不可重复读、幻读。为了避免这 3 中副作用的发生,在标准的 SQL 语句中定义了 4 种隔离级别,分别是未提交读、已提交读、可重复读、可序列化。而在 spring 事务中提供了 5 种隔离级别来对应在 SQL 中定义的 4 种隔离级别,如下:
隔离级别 | 意义 |
ISOLATION_DEFAULT | 使用后端数据库默认的隔离级别 |
ISOLATION_READ_UNCOMMITTED | 允许读取未提交的数据(对应未提交读),可能导致脏读、不可重复读、幻读 |
ISOLATION_READ_COMMITTED | 允许在一个事务中读取另一个已经提交的事务中的数据(对应已提交读)。可以避免脏读,但是无法避免不可重复读和幻读 |
ISOLATION_REPEATABLE_READ | 一个事务不可能更新由另一个事务修改但尚未提交(回滚)的数据(对应可重复读)。可以避免脏读和不可重复读,但无法避免幻读 |
ISOLATION_SERIALIZABLE | 这种隔离级别是所有的事务都在一个执行队列中,依次顺序执行,而不是并行(对应可序列化)。可以避免脏读、不可重复读、幻读。但是这种隔离级别效率很低,因此,除非必须,否则不建议使用。 |
c) 只读
如果在一个事务中所有关于数据库的操作都是只读的,也就是说,这些操作只读取数据库中的数据,而并不更新数据,那么应将事务设为只读模式( READ_ONLY_MARKER ) , 这样更有利于数据库进行优化 。
因为只读的优化措施是事务启动后由数据库实施的,因此,只有将那些具有可能启动新事务的传播行为 (PROPAGATION_NESTED 、 PROPAGATION_REQUIRED 、 PROPAGATION_REQUIRED_NEW) 的方法的事务标记成只读才有意义。
如果使用 Hibernate 作为持久化机制,那么将事务标记为只读后,会将 Hibernate 的 flush 模式设置为 FULSH_NEVER, 以告诉 Hibernate 避免和数据库之间进行不必要的同步,并将所有更新延迟到事务结束。
d) 事务超时
如果一个事务长时间运行,这时为了尽量避免浪费系统资源,应为这个事务设置一个有效时间,使其等待数秒后自动回滚。与设置“只读”属性一样,事务有效属性也需要给那些具有可能启动新事物的传播行为的方法的事务标记成只读才有意义。
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
4、下面有关servlet和cgi的描述,说法错误的是?
servlet处于服务器进程中,它通过多线程方式运行其service方法CGI对每个请求都产生新的进程,服务完成后就销毁
servlet在易用性上强于cgi,它提供了大量的实用工具例程,例如自动地解析和解码HTML表单数据、读取和设置HTTP头、处理Cookie、跟踪会话状态等
cgi在移植性上高于servlet,几乎所有的主流服务器都直接或通过插件支持cgi
正确答案:D 解析:
选择D,servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。
和CGI程序一样,Servlet可以响应用户的指令(提交一个FORM等等),也可以象CGI程序一样,收集用户表单的信息并给予动态反馈(简单的注册信息录入和检查错误)。
然而,Servlet的机制并不仅仅是这样简单的与用户表单进行交互。传统技术中,动态的网页建立和显示都是通过CGI来实现的,但是,有了Servlet,您可以大胆的放弃所有CGI(perl?php?甚至asp!),利用Servlet代替CGI,进行程序编写。
对比一:当用户浏览器发出一个Http/CGI的请求,或者说 调用一个CGI程序的时候,服务器端就要新启用一个进程 (而且是每次都要调用),调用CGI程序越多(特别是访问量高的时候),就要消耗系统越多的处理时间,只剩下越来越少的系统资源,对于用户来说,只能是漫长的等待服务器端的返回页面了,这对于电子商务激烈发展的今天来说,不能不说是一种技术上的遗憾。
而Servlet充分发挥了服务器端的资源并高效的利用。每次调用Servlet时并不是新启用一个进程 ,而是在一个Web服务器的进程敏感词享和分离线程,而线程最大的好处在于可以共享一个数据源,使系统资源被有效利用。
对比二:传统的CGI程序,不具备平台无关性特征,系统环境发生变化,CGI程序就要瘫痪,而Servlet具备Java的平台无关性,在系统开发过程中保持了系统的可扩展性、高效性。
对比三:传统技术中,一般大都为二层的系统架构,即Web服务器+数据库服务器,导致网站访问量大的时候,无法克服CGI程序与数据库建立连接时速度慢的瓶颈,从而死机、数据库死锁现象频繁发生。而我们的Servlet有连接池的概念,它可以利用多线程的优点,在系统缓存中事先建立好若干与数据库的连接,到时候若想和数据库打交道可以随时跟系统"要"一个连接即可,反应速度可想而知。
选D:CGI不可移植,为某一特定平台编写的CGI应用只能运行于这一环境中。每一个CGI应用存在于一个由客户端请求激活的进程中,并且在请求被服务后被卸载。这种模式将引起很高的内存、CPU开销,而且在同一进程中不能服务多个客户。
5、下面有关servlet service描述错误的是?
不管是post还是get方法提交过来的连接,都会在service中处理doGet/doPost 则是在 javax.servlet.GenericServlet 中实现的
service()是在javax.servlet.Servlet接口中定义的
service判断请求类型,决定是调用doGet还是doPost方法
正确答案:B 解析:
doGet/doPost 则是在 javax.servlet.http.HttpServlet 中实现的
6、下列有关Servlet的生命周期,说法不正确的是?
在创建自己的Servlet时候,应该在初始化方法init()方法中创建Servlet实例在Servlet生命周期的服务阶段,执行service()方法,根据用户请求的方法,执行相应的doGet()或是doPost()方法
在销毁阶段,执行destroy()方法后会释放Servlet 占用的资源
destroy()方法仅执行一次,即在服务器停止且卸载Servlet时执行该方法
正确答案:A 解析:
创建Servlet的实例是由Servlet容器来完成的,且创建Servlet实例是在初始化方法init()之前
7、下面有关servlet中init,service,destroy方法描述错误的是?
init()方法是servlet生命的起点。一旦加载了某个servlet,服务器将立即调用它的init()方法
service()方法处理客户机发出的所有请求
destroy()方法标志servlet生命周期的结束
servlet在多线程下使用了同步机制,因此,在并发编程下servlet是线程安全的
正确答案:D 解析:
8、下面有关struts1和struts2的区别,描述错误的是?
Struts1要求Action类继承一个抽象基类。Struts 2 Action类可以实现一个Action接口Struts1 Action对象为每一个请求产生一个实例。Struts2 Action是单例模式并且必须是线程安全的
Struts1 Action 依赖于Servlet API,Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试
Struts1 整合了JSTL,Struts2可以使用JSTL,但是也支持OGNL
正确答案:B 解析:
1.Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类编程而不是接口。
2. Struts 2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去实现常用的接口。Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2的Action对象。
从Servlet 依赖分析:
3. Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
4. Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。
从action线程模式分析:
5. Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
6. Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)
Struts1和Struts2的区别和对比:
Action 类:• Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类编程而不是接口,而struts2的Action是接口。
• Struts 2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去 实现 常用的接口。Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2的Action对象。
线程模式:
• Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
• Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)
Servlet 依赖:
• Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
• Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。
可测性:
• 测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)。
• Struts 2 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。
捕获输入:
• Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经常创建多余的类捕获输入。动态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是在重新描述(创建)已经存 在的JavaBean(仍然会导致有冗余的javabean)。
• Struts 2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种 ModelDriven 特性简化了taglib对POJO输入对象的引用。
表达式语言:
• Struts1 整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。
• Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL).
servle是单例的 Struts2是多例的 记住这个就OK了
9、关于AWT和Swing说法正确的是?
Swing是AWT的子类
AWT在不同操作系统中显示相同的风格
AWT不支持事件类型,Swing支持事件模型
Swing在不同的操作系统中显示相同的风格
正确答案:D 解析:
AWT和Swing都是java中的包。
AWT(Abstract Window Toolkit):抽象窗口工具包,早期编写图形界面应用程序的包。
Swing :为解决 AWT 存在的问题而新开发的图形界面包。Swing是对AWT的改良和扩展。
AWT和Swing的实现原理不同:
AWT的图形函数与操作系统提供的图形函数有着一一对应的关系。也就是说,当我们利用 AWT构件图形用户界面的时候,实际上是在利用操作系统的图形库。
不同的操作系统其图形库的功能可能不一样,在一个平台上存在的功能在另外一个平台上则可能不存在。为了实现Java语言所宣称的"一次编译,到处运行"的概念,AWT不得不通过牺牲功能来实现平台无关性。因此,AWT 的图形功能是各操作系统图形功能的“交集”。
因为AWT是依靠本地方法来实现功能的,所以AWT控件称为“重量级控件”。
而Swing ,不仅提供了AWT 的所有功能,还用纯粹的Java代码对AWT的功能进行了大幅度的扩充。
例如:并不是所有的操作系统都提供了对树形控件的支持, Swing则利用了AWT中所提供的基本作图方法模拟了一个树形控件。
由于 Swing是用纯粹的Java代码来实现的,因此Swing控件在各平台通用。
因为Swing不使用本地方法,故Swing控件称为“轻量级控件”。
AWT和Swing之间的区别:
1)AWT 是基于本地方法的C/C++程序,其运行速度比较快;Swing是基于AWT的Java程序,其运行速度比较慢。
2)AWT的控件在不同的平台可能表现不同,而Swing在所有平台表现一致。
在实际应用中,应该使用AWT还是Swing取决于应用程序所部署的平台类型。例如:
1)对于一个嵌入式应用,目标平台的硬件资源往往非常有限,而应用程序的运行速度又是项目中至关重要的因素。在这种矛盾的情况下,简单而高效的AWT当然成了嵌入式Java的第一选择。
2)在普通的基于PC或者是工作站的标准Java应用中,硬件资源对应用程序所造成的限制往往不是项目中的关键因素。所以在标准版的Java中则提倡使用Swing, 也就是通过牺牲速度来实现应用程序的功能。
10、看以下代码: 文件名称:forward.jsp
<html>
<head><title> 跳转 </title> </head>
<body>
<jsp:forward page="index.htm"/>
</body>
</html>
如果运行以上jsp文件,地址栏的内容为
http://127.0.0.1:8080/myjsp/forward.jsphttp://127.0.0.1:8080/myjsp/index.jsp
http://127.0.0.1:8080/myjsp/index.htm
http://127.0.0.1:8080/myjsp/forward.htm
正确答案:A 解析:
11、下面哪一项不是加载驱动程序的方法?
通过DriverManager.getConnection方法加载调用方法 Class.forName
通过添加系统的jdbc.drivers属性
通过registerDriver方法注册
正确答案:A 解析:
DriverManager.getConnection方法返回一个Connection对象,这是加载驱动之后才能进行的
1.Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
- 加载驱动 DriverManager. registerDriver(Driver driver)
- 获取连接 Connection conn = DriverManager.getConnection(url,user,pass);
- 通过连接创建statement Statement st = conn.createStatement();
- 解析sql获取结果集 ResultSet rs = st.excuteQuery(sql);
- 遍历结果集,获得数据 rs.getobject(xx)
- 释放资源,关闭连接
D DriverManager.registerDriver(new com.microsoft.sqlserver.jdbc.SQLServerDriver());
jdbc是使用桥的模式进行连接的。DriverManager就是管理数据库驱动的一个类,java.sql.Driver就 是一个提供注册数据库驱动的接口,而com.microsoft.sqlserver.jdbc.SQLServerDriver()是 java.sql.Driver接口的一个具体实现。
12、关于sleep()和wait(),以下描述错误的一项是()
sleep是线程类(Thread)的方法,wait是Object类的方法;sleep不释放对象锁,wait放弃对象锁
sleep暂停线程、但监控状态仍然保持,结束后会自动恢复
wait后进入等待锁定池,只有针对此对象发出notify方法后获得对象锁进入运行状态
正确答案: D 解析:
共同点 :
1. 他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。
2. wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态 ,从而使线程立刻抛出InterruptedException。
如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep/join,则线程B会立刻抛出InterruptedException,在catch() {} 中直接return即可安全地结束线程。
需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用 interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到 wait()/sleep()/join()后,就会立刻抛出InterruptedException 。
不同点 :
1.每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互,来实现线程的同步。
sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
2.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
3.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
D错是因为进入的是就绪状态而不是运行状态
D选项,notity()和notifyAll()两个方法均可,应该进入就绪状态而不是运行状态。
13、根据下面的程序代码,哪些选项的值返回true?
public class Square {
long width;
public Square(long l) {
width = l;
}
public static void main(String arg[]) {
Square a, b, c;
a = new Square(42L);
b = new Square(42L);
c = b;
long s = 42L;
}
}
a == b
s == a
b == c
a.equals(s)
正确答案:C 解析:
这里new了两个对象,所以a,b不是同一个引用a!=b
这里b,c是同一个对象的引用,所以b==c是true
//声明了3个Square类型的变量a, b, c
//在stack中分配3个内存,名字为a, b, c
Square a, b, c;
//在heap中分配了一块新内存,里边包含自己的成员变量width值为48L,然后stack中的a指向这块内存
a = new Square(42L);
//在heap中分配了一块新内存,其中包含自己的成员变量width值为48L,然后stack中的b指向这块内存
b = new Square(42L);
//stack中的c也指向b所指向的内存
c = b;
//在stack中分配了一块内存,值为42
long s = 42L;
public boolean equals(Object obj) {
return (this == obj);
}
其实就是判断两个引用是否相等,故D也错误。
14、在jdk1.5的环境下,有如下4条语句:
Integer i01 = 59;
int i02 = 59;
Integer i03 =Integer.valueOf(59);
Integer i04 = new Integer(59);
以下输出结果为false的是:
System.out.println(i01== i02);
System.out.println(i01== i03);
System.out.println(i03== i04);
System.out.println(i02== i04);
正确答案:C 解析:
Integer i01=59 的时候,会调用 Integer 的 valueOf 方法,
public static Integer valueOf(int i) {
assert IntegerCache.high>= 127;
if (i >= IntegerCache.low&& i <= IntegerCache.high)
return IntegerCache.cache[i+ (-IntegerCache.low)];
return new Integer(i);
}
这个方法就是返回一个 Integer 对象,只是在返回之前,看作了一个判断,判断当前 i 的值是否在 [-128,127] 区别,且 IntegerCache 中是否存在此对象,如果存在,则直接返回引用,否则,创建一个新的对象。
在这里的话,因为程序初次运行,没有 59 ,所以,直接创建了一个新的对象。
int i02=59 ,这是一个基本类型,存储在栈中。
Integer i03 =Integer.valueOf(59); 因为 IntegerCache 中已经存在此对象,所以,直接返回引用。
Integer i04 = new Integer(59) ;直接创建一个新的对象。
System. out .println(i01== i02); i01 是 Integer 对象, i02 是 int ,这里比较的不是地址,而是值。 Integer 会自动拆箱成 int ,然后进行值的比较。所以,为真。
System. out .println(i01== i03); 因为 i03 返回的是 i01 的引用,所以,为真。
System. out .println(i03==i04); 因为 i04 是重新创建的对象,所以 i03,i04 是指向不同的对象,因此比较结果为假。
System. out .println(i02== i04); 因为 i02 是基本类型,所以此时 i04 会自动拆箱,进行值比较,所以,结果为真。
思路:i02为基本数据类型,有基本数据类型的都是比较值,所以A、D为TRUE。i01和i03在-128--127之间分配机制是一样的,所以i01==i03。i03和i04分配内存的机制是不一样的,所以为false。
15、下面哪个不对?
RuntimeException is the superclass of those exceptions that can be thrown during the normal operation of the Java Virtual Machine.
A method is not required to declare in its throws clause any subclasses of RuntimeExeption that might be thrown during the execution of the method but not caught
An RuntimeException is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch.
NullPointerException is one kind of RuntimeException
正确答案: C 解析:
IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
非运行时异常 (编译异常): 是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
16、关于以下程序代码的说明正确的是?
public class HasStatic{
private static int x=100;
public static void main(String args[]){
HasStatic hs1=new HasStatic();
hs1.x++;
HasStatic hs2=new HasStatic();
hs2.x++;
hs1=new HasStatic();
hs1.x++;
HasStatic.x--;
System.out.println("x="+x);
}
}
程序通过编译,输出结果为:x=103
10行不能通过编译,因为x是私有静态变量
5行不能通过编译,因为引用了私有静态变量
程序通过编译,输出结果为:x=102
正确答案: D 解析:
static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念。static变量在第一次使用的时候初始化,但只会有一份成员对象。
x=102
x=103
x=102
main是HasStatic的静态方法,在其内部可直接访问静态变量,不存在因为私有变量不能通过编译的问题;如果在其他类中,包括HasStatic的派生类中,均不能访问其私有静态变量
当static作用于某个字段时,肯定会改变数据创建的方式(因为一个static字段对每个类来说都只有一份储存空间,而非static字段则是对每个对象有一个储存空间);
所以无论是HasStatic类的对象hs1,hs2,或是直接通过类名修改static作用的字段,都是一个,因此选择D
17、关于struts项目中的类与MVC模式的对应关系,说法错误的是
Jsp文件实现视图View的功能ActionServlet这一个类是整个struts项目的控制器
ActionForm、Action都属于Model部分
一个struts项目只能有一个Servlet
正确答案:CD 解析:
Struts工作原理
MVC即Model-View-Controller的缩写,是一种常用的设计模式。MVC 减弱了业务逻辑接口和数据接口之间的耦合,以及让视图层更富于变化。 Struts 是MVC的一种实现,它将 Servlet和 JSP 标记(属于 J2EE 规范)用作实现的一部分。Struts继承了MVC的各项特性,并根据J2EE的特点,做了相应的变化与扩展。
控 制:有一个XML文件Struts-config.xml,与之相关联的是Controller,在Struts中,承担MVC中Controller角 色的是一个Servlet,叫ActionServlet。ActionServlet是一个通用的控制组件。这个控制组件提供了处理所有发送到 Struts的HTTP请求的入口点。它截取和分发这些请求到相应的动作类(这些动作类都是Action类的子类)。另外控制组件也负责用相应的请求参数 填充 Action From(通常称之为FromBean),并传给动作类(通常称之为ActionBean)。动作类实现核心商业逻辑,它可以访问java bean 或调用EJB。最后动作类把控制权传给后续的JSP 文件,后者生成视图。所有这些控制逻辑利用Struts-config.xml文件来配置。
视图:主要由JSP生成页面完成视图,Struts提供丰富的JSP 标签库: Html,Bean,Logic,Template等,这有利于分开表现逻辑和程序逻辑。
模 型:模型以一个或多个java bean的形式存在。这些bean分为三类:Action Form、Action、JavaBean or EJB。Action Form通常称之为FormBean,封装了来自于Client的用户请求信息,如表单信息。Action通常称之为ActionBean,获取从 ActionSevlet传来的FormBean,取出FormBean中的相关信息,并做出相关的处理,一般是调用Java Bean或EJB等。
流程:在Struts中,用户的请求一般以*.do作为请求服务名,所有的*.do请求均被指向 ActionSevlet,ActionSevlet根据Struts-config.xml中的配置信息,将用户请求封装成一个指定名称的 FormBean,并将此FormBean传至指定名称的ActionBean,由ActionBean完成相应的业务操作,如文件操作,数据库操作等。 每一个*.do均有对应的FormBean名称和ActionBean名称,这些在Struts-config.xml中配置。
核心:Struts的核心是ActionSevlet,ActionSevlet的核心是Struts-config.xml。
18、有关jsp中静态include和动态include的区别,说法错误的是?
动态INCLUDE:用jsp:include动作实现静态INCLUDE:用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面<%@ include file="included.htm" %>
静态include的结果是把其他jsp引入当前jsp,两者合为一体;动态include的结构是两者独立,直到输出时才合并
静态include和动态include都可以允许变量同名的冲突.页面设置也可以借用主文件的
正确答案: D 解析:
静态 INCLUDE 用 include 伪码实现 , 定不会检查所含文件的变化 , 适用于包含静态页面 <%@ include file="included.htm" %> 。先将文件的代码被原封不动地加入到了主页面从而合成一个文件,然后再进行翻译,此时不允许有相同的变量。
以下是对 include 两种用法的区别 , 主要有两个方面的不同 ;
一 : 执行时间上 :
<%@ include file="relativeURI"%> 是在翻译阶段执行
<jsp:include page="relativeURI" flush="true" /> 在请求处理阶段执行 .
二 : 引入内容的不同 :
<%@ include file="relativeURI"%>
引入静态文本 (html,jsp), 在 JSP 页面被转化成 servlet 之前和它融和到一起 .
<jsp:include page="relativeURI" flush="true" /> 引入执行页面或 servlet 所生成的应答文本 .
静态的include不允许变量同名
19、对于JVM内存配置参数:
-Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3
其最小内存值和Survivor区总大小分别是()
5120m,1024m5120m,2048m
10240m,1024m
10240m,2048m
正确答案: D 解析:
20、给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?输出需要删除的字符个数。
提到回文串,自然要利用回文串的特点,想到将源字符串逆转后,“回文串”(不一定连续)相当于顺序没变求原字符串和其反串的最大公共子序列(不是子串,因为可以不连续)的长度(使用动态规划很容易求得),然后用原字符串的长度减去这个最大公共子串的长度就得到了最小编辑长度。
输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出一个整数,代表最少需要删除的字符个数。
输入例子1:
abcda
google
输出例子1:
2
2
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String s1 = sc.next();
String s2 = new StringBuilder(s1).reverse().toString();
int[][] dp = new int[s1.length() + 1][s2.length() + 1];
for (int i = 1; i < dp.length; i++) {
for (int j = 1; j < dp[0].length; j++) {
dp[i][j] = s1.charAt(i - 1) == s2.charAt(j - 1) ? dp[i - 1][j - 1] + 1
: Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
System.out.println(s1.length() - dp[s1.length()][s2.length()]);
}
}
21、把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。
输入描述:
输入包含多组测试数据。
对于每组测试数据:
N - 本组测试数据有n个数
a1,a2...an - 需要计算的数据
保证:
1<=N<=100000,0<=ai<=INT_MAX.
输出描述:
对于每组数据,输出两个数,第一个数表示差最小的对数,第二个数表示差最大的对数。
输入例子1:
6
45 12 45 32 5 6
输出例子1:
1 2
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str = sc.nextLine();
for (int i = 0; i < str.length(); i++) {
if (Character.isLowerCase(str.charAt(i))) {
System.out.print(str.charAt(i));
}
}
for (int i = 0; i < str.length(); i++) {
if (!Character.isLowerCase(str.charAt(i))) {
System.out.print(str.charAt(i));
}
}
System.out.println();
}
}
22、有n个数,两两组成二元组,差最小的有多少对呢?差最大呢?
1.先排序
特殊情况:如果排完序之后发现数组中所有数都相同,直接输出结果
结果为:差最大个数 = 差最小个数 = (n * (n-1))/2;(两两组合)
2.统计数组中每种数字的个数(这里用的map)
3.计算差最小个数
3.1.如果数组中没有重复数字,说明最小差不为0,最小差肯定是数组中相邻两个数的差
因此,遍历一边数组,计算并统计最小差。
3.2.如果数组中有重复数字,说明最小差是0,此时,遍历一边map,数字个数不为0的
数字会产生最小差0,利用公式计算即可
4.计算差最大个数
只有一种情况,最大值与最小值的两两组合,即最大值个数 * 最小值个数
算法复杂度:排序O(nlogn), 统计O(n)
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
Arrays.sort(a);
// 如果数组中的值全相同,直接两两组合
if (a[0] == a[n - 1]) {
int tmp = (n * (n - 1)) / 2;
System.out.println(tmp + " " + tmp);
continue;
}
// map用来统计
Map<Integer, Integer> map = new TreeMap<Integer, Integer>();
for (int i = 0; i < n; i++) {
if (map.containsKey(a[i]))
map.put(a[i], map.get(a[i]) + 1);
else
map.put(a[i], 1);
}
// 求差最小个数
int minres = 0;
if (map.size() == n) {
int min = Math.abs(a[1] - a[0]);
for (int i = 2; i < n; i++) {
int tmp = Math.abs(a[i] - a[i - 1]);
if (tmp == min)
minres++;
else if (tmp < min) {
min = tmp;
minres = 1;
}
}
} else {
for (Integer key : map.keySet()) {
int val = map.get(key);
if (val > 1) {
minres += (val * (val - 1)) / 2;
}
}
}
// 求差最大个数
int maxres = 0;
List<Integer> keyset = new ArrayList<Integer>(map.keySet());
int val1 = map.get(keyset.get(0));
int val2 = map.get(keyset.get(keyset.size() - 1));
maxres = val1 * val2;
System.out.println(minres + " " + maxres);
}
}
23、老师想知道从某某同学当中,分数最高的是多少,现在请你编程模拟老师的询问。当然,老师有时候需要更新某位同学的成绩.
输入描述:
输入包括多组测试数据。
每组输入第一行是两个正整数N和M(0 < N <= 30000,0 < M < 5000),分别代表学生的数目和操作的数目。
学生ID编号从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩
接下来又M行,每一行有一个字符C(只取‘Q’或‘U’),和两个正整数A,B,当C为'Q'的时候, 表示这是一条询问操作,他询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少
当C为‘U’的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。
输出描述:
对于每一次询问操作,在一行里面输出最高成绩.
输入例子1:
5 7
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 4 5
U 2 9
Q 1 5
输出例子1:
5
6
5
9
public static void main(String[] args) {
int M = 0, N = 0;
int i;
int A = 0, B = 0;
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
N = in.nextInt();
M = in.nextInt();
// System.out.println (N + " " + M);
int[] score = new int[N];
for (i = 0; in.hasNext() && i < N; i++) {
score[i] = in.nextInt();
// System.out.println (score[i] + " ");
}
String c = null;
for (i = 0; in.hasNext() && i < M; i++) {
c = in.next();
A = in.nextInt();
B = in.nextInt();
process(c, A, B, score);
}
}
}
private static void process(String c, int a, int b, int[] score) {
int begin, end;
if (c.equals("Q")) {
end = Math.max(a, b);
begin = Math.min(a, b) - 1;
int max = score[begin];
for (int i = begin; i < end; i++) {
if (max < score[i]) {
max = score[i];
}
}
System.out.println(max);
} else if (c.equals("U")) {
score[a - 1] = b;
}
}
24、开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。
处理:1.记录最多8条错误记录,对相同的错误记录(即文件名称和行号完全匹配)只记录一条,错误计数增加;(文件所在的目录不同,文件名和行号相同也要合并)
2.超过16个字符的文件名称,只记录文件的最后有效16个字符;(如果文件名不同,而只是文件名的后16个字符和行号相同,也不要合并)
3.输入的文件可能带路径,记录文件名称不能带路径
输入描述:
一行或多行字符串。每行包括带路径文件名称,行号,以空格隔开。
文件路径为windows格式
如:E:\V1R2\product\fpgadrive.c 1325
输出描述:
将所有的记录统计并将结果输出,格式:文件名代码行数数目,一个空格隔开,如: fpgadrive.c 1325 1
结果根据数目从多到少排序,数目相同的情况下,按照输入第一次出现顺序排序。
如果超过8条记录,则只输出前8条记录.
如果文件名的长度超过16个字符,则只输出后16个字符
输入例子1:
E:\V1R2\product\fpgadrive.c 1325
输出例子1:
fpgadrive.c 1325 1
public class Huawei2 {
public static void main(String[] args) {
// 创建接受键盘录入对象
Scanner cin = new Scanner(System.in);
// 接受文件名称或者文件路径
String file = null;
// 获取文件路径 最后一个“\” 下标索引
int lastIndex = 0;
// 获取文件名称
// 接受错误出现的行号
int errorLine = 0;
// 创建一个HashMap<ErrLog>
HashMap<String, ErrLog> hashMap = new HashMap<String, ErrLog>();
ErrLog errLog = null;
String key = null;
StringBuilder sbBuilder = new StringBuilder();
while (cin.hasNext()) {
// 第一个参数为文件名称或文件路径
file = cin.next();
// 获取错误行号
errorLine = cin.nextInt();
// 获取最后一个'\'的索引
lastIndex = file.lastIndexOf('\\');
// 如果没有找到说明不是路径,直接返回文件名
// 是路径 就截取\后面的字符串作为文件名
sbBuilder.append(lastIndex < 0 ? file : file.substring(lastIndex + 1)).append(" ").append(errorLine);
key = sbBuilder.toString();
sbBuilder.setLength(0);
// 将错误记录添加进hashMap 中
errLog = hashMap.get(key);
if (errLog == null) {
// 如果不存在,new 一个并添加进去
hashMap.put(key, new ErrLog(key, 1));
} else
errLog.size++; // 存在,就将错误次数累加
}
cin.close();
// ----------以上就是统计错误信息,下面是取值------------------
ArrayList<ErrLog> list = new ArrayList<ErrLog>(hashMap.values());
// 根据 错误次数比较,将错误次数多的放前面,如果错误次数一致,将出现顺序早的放到前面 进行排序
Comparator<ErrLog> cmp = new Comparator<ErrLog>() {
@Override
public int compare(ErrLog o1, ErrLog o2) {
return o2.size - o1.size == 0 ? (o1.queueMark - o2.queueMark) : o2.size - o1.size;
}
};
Collections.sort(list, cmp);
// 取出前8个,并输出
int lens = 8 > list.size() ? list.size() : 8;
for (int i = 0; i < lens; i++) {
// 这里文件名如果大于16位 还需要截取文件名16位 + 行号 输出
errLog = list.get(i);
// 这样就获取到了分界符' '的索引了,然后往前推16位就是我们要输出的文件名了
lastIndex = errLog.name.lastIndexOf(" ");
lastIndex = lastIndex - 16 < 0 ? 0 : lastIndex - 16;
// 获取文件名并输出
System.out.println((lastIndex == 0 ? errLog.name : errLog.name.substring(lastIndex)) + " " + errLog.size);
}
}
}
class ErrLog {
// 此类并不标准,仅方便此题目实现而已
static int mark; // 辅助实现字段queueMark按出现顺序自增
String name;// fileName 存储错误的文件名称,由完整的文件名,与错误行号组成。
int queueMark; // 标记出现的顺序
int size; // 统计出现错误的次数
public ErrLog(String name, int size) {
super();
this.name = name;
this.queueMark = mark++;
this.size = size;
}
}
25、扑克牌游戏大家应该都比较熟悉了,一副牌由54张组成,含3~A,2各4张,小王1张,大王1张。牌面从小到大用如下字符和字符串表示(其中,小写joker表示小王,大写JOKER表示大王):)
3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER
输入两手牌,两手牌之间用“-”连接,每手牌的每张牌以空格分隔,“-”两边没有空格,如:4 4 4 4-joker JOKER
请比较两手牌大小,输出较大的牌,如果不存在比较关系则输出ERROR
基本规则:
(1)输入每手牌可能是个子,对子,顺子(连续5张),三个,炸弹(四个)和对王中的一种,不存在其他情况,由输入保证两手牌都是合法的,顺子已经从小到大排列;
(2)除了炸弹和对王可以和所有牌比较之外,其他类型的牌只能跟相同类型的存在比较关系(如,对子跟对子比较,三个跟三个比较),不考虑拆牌情况(如:将对子拆分成个子)
(3)大小规则跟大家平时了解的常见规则相同,个子,对子,三个比较牌面大小;顺子比较最小牌大小;炸弹大于前面所有的牌,炸弹之间比较牌面大小;对王是最大的牌;
(4)输入的两手牌不会出现相等的情况。
答案提示:
(1)除了炸弹和对王之外,其他必须同类型比较。
(2)输入已经保证合法性,不用检查输入是否是合法的牌。
(3)输入的顺子已经经过从小到大排序,因此不用再排序了.
输入两手牌,两手牌之间用“-”连接,每手牌的每张牌以空格分隔,“-”两边没有空格,如4 4 4 4-joker JOKER。
输出两手牌中较大的那手,不含连接符,扑克牌顺序不变,仍以空格隔开;如果不存在比较关系则输出ERROR。输入例子
4 4 4 4-joker JOKER
joker JOKER
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] left, right;
String[] line;
String nextLine, outString;
while (sc.hasNext()) {
nextLine = sc.nextLine();
// 有王炸就王炸最大
if (nextLine.contains("joker JOKER")) {
outString = "joker JOKER";
} else {
// 拆分 先拆成左右 再拆成单排
line = nextLine.split("-");
left = line[0].split(" ");
right = line[1].split(" ");
// 炸弹最大
if (left.length == 4 && right.length != 4) {
outString = line[0];
} else if (right.length == 4 && left.length != 4) {
outString = line[1];
}
// 牌数相同的情况下比较最小的牌的大小,compare方法返回牌所对应的值
else if (right.length == left.length) {
if (count(left[0]) > count(right[0])) {
outString = line[0];
} else {
outString = line[1];
}
} else {
outString = "ERROR";
}
}
System.out.println(outString);
}
}
// 2-JOKER 按大小返回2-16
private static int count(String str) {
return "345678910JQKA2jokerJOKER".indexOf(str);
}
26、构造方法不需要同步化,定义在接口中的方法默认是public的。
构造方法每次都是构造出新的对象,不存在多个线程同时读写同一对象中的属性的问题,所以不需要同步 。
如果父类中的某个方法使用了 synchronized关键字,而子类中也覆盖了这个方法,默认情况下子类中的这个方法并不是同步的,必须显示的在子类的这个方法中加上 synchronized关键字才可。当然,也可以在子类中调用父类中相应的方法,这样虽然子类中的方法并不是同步的,但子类调用了父类中的同步方法,也就相当子类方法也同步了。接口里面的变量为常量,其实际是 public static final ;接口里面的方法为抽象方法,其实际是public abstract。
如果父类中的某个方法使用了synchronized关键字,而子类中也覆盖了这个方法,默认情况下子类中的这个方法并不是同步的,必须显示的在子类的这个方法中加上synchronized关键字才可。当然,也可以在子类中调用父类中相应的方法,这样虽然子类中的方法并不是同步的,但子类调用了父类中的同步方法,也就相当子类方法也同步了。
27、在Java中,以下关于方法重载和方法重写描述正确的是?
方法重载和方法的重写实现的功能相同
方法重载出现在父子关系中,方法重写是在同一类中
方法重载的返回值类型必须一致,参数项必须不同
方法重写的返回值类型必须相同或相容。(或是其子类)
正确答案: D 解析:
28、下面有关spring的依赖注入,说法错误的是?
依赖注入通常有如下两种:设置注入和构造注入:
构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入
当设值注入与构造注入同时存在时,先执行设值注入,再执行构造注入
设值注入是指IoC容器使用属性的setter方法来注入被依赖的实例。这种注入方式比较简单、直观
正确答案:C 解析:
在没有设值注入的情况下才会根据配置文件中的构造注入,一旦有设值注入,则构造注入失效
注入方式:
接口注入
属性注入[属性的SET/GET]
构造注入[构造方法注入]
使用构造函数依赖注入时,Spring保证所有一个对象所有依赖的对象先实例化后,才实例化这个对象。使用set方法依赖注入时,Spring首先实例化对象,然后才实例化所有依赖的对象。
当设值注入与构造注入同时存在时,先执行设置注入,在执行构造注入。
依赖注入通常有如下两种:设置注入和构造注入:构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入设值注入是指IoC容器使用属性的setter方法来注入被依赖的实例。这种注入方式比较简单、直观。
29、下面不属于HttpServletRequest接口完成功能的是?
读取cookie
读取HTTP头
设定响应的content类型
读取路径信息
正确答案:C 解析:
HttpServletRequest类主要处理:
1.读取和写入HTTP头标
2.取得和设置cookies
3.取得路径信息
4.标识HTTP会话
30、从以下哪一个选项中可以获得Servlet的初始化参数?
ServletServletContext
ServletConfig
GenericServlet
正确答案: C 解析:
通过ServletConfig接口的getInitParameter(java.lang.String name)方法
31、下列关于java抽象类的说法哪个正确?
某个抽象类的父类是抽象类,则这个子类必须重载父类的所有抽象方法接口和抽象类是同一回事
可以用抽象类直接去实例化创建对象
一个类只能继承一个抽象类
正确答案: D 解析:
32、下面关于spring mvc 和struts2的描述,错误的是?
spring mvc的入口是filter,而struts2是servletspring mvc是基于方法的设计,而struts2是基于类的设计
struts2有以自己的interceptor机制,spring mvc用的是独立的AOP方式
spring mvc的方法之间基本上独立的,独享request response数据,struts2所有Action变量是共享的
正确答案: A 解析:
@RequestMapping (value= "/whitelists" )
public String index(ModelMap map) {
Account account = accountManager.getByDigitId(SecurityContextHolder.get().getDigitId());
List<Group> groupList = groupManager.findAllGroup(account.getId());
map.put("account" , account);
map.put("groupList" , groupList);
return "/group/group-index" ;
}
// @ResponseBody ajax响应,处理Ajax请求也很方便
@RequestMapping (value= "/whitelist/{whiteListId}/del" )
@ResponseBody
public String delete( @PathVariable Integer whiteListId) {
whiteListManager.deleteWhiteList(whiteListId);
return "success" ;
}
spring mvc 和struts2的区别: 1.spring mvc是基于方法的设计,而struts2是基于类的设计。 2.struts2有以自己的interceptor机制,spring mvc用的是独立的AOP方式。 3.spring mvc的方法之间基本上独立的,独享request response数据,struts2所有Action变量是共享的。 4.机制:spring mvc的入口是servlet,而struts2是filter。 5.性能:spring会稍微比struts快。 spring mvc是基于方法的设计 , 而sturts是基于类 , 每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法,粒度更细
- 参数传递:struts是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。
- 设计思想上: struts更加符合oop的编程思想 , spring就比较谨慎,在servlet上扩展。 8.intercepter(拦截器)的实现机制:struts有以自己的interceptor机制, spring mvc用的是独立的AOP方式 。
33、关于JAVA的垃圾回收机制,下面哪些结论是正确?
程序可以任意指定释放内存的时间JAVA程序不能依赖于垃圾回收的时间或者顺序
程序可明确地标识某个局部变量的引用不再被使用
程序可以显式地立即释放对象占有的内存
正确答案:B 解析:
java提供了一个系统级的线程,即垃圾回收器线程。用来对每一个分配出去的内存空间进行跟踪。当JVM空闲时,自动回收每块可能被回收的内存,GC是完全自动的,不能被强制执行。程序员最多只能用System.gc()来建议执行垃圾回收器回收内存,但是具体的回收时间,是不可知的。34、一般用()创建InputStream对象,表示从标准输入中获取数据,用()创建OutputStream对象,表示输出到标准输出设备中。
System.in System.outSystem.out System.in
System.io.in System.io.out
System.io.out System.io.in
正确答案:A 解析:
System.in 和 System.out 是java中的标准输入输出流,一般情况下代表从控制台输入和输出到控制台
标准输入指键盘输入;标准输出指输出到屏幕上。
35、下面有个hibernate延迟加载,说法错误的是?
Hibernate2延迟加载实现:a)实体对象 b)集合(Collection)Hibernate3 提供了属性的延迟加载功能
get支持延迟加载,load不支持延迟加
hibernate使用Java反射机制,而不是字节码增强程序来实现透明性
正确答案:C 解析:
load方法来得到一个对象时,此时hibernate会使用延迟加载的机制来加载这个对象,即:当 我们使用session.load()方法来加载一个对象时,此时并不会发出sql语句,当前得到的这个对象其实是一个代理对象,这个代理对象只保存了实 体对象的id值,只有当我们要使用这个对象,得到其它属性时,这个时候才会发出sql语句,从数据库中去查询我们的对象。相对于load的延迟加载方式,get就直接的多,当我们使用session.get()方法来得到一个对象时,不管我们使不使用这个对象,此时都会发出sql语句去从数据库中查询出来。
36、下面哪一项不属于优化Hibernate所鼓励的?
使用单向一对多关联,不使用双向一对多不用一对一,用多对一取代
配置对象缓存,不使用集合缓存
继承类使用显式多态
正确答案:A 解析:
优化Hibernate所鼓励的7大措施:
1.尽量使用many-to-one,避免使用单项one-to-many
2.灵活使用单向one-to-many
3.不用一对一,使用多对一代替一对一
4.配置对象缓存,不使用集合缓存
5.一对多使用Bag 多对一使用Set
6.继承使用显示多态 HQL:from object polymorphism="exlicit" 避免查处所有对象
7.消除大表,使用二级缓存
37、关于struts框架,下面那些说法是正确的?
Struts中无法完成上传功能Struts框架基于MVC模式
Struts框架容易引起流程复杂、结构不清晰等问题
Struts可以有效地降低项目的类文件数目
正确答案:B 解析:
工作机制:Struts的工作流程 :
在 web应用启动时就会加载初始化 ActionServlet,ActionServlet从
struts-config.xml文件中读取配置信息 ,把它们存放到各种配置对象
当 ActionServlet接收到一个客户请求时 ,将执行如下流程 .
-(1)检索和用户请求匹配的 ActionMapping实例 ,如果不存在 ,就返回请求路径无效信息 ;
-(2)如果 ActionForm实例不存在 ,就创建一个 ActionForm对象 ,把客户提交的表单数据保存到 ActionForm对象中 ;
-(3)根据配置信息决定是否需要表单验证 .如果需要验证 ,就调用 ActionForm的 validate()方法 ;
-(4)如果 ActionForm的 validate()方法返回或返回一个不包含 ActionMessage的 ActuibErrors对象 , 就表示表单验证成功 ;
-(5)ActionServlet根据 ActionMapping所包含的映射信息决定将请求转发给哪个 Action,如果相应的 Action实例不存在 ,就先创建这个实例 ,然后调用 Action的 execute()方法 ;
-(6)Action的 execute()方法返回一个 ActionForward对象 ,ActionServlet在把客户请求转发给 ActionForward对象指向的 JSP组件 ;
-(7)ActionForward对象指向 JSP组件生成动态网页 ,返回给客户 ;
为什么要用:
JSP、 Servlet、 JavaBean技术的出现给我们构建强大的企业应用系统提供了可能。但用这些技术构建的系统非常的繁乱,所以在此之上,我们需要一个规则、一个把这些技术组织起来的规则,这就是框架, Struts便应运而生。
基于Struts开发的应用由3类组件构成:控制器组件、模型组件、视图组件
38、在Struts框架中如果要使用Validation作验证的话,需要使用以下哪个Form?
ActionFormValidatorActionForm
ValidatorForm
DynaValidatorActionForm
正确答案:D 解析:
DynaValidatorActionForm 动态验证表单
39、关于Spring MVC的核心控制器DispatcherServlet的作用,以下说法错误的是( )?
它负责处理HTTP请求
加载配置文件
实现业务操作
初始化上下应用对象ApplicationContext
正确答案:C 解析:
DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。
DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责如下:
1、文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;
2、通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);
3、 通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器);
4、通过ViewResolver解析逻辑视图名到具体视图实现;
5、本地化解析;
6、渲染具体的视图等;
7、如果执行过程中遇到异常将交给HandlerExceptionResolver来解析。
40、属于JSP内置对象的是?
1.request对象客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。
2.response对象
response对象包含了响应客户请求的有关信息,但在JSP中很少直接用到它。它是HttpServletResponse类的实例。
3.session对象
session对象指的是客户端与服务器的一次会话,从客户连到服务器的一个WebApplication开始,直到客户端与服务器断开连接为止。它是HttpSession类的实例.
4.out对象
out对象是JspWriter类的实例,是向客户端输出内容常用的对象
5.page对象
page对象就是指向当前JSP页面本身,有点象类中的this指针,它是java.lang.Object类的实例
6.application对象
application对象实现了用户间数据的共享,可存放全局变量。它开始于服务器的启动,直到服务器的关闭,在此期间,此对象将一直存在;这样在用户的前后连接或不同用户之间的连接中,可以对此对象的同一属性进行操作;在任何地方对此对象属性的操作,都将影响到其他用户对此的访问。服务器的启动和关闭决定了application对象的生命。它是ServletContext类的实例。
7.exception对象
exception对象是一个例外对象,当一个页面在运行过程中发生了例外,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。他实际上是java.lang.Throwable的对象
8.pageContext对象
pageContext对象提供了对JSP页面内所有的对象及名字空间的访问,也就是说他可以访问到本页所在的SESSION,也可以取本页面所在的application的某一属性值,他相当于页面中所有功能的集大成者,它的本 类名也叫pageContext。
9.config对象
config对象是在一个Servlet初始化时,JSP引擎向它传递信息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象)
pageContext javax.servlet.jsp.PageContext
request javax.servlet.http.HttpServletRequestresponse javax.servlet.http.HttpServletResponse
session javax.servlet.http.HttpSession
application javax.servlet.ServletContext
config javax.serlvet.ServletConfig
exception java.lang.Throwable
page java.lang.Object
out javax.servlet.jsp.JspWriter
作用:
1、pageContext 表示页容器 EL表达式、 标签 、上传
2、request 服务器端取得客户端的信息:头信息 、Cookie 、请求参数 ,最大用处在MVC设计模式上
3、response 服务器端回应客户端信息:Cookie、重定向
4、session 表示每一个用户,用于登录验证上
5、application 表示整个服务器
6、config 取得初始化参数,初始化参数在web.xml文件中配置
7、exception 表示的是错误页的处理操作
8、page 如同this一样,代表整个jsp页面自身
9、out 输出 ,但是尽量使用表达式输出
41、在 myjsp.jsp 中,关于下面的代码说法错误的是: ( )
<%@ page language="java" import="java.util.*" errorPage="error.jsp" isErrorPage="false" %>
该页面发生异常会转向 error.jsp
存在 errorPage 属性时,isErrorPage 是默认为 false
error.jsp 页面一定要有isErrorPage 属性且值为 true
正确答案:A 解析:
exception是JSP九大内置对象之一,其实例代表其他页面的异常和错误。只有当页面是错误处理页面时,即isErroePage为true时,该对象才可以使用。对于C项,errorPage的实质就是JSP的异常处理机制,发生异常时才会跳转到errorPage指定的页面,没必要给errorPage再设置一个errorPage。所以当errorPage属性存在时, isErrorPage属性值为false
当isErrorPage ="false"时,用errorPage="error.jsp"(isErrorPage默认是false)
当isErrorPage ="true"时,页面会直接使用exception