Java工程师笔试

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

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

解释:方法区在JVM中也是一个非常重要的区域,它与堆一样,是被 线程共享 的区域。 在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。

 

2、下面有关jdbc statement的说法错误的是? C

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

解释:

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

Statement每次执行sql语句,数据库都要执行sql语句的编译 ,  
最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement。  

PreparedStatement是预编译的,使用PreparedStatement有几个好处  
1. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。  
2. 安全性好,有效防止Sql注入等问题。  
3.  对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;  
4.  代码的可读性和可维护性。

 

3、下面有关servlet service描述错误的是?B

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

 解释:doGet/doPost 则是在 javax.servlet.http.HttpServlet 中实现的,javax.servlet.http.HttpServlet 是 javax.servlet.GenericServlet 的子类。


javax.servlet.http.HttpServlet 的 service() 方法中, 主要做的事情就是判断请求类型是 Get 还是 Post, 然后调用对应的 doGet/doPost 执行。

 

4、下列有关Servlet的生命周期,说法不正确的是?

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

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

Servlet的生命周期分为5个阶段:加载、创建、初始化、处理客户请求、卸载。
(1)加载:Servlet容器(Tomcat)通过类加载器加载servlet文件(.class)
(2)创建:通过调用servlet构造函数创建一个servlet对象
(3)初始化:调用init方法初始化
(4)处理客户请求:每当有一个客户请求,容器会创建一个线程来处理客户请求
(5)卸载:调用destroy方法让servlet自己释放其占用的资源
servlet是由Servlet容器负责加载Servlet类,创建Servlet对象并实例化,然后调用Servlet的init方法,进行初始化,之后调用Service方法。实例化和初始化不同。先实例化,再初始化。
再说一下ServletConfig和ServletContext
1. Jsp/Servlet容器初始化一个Servlet类型的对象时,会为这个Servlet对象创建一个ServletConfig对象。在ServletConfig对象中包含了Servlet的初始化参数信息。
2. ServletContext是servlet与servlet容器之间的直接通信的接口。Servlet容器在启动一个Webapp时,会为它创建一个ServletContext对象,即servlet上下文环境。每个webapp都有唯一的ServletContext对象。同一个webapp的所有servlet对象共享一个ServeltContext,servlet对象可以通过ServletContext来访问容器中的各种资源。
从作用范围来说,ServletConfig作用于某个特定的Servlet,即从该Servlet实例化,那么就开始有效,但是该Servlet之外的其他Servlet不能访问;ServletContext作用于某个webapp,即在一个webapp中相当于一个全局对象,在Servlet容器启动时就已经加载,对于不同的webapp,有不同的ServletContext。
最后,说明一下参数的获取。访问ServletConfig参数,取得ServletConfig对象后,调用getInitParameter()方法;访问ServletContext对象,只要调用现有的ServletConfig对象的getServletContext()即可,然后同样调用getInitParamter()方法就能获取参数。

 

5、下面有关struts1和struts2的区别,描述错误的是?

A、Struts1要求Action类继承一个抽象基类。Struts 2 Action类可以实现一个Action接口
B、Struts1 Action对象为每一个请求产生一个实例。Struts2 Action是单例模式并且必须是线程安全的
C、Struts1 Action 依赖于Servlet API,Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试
D、Struts1 整合了JSTL,Struts2可以使用JSTL,但是也支持OGNL

解释:

参考:https://www.nowcoder.com/questionTerminal/71bcf5cc03004b8e8873af37ef5f8445

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

 

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

 

6、看以下代码: 
文件名称:forward.jsp 

1

2

3

4

5

6

<html>  

     <head><title> 跳转  </title> </head

     <body>  

         <jsp:forward page="index.htm"/>     

     </body>

 </html

如果运行以上jsp文件,地址栏的内容为

A、http://127.0.0.1:8080/myjsp/forward.jsp
B、http://127.0.0.1:8080/myjsp/index.jsp
C、http://127.0.0.1:8080/myjsp/index.htm
D、http://127.0.0.1:8080/myjsp/forward.htm

解释:

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

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

 

7、下面哪一项不是加载驱动程序的方法?

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

解释:DriverManager.getConnection方法返回一个Connection对象,这是加载驱动之后才能进行的

 

加载驱动方法

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

 

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

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

解释:notity()和notifyAll()两个方法均可,应该进入就绪状态而不是运行状态。

 

9、

在jdk1.5的环境下,有如下4条语句:

1

2

3

4

Integer i01 = 59;

int i02 = 59;

Integer i03 =Integer.valueOf(59);

Integer i04 = new Integer(59);

 以下输出结果为false的是:C

A、System.out.println(i01 == i02);
B、System.out.println(i01 == i03);
C、System.out.println(i03 == i04);
D、System.out.println(i02 == i04);

解释:

参考:https://www.nowcoder.com/questionTerminal/bc5da9d0b8444006a776b7cbfba5d250

① 无论如何,Integer与new Integer不会相等。不会经历拆箱过程,i3的引用指向堆,而i4指向专门存放他的内存(常量池),他们的内存地址不一样,所以为false

② 两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false

java在编译Integer i2 = 128的时候,被翻译成-> Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存

③ 两个都是new出来的,都为false

④ int和Integer(无论new否)比,都为true,因为会把Integer自动拆箱为int再去比

 

基本数据类型和包装类的比较。

1. 只要涉及到基本数据类型,一直表示的是值比较。也就是说,只要==号左边或者右边有一个是基本数据类型,那么就是值比较。

2. 如果==号左右两边都是包装类,那么==号表示引用类型所指地址是否一致。

    注意:

        1. 因为Integer这个包装类比较特殊,内部有一个数组cache数组,保存了-128到127的值,也就是Integer i = n,只要n在-128到127之间,都是直接从cache数组中获取,不会再创建新的对象。

        2. 对于其他的包装类,比如Double d = 2.1;那么2.1会被自动装箱,也就是调用valueOf方法,这个方法内部还是new了一个Double对象的。

        3. 同时需要注意,自动装箱可不提供向上转型,也就是Double d = 1;1不会先自动向上转成double然后再装箱,会直接编译错误,因为Double这个包装类中就没有形参是int的构造器,其他包装类也是一样的。

3. 包装类的equals方法,不提供类型转换。例如Byte b = 100;Integer i = 100;i.equals(b);返回false。

        1. equals方法先比较类型,再比较值。

 

 10、关于struts项目中的类与MVC模式的对应关系,说法错误的是CD

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

解释:

 

10、______可区分存储单元中存放的是指令还是数据。

A、存储器
B、运算器
C、控制器
D、用户

 

11、分支限界法和回溯法对比

 

对解空间树的搜索方式

存储结点的常用数据结构

结点存储特性

常用应用

回溯法

深度优先搜索

堆栈

活结点的所有可行子结点被遍历后才被从栈中弹出

找出满足约束条件的所有解

分支限界法

广度优先或最小消耗优先搜索

队列、优先队列

每个结点只有一次成为活结点的机会

找出满足约束条件的一个解或特定意义下的最优解

 

 12、HTML解释器解释过程

解释器的作用就是将本地磁盘或者网络获取的HTML网页和资源从字节流解释成DOM树结构,Webkit的处理过程如下: 

13、JavaScript的宏任务与微任务

 宏任务:包括整体代码script,setTimeout,setInterval。

微任务:Promise,process.nextTick。

setTimeout(function(){
		    console.log('1')
		});
 
		new Promise(function(resolve){
		    console.log('2');
                    resolve();
		}).then(function(){
		    console.log('3')
		});
 
		console.log('4');

 输出:

2
4
3
1
  • 这段代码作为宏任务,进入主线程。
  • 先遇到setTimeout,那么将其回调函数注册后分发到宏任务Event Queue。(注册过程与上同,下文不再描述)
  • 接下来遇到了Promisenew Promise立即执行,then函数分发到微任务Event Queue。
  • 遇到console.log(),立即执行。
  • 好啦,整体代码script作为第一个宏任务执行结束,看看有哪些微任务?我们发现了then在微任务Event Queue里面,执行。
  • ok,第一轮事件循环结束了,我们开始第二轮循环,当然要从宏任务Event Queue开始。我们发现了宏任务Event Queue中setTimeout对应的回调函数,立即执行。
  • 结束。


作者:ssssyoki
链接:https://juejin.im/post/59e85eebf265da430d571f89
来源:掘金

14、

在jdk1.5之后,下列 java 程序输出结果为______。

1

2

3

4

int i=0;

Integer j = new Integer(0);

System.out.println(i==j);

System.out.println(j.equals(i));

 答案:true,true

解析:本题是一个自动拆装箱的考题(自动拆装箱JDK需在1.5上),下面的讨论都不针对新开辟对象的情况:
1、基本型和基本型封装型进行“==”运算符的比较,基本型封装型将会自动拆箱变为基本型后再进行比较,因此Integer(0)会自动拆箱为int类型再进行比较,显然返回true;
2、两个Integer类型进行“==”比较,如果其值在-128至127,那么返回true,否则返回false, 这跟Integer.valueOf()的缓冲对象有关,这里不进行赘述。
3、两个基本型的封装型进行equals()比较,首先equals()会比较类型,如果类型相同,则继续比较值,如果值也相同,返回true
4、基本型封装类型调用equals(),但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型,再进行3中的比较。

int a=257;
Integer b=257;
Integer c=257;
Integer b2=57;
Integer c2=57;
System.out.println(a==b);
//System.out.println(a.equals(b));  编译出错,基本型不能调用equals()
System.out.println(b.equals(257.0));
System.out.println(b==c);
System.out.println(b2==c2);

 

因此上面的代码的结果因此为 true, false, false, true

 

15、下面有关forward和redirect的描述,正确的是() ? 

A、forward是服务器将控制权转交给另外一个内部服务器对象,由新的对象来全权负责响应用户的请求
B、执行forward时,浏览器不知道服务器发送的内容是从何处来,浏览器地址栏中还是原来的地址
C、执行redirect时,服务器端告诉浏览器重新去请求地址
D、forward是内部重定向,redirect是外部重定向
E、redirect默认将产生301 Permanently moved的HTTP响应

答案: B C D 

解析:

1.从地址栏显示来说

forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.

redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.

2.从数据共享来说

forward:转发页面和转发到的页面可以共享request里面的数据.

redirect:不能共享数据.

3.从运用地方来说

forward:一般用于用户登陆的时候,根据角色转发到相应的模块.

redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.

4.从效率来说

forward:高.

redirect:低.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值