牛客网 Java 工程师能力评估 20 题 - 详解

时间:2023-03-08 15:41:29
牛客网 Java 工程师能力评估 20 题 - 详解

牛客网 Java 工程师能力评估 20 题 - 详解

不知在看博客的你是否知道 牛客网,不知道就太落后了,分享给你 :

此 20 题,绝对不只是 20 题!

免责声明:本博客为学习笔记,如有侵权请联系删除

牛客网 Java 工程师能力评估 20 题(仅题目模式)

(1)下面有关 JVM 内存,说法错误的是?

  • 程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,是线程隔离的
  • 虚拟机栈描述的是 Java 方法执行的内存模型,用于存储局部变量,操作数栈,动态链接,方法出口等信息,是线程隔离的
  • 方法区用于存储 JVM 加载的类信息、常量、静态变量、以及编译器编译后的代码等数据,是线程隔离的
  • 原则上讲,所有的对象都在堆区上分配内存,是线程之间共享的

(2)下面有关 jdbc statement 的说法错误的是?

  • JDBC提供了 Statement、PreparedStatement 和 CallableStatement 三种方式来执行查询语句,其中 Statement 用于通用查询,PreparedStatement 用于执行参数化查询,而 CallableStatement 则是用于存储过程
  • 对于 PreparedStatement 来说,数据库可以使用已经编译过及定义好的执行计划,由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象”
  • PreparedStatement 中,“?” 叫做占位符,一个占位符可以有一个或者多个值
  • PreparedStatement 可以阻止常见的 SQL 注入式攻击

(3)下面有关 SPRING 的事务传播特性,说法错误的是?

  • PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行
  • PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就抛出异常
  • PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起
  • PROPAGATION_NESTED:支持当前事务,新增 Savepoint 点,与当前事务同步提交或回滚

(4)下面有关 servlet 和 cgi 的描述,说法错误的是?

  • servlet 处于服务器进程中,它通过多线程方式运行其 service 方法
  • CGI 对每个请求都产生新的进程,服务完成后就销毁
  • servlet 在易用性上强于 cgi,它提供了大量的实用工具例程,例如自动地解析和解码 HTML 表单数据、读取和设置 HTTP 头、处理 Cookie、跟踪会话状态等
  • cgi 在移植性上高于 servlet,几乎所有的主流服务器都直接或通过插件支持 cgi

(5)下面有关 servlet service 描述错误的是?

  • 不管是 post 还是 get 方法提交过来的连接,都会在 service 中处理
  • doGet/doPost 则是在 javax.servlet.GenericServlet 中实现的
  • service() 是在 javax.servlet.Servlet 接口中定义的
  • service 判断请求类型,决定是调用 doGet 还是 doPost 方法

(6)下列有关 Servlet 的生命周期,说法不正确的是?

  • 在创建自己的 Servlet 时候,应该在初始化方法 init() 方法中创建 Servlet 实例
  • 在 Servlet 生命周期的服务阶段,执行 service() 方法,根据用户请求的方法,执行相应的 doGet() 或是 doPost() 方法
  • 在销毁阶段,执行 destroy() 方法后会释放 Servlet 占用的资源
  • destroy() 方法仅执行一次,即在服务器停止且卸载 Servlet 时执行该方法

(7)下面有关servlet中init,service,destroy方法描述错误的是?

  • init()方法是servlet生命的起点。一旦加载了某个servlet,服务器将立即调用它的init()方法
  • service()方法处理客户机发出的所有请求
  • destroy()方法标志servlet生命周期的结束
  • servlet在多线程下使用了同步机制,因此,在并发编程下servlet是线程安全的

(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

(9)关于 AWT 和 Swing 说法正确的是?

  • Swing 是 AWT 的子类
  • AWT 在不同操作系统中显示相同的风格
  • AWT 不支持事件类型,Swing 支持事件模型
  • 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.jsp
  • http:// 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

(11)下面哪一项不是加载驱动程序的方法?

  • 通过DriverManager.getConnection方法加载
  • 调用方法 Class.forName
  • 通过添加系统的jdbc.drivers属性
  • 通过registerDriver方法注册

(12)关于 sleep() 和 wait(),以下描述错误的一项是( )

  • sleep是线程类(Thread)的方法,wait是Object类的方法;
  • sleep不释放对象锁,wait放弃对象锁
  • sleep暂停线程、但监控状态仍然保持,结束后会自动恢复
  • wait后进入等待锁定池,只有针对此对象发出notify方法后获得对象锁进入运行状态

(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)

(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);

(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

(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

(17)关于 struts 项目中的类与 MVC 模式的对应关系,说法错误的是:

  • Jsp 文件实现视图 View 的功能
  • ActionServlet 这一个类是整个 struts 项目的控制器
  • ActionForm、Action 都属于 Model 部分
  • 一个 struts 项目只能有一个 Servlet

(18)下面有关 jsp 中静态 include 和动态 include 的区别,说法错误的是?

  • 动态 INCLUDE:用 jsp:include 动作实现
  • 静态 INCLUDE:用 include 伪码实现,定不会检查所含文件的变化,适用于包含静态页面 <%@ include file="included.htm" %>
  • 静态 include 的结果是把其他 jsp 引入当前 jsp,两者合为一体;动态 include 的结构是两者独立,直到输出时才合并
  • 静态 include 和动态 include 都可以允许变量同名的冲突.页面设置也可以借用主文件的

(19)给定以下 JAVA 代码,这段代码运行后输出的结果是()

public class Test
{
public static int aMethod(int i)throws Exception
{
try{
return i / 10;
}
catch (Exception ex)
{
throw new Exception("exception in a Method");
} finally{
System.out.printf("finally");
}
} public static void main(String [] args)
{
try
{
aMethod(0);
}
catch (Exception ex)
{
System.out.printf("exception in main");
}
System.out.printf("finished");
}
}
  • exception in main finished
  • finally finished
  • exception in main finally
  • finally exception in main finished

(20)对于 JVM 内存配置参数:

-Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3

,其最小内存值和 Survivor 区总大小分别是()

  • 5120m,1024m
  • 5120m,2048m
  • 10240m,1024m
  • 10240m,2048m

原文地址:查看原文

牛客网 Java 工程师能力评估 20 题(题目 & 详细解析)

选项从上到下为,A,B,C,D

(1)下面有关 JVM 内存,说法错误的是?

  • 程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,是线程隔离的
  • 虚拟机栈描述的是 Java 方法执行的内存模型,用于存储局部变量,操作数栈,动态链接,方法出口等信息,是线程隔离的
  • 方法区用于存储 JVM 加载的类信息、常量、静态变量、以及编译器编译后的代码等数据,是线程隔离的
  • 原则上讲,所有的对象都在堆区上分配内存,是线程之间共享的

答案:C 、解析:

大多数 JVM 将内存区域划分为:

Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟机栈,也有翻译成 JAVA 方法栈的),Native Method Stack ( 本地方法栈 )

其中 Method AreaHeap线程共享的 ** ,

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上)的原因。


(2)下面有关 jdbc statement 的说法错误的是?

  • JDBC提供了 Statement、PreparedStatement 和 CallableStatement 三种方式来执行查询语句,其中 Statement 用于通用查询,PreparedStatement 用于执行参数化查询,而 CallableStatement 则是用于存储过程
  • 对于 PreparedStatement 来说,数据库可以使用已经编译过及定义好的执行计划,由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象”
  • PreparedStatement 中,“?” 叫做占位符,一个占位符可以有一个或者多个值
  • PreparedStatement 可以阻止常见的 SQL 注入式攻击

答案:C、解析:

JDBC statement 中的 PReparedStatement 的占位符对应着即将与之对应当值,并且一个占位符只能对应一个值,如果能对应多个就会引起混淆。sql 语句是确定的,那么一个占位符必定只能对应一个值。

(1)Statement、PreparedStatement 和 CallableStatement 都是接口(interface)。

(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)的支持;

(5)

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、解析:

PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。

扩展:

事务属性的种类: 传播行为、隔离级别、只读和事务超时

  • (1)传播行为定义了被调用方法的事务边界。


传播行为


意义

PROPERGATION_MANDATORY

表示方法必须运行在一个事务中,如果当前事务不存在,就抛出异常

PROPAGATION_NESTED

表示如果当前事务存在,则方法应该运行在一个嵌套事务中。否则,它看起来和
PROPAGATION_REQUIRED
看起来没什么俩样

PROPAGATION_NEVER

表示方法不能运行在一个事务中,否则抛出异常

PROPAGATION_NOT_SUPPORTED

表示方法不能运行在一个事务中,如果当前存在一个事务,则该方法将被挂起

PROPAGATION_REQUIRED

表示当前方法必须运行在一个事务中,如果当前存在一个事务,那么该方法运行在这个事务中,否则,将创建一个新的事务

PROPAGATION_REQUIRES_NEW

表示当前方法必须运行在自己的事务中,如果当前存在一个事务,那么这个事务将在该方法运行期间被挂起

PROPAGATION_SUPPORTS

表示当前方法不需要运行在一个是事务中,但如果有一个事务已经存在,该方法也可以运行在这个事务中

- (2) 隔离级别
在操作数据时可能带来 3 个副作用,分别是脏读、不可重复读、幻读。为了避免这 3 中副作用的发生,在标准的 SQL 语句中定义了 4 种隔离级别,分别是未提交读、已提交读、可重复读、可序列化。而在 spring 事务中提供了 5 种隔离级别来对应在 SQL 中定义的 4 种隔离级别,如下:


隔离级别


意义

ISOLATION_DEFAULT

使用后端数据库默认的隔离级别

ISOLATION_READ_UNCOMMITTED

允许读取未提交的数据(对应未提交读),可能导致脏读、不可重复读、幻读

ISOLATION_READ_COMMITTED

允许在一个事务中读取另一个已经提交的事务中的数据(对应已提交读)。可以避免脏读,但是无法避免不可重复读和幻读

ISOLATION_REPEATABLE_READ

一个事务不可能更新由另一个事务修改但尚未提交(回滚)的数据(对应可重复读)。可以避免脏读和不可重复读,但无法避免幻读

ISOLATION_SERIALIZABLE

这种隔离级别是所有的事务都在一个执行队列中,依次顺序执行,而不是并行(对应可序列化)。可以避免脏读、不可重复读、幻读。但是这种隔离级别效率很低,因此,除非必须,否则不建议使用。

  • (3)只读

如果在一个事务中所有关于数据库的操作都是只读的,也就是说,这些操作只读取数据库中的数据,而并不更新数据,那么应将事务设为只读模式( READ_ONLY_MARKER ) , 这样更有利于数据库进行优化 。

因为只读的优化措施是事务启动后由数据库实施的,因此,只有将那些具有可能启动新事务的传播行为 (PROPAGATION_NESTED 、 PROPAGATION_REQUIRED 、 PROPAGATION_REQUIRED_NEW) 的方法的事务标记成只读才有意义。

如果使用 Hibernate 作为持久化机制,那么将事务标记为只读后,会将 Hibernate 的 flush 模式设置为 FULSH_NEVER, 以告诉 Hibernate 避免和数据库之间进行不必要的同步,并将所有更新延迟到事务结束。

  • (4)事务超时

如果一个事务长时间运行,这时为了尽量避免浪费系统资源,应为这个事务设置一个有效时间,使其等待数秒后自动回滚。与设

置“只读”属性一样,事务有效属性也需要给那些具有可能启动新事物的传播行为的方法的事务标记成只读才有意义。


(4)下面有关 servlet 和 cgi 的描述,说法错误的是?

  • servlet 处于服务器进程中,它通过多线程方式运行其 service 方法
  • CGI 对每个请求都产生新的进程,服务完成后就销毁
  • servlet 在易用性上强于 cgi,它提供了大量的实用工具例程,例如自动地解析和解码 HTML 表单数据、读取和设置 HTTP 头、处理 Cookie、跟踪会话状态等
  • cgi 在移植性上高于 servlet,几乎所有的主流服务器都直接或通过插件支持 cgi

答案:D、解析:

servlet 处于服务器进程中,它通过多线程方式运行其 service 方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而 CGI 对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于 servlet。

扩展:

Servlet 与 CGI 的比较

和 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 有连接池的概念,它可以利用多线程的优点,在系统缓存中事先建立好若干与数据库的连接,到时候若想和数据库打交道可以随时跟系统"要"一个连接即可,反应速度可想而知。


(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 中实现的

而 GenericServlet 抽象类 给出了设计 servlet 的一些骨架,定义了 servlet 生命周期,还有一些得到名字、配置、初始化参数的方法,其设计的是和应用层协议无关的


(6)下列有关 Servlet 的生命周期,说法不正确的是?

  • 在创建自己的 Servlet 时候,应该在初始化方法 init() 方法中创建 Servlet 实例
  • 在 Servlet 生命周期的服务阶段,执行 service() 方法,根据用户请求的方法,执行相应的 doGet() 或是 doPost() 方法
  • 在销毁阶段,执行 destroy() 方法后会释放 Servlet 占用的资源
  • destroy() 方法仅执行一次,即在服务器停止且卸载 Servlet 时执行该方法

答案:A、解析:

创建 Servlet 的实例是由 Servlet 容器来完成的,且创建 Servlet 实例是在初始化方法 init() 之前

Servlet 的生命周期:

Servlet 的生命周期分为5个阶段:加载、创建、初始化、处理客户请求、卸载。

  • (1)加载:容器通过类加载器使用servlet类对应的文件加载servlet
  • (2)创建:通过调用servlet构造函数创建一个servlet对象
  • (3)初始化:调用init方法初始化
  • (4)处理客户请求:每当有一个客户请求,容器会创建一个线程来处理客户请求
  • (5)卸载:调用destroy方法让servlet自己释放其占用的资源

(7)下面有关servlet中init,service,destroy方法描述错误的是?

  • init()方法是servlet生命的起点。一旦加载了某个servlet,服务器将立即调用它的init()方法
  • service()方法处理客户机发出的所有请求
  • destroy()方法标志servlet生命周期的结束
  • servlet在多线程下使用了同步机制,因此,在并发编程下servlet是线程安全的

答案:D、解析:

servlet 在多线程下其本身并不是线程安全的。

如果在类中定义成员变量,而在 service 中根据不同的线程对该成员变量进行更改,那么在并发的时候就会引起错误。最好是在方法中,定义局部变量,而不是类变量或者对象的成员变量。由于方法中的局部变量是在栈中,彼此各自都拥有独立的运行空间而不会互相干扰,因此才做到线程安全。


(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、解析:

从 action 类上分析:

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 容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)


(9)关于 AWT 和 Swing 说法正确的是?

  • Swing 是AWT的子类
  • AWT 在不同操作系统中显示相同的风格
  • AWT 不支持事件类型,Swing 支持事件模型
  • Swing 在不同的操作系统中显示相同的风格

答案:D、解析:

AWT,抽象窗口工具包,是 Java 提供的建立图形用户界面的工具集,可用于生成现代的、鼠标控制的图形应用接口,且无需修改,就可以在各种软硬件平台上运行。

而 swing 是 Java 语言在编写图形用户界面方面的新技术,Swing 采用模型-视图-控制设计范式,Swing 可以使 Java 程序在同一个平台上运行时能够有不同外观以供用户选择。

两者不同在于一个是初代工具集,一个是进化版的工具集,用户不会再满足于初始的功能,而是更加注重于附加价值,明显从这点上,Swing 是比 AWT 要好很多。

写法上,Swing 的头文件引用包需要用到 Javax,组件调用时也需要在 AWT 的基础上加上 “J”。


(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.jsp
  • http:// 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、解析:

redirect:请求重定向:客户端行为,本质上为2次请求,地址栏改变,前一次请求对象消失。举例:你去银行办事(forward.jsp),结果告诉你少带了东西,你得先去*局办(index.html)临时身份证,这时你就会走出银行,自己前往*局,地址栏变为index.html.

forward:请求转发:服务器行为,地址栏不变。举例:你把钱包落在出租车上,你去警察局(forward.jsp)报案,警察局说钱包落在某某公司的出租车上(index.html),这时你不用亲自去找某某公司的出租车,警察局让出租车自己给你送来,你只要在警察局等就行。所以地址栏不变,依然为forward.jsp


(11)下面哪一项不是加载驱动程序的方法?

  • 通过 DriverManager.getConnection 方法加载
  • 调用方法 Class.forName
  • 通过添加系统的 jdbc.drivers 属性
  • 通过 registerDriver 方法注册

答案:A、解析:

加载驱动方法:

1.Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

2.DriverManager.registerDriver(new com.mysql.jdbc.Driver());

3.System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");


(12)关于sleep()和wait(),以下描述错误的一项是( )

  • sleep是线程类(Thread)的方法,wait是Object类的方法;
  • sleep不释放对象锁,wait放弃对象锁
  • sleep暂停线程、但监控状态仍然保持,结束后会自动恢复
  • wait后进入等待锁定池,只有针对此对象发出notify方法后获得对象锁进入运行状态

答案:D、解析:

Java中的多线程是一种抢占式的机制,而不是分时机制。抢占式的机制是有多个线程处于可运行状态,但是只有一个线程在运行。

共同点 :

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 不需要捕获异常

4.sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用 sleep 不会释放对象锁。

5.wait 是 Object 类的方法,对此对象调用 wait 方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出 notify 方法(或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、解析:

a = new Square(42L);
b = new Square(42L);

这里 new 了两个对象,所以 a,b 不是同一个引用 a!=b

s 的类型跟 a,b 不同类型,所以 s!=a,s!=b

 c = b;

这里 b,c 是同一个对象的引用,所以 b==c 是 true


(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、解析:

JVM 中一个字节以下的整型数据会在 JVM 启动的时候加载进内存,除非用 new Integer() 显式的创建对象,否则都是同一个对象

所有只有 i04 是一个新对象,其他都是同一个对象。所有 A,B 选项为 true

C选项 i03 和 i04 是两个不同的对象,返回 false

D选项 i02 是基本数据类型,比较的时候比较的是数值,返回 true


(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、解析:

四个选项都来自于Java API原文

A选项是RuntimeException的定义;

B选项是把Error的第二段定义拿来改掉换成RuntimeException,但这样说对于RuntimeException也没错;

C选项也是把Error的定义换成了RuntimeException,但这里的"indicates serious problems"不应该用在RuntimeException上,Error才表示严重的错误,RuntimeException并不是.

D选项显然.

牛客网 Java 工程师能力评估 20 题 - 详解

运行时异常:

都是 RuntimeException 类及其子类异常,如 NullPointerException(空指针异常)、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、解析:

main 是 HasStatic 的静态方法,在其内部可直接访问静态变量,不存在因为私有变量不能通过编译的问题;如果在其他类中,包括 HasStatic 的派生类中,均不能访问其私有静态变量


(17)关于struts项目中的类与MVC模式的对应关系,说法错误的是:

  • Jsp 文件实现视图 View 的功能
  • ActionServlet 这一个类是整个 struts 项目的控制器
  • ActionForm、Action 都属于 Model 部分
  • 一个 struts 项目只能有一个 Servlet

答案:C、D 解析:

牛客网 Java 工程师能力评估 20 题 - 详解


(18)下面有关 jsp 中静态 include 和动态 include 的区别,说法错误的是?

  • 动态 INCLUDE:用 jsp:include 动作实现
  • 静态 INCLUDE:用 include 伪码实现,定不会检查所含文件的变化,适用于包含静态页面 <%@ include file="included.htm" %>
  • 静态 include 的结果是把其他 jsp 引入当前 jsp,两者合为一体;动态 include 的结构是两者独立,直到输出时才合并
  • 静态 include 和动态 include 都可以允许变量同名的冲突.页面设置也可以借用主文件的

答案:D、解析:

动态 INCLUDE 用 jsp:include 动作实现 <jsp:include page="included.jsp" flush="true" /> 它总是会检查所含文件中的变化 , 适合用于包含动态页面 , 并且可以带参数。各个文件分别先编译,然后组合成一个文件。

静态 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 所生成的应答文本 .


(19)给定以下JAVA代码,这段代码运行后输出的结果是()

public class Test
{
public static int aMethod(int i)throws Exception
{
try{
return i / 10;
}
catch (Exception ex)
{
throw new Exception("exception in a Method");
} finally{
System.out.printf("finally");
}
} public static void main(String [] args)
{
try
{
aMethod(0);
}
catch (Exception ex)
{
System.out.printf("exception in main");
}
System.out.printf("finished");
}
}
  • exception in main finished
  • finally finished
  • exception in main finally
  • finally exception in main finished

答案:B、解析:

i / 10;无论 i 是多少,永远不会抛出异常,所以 catch 语句不会执行。

而 finally 语句是必定执行的语句。

所以先指向 aMathod() 的 finally 代码块,输出 finally

然后执行 main() 方法的最后一条输出语句,输出 finished


(20)对于 JVM 内存配置参数:

-Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3

,其最小内存值和 Survivor 区总大小分别是()

  • 5120m,1024m
  • 5120m,2048m
  • 10240m,1024m
  • 10240m,2048m

答案:D、解析:

-Xmx:最大堆大小

-Xms:初始堆大小

-Xmn:年轻代大小

-XXSurvivorRatio:年轻代中Eden区与Survivor区的大小比值

年轻代5120m, Eden:Survivor=3,Survivor区大小=1024m(Survivor区有两个,即将年轻代分为5份,每个Survivor区占一份),总大小为2048m。

-Xms 初始堆大小即最小内存值为 10240m