java架构面试题及答案(百度java面试题有哪些 集锦汇总java面试)

本文目录
百度java面试题有哪些 集锦汇总java面试
1、Servlet 3中的异步处理指的是什么?
答:在Servlet
3中引入了一项新的技术可以让Servlet异步处理请求。有人可能会质疑,既然都有多线程了,还需要异步处理请求吗?答案是肯定的,因为如果一个任务处理时间相当长,那么Servlet或Filter会一直占用着请求处理线程直到任务结束,随着并发用户的增加,容器将会遭遇线程超出的风险,这这种情况下很多的请求将会被堆积起来而后续的请求可能会遭遇拒绝服务,直到有资源可以处理请求为止。异步特性可以帮助应用节省容器中的线程,特别适合执行时间长而且用户需要得到结果的任务,如果用户不需要得到结果则直接将一个Runnable对象交给Executor并立即返回即可。
补充:多线程在Java诞生初期无疑是一个亮点,而Servlet单实例多线程的工作方式也曾为其赢得美名,然而技术的发展往往会颠覆我们很多的认知,就如同当年爱因斯坦的相对论颠覆了牛顿的经典力学一般。事实上,异步处理绝不是Serlvet
3首创,如果你了解Node.js的话,对Servlet 3的这个重要改进就不以为奇了。
下面是一个支持异步处理请求的Servlet的例子。
importjava.io.IOException; importjavax.servlet.AsyncContext;
importjavax.servlet.ServletException; importjavax.servlet.annotation.WebServlet;
***隐藏网址***
***隐藏网址***
***隐藏网址***
"/async"}, asyncSupported = true)
publicclassAsyncServletextendsHttpServlet{privatestaticfinallongserialVersionUID
= 1L; @OverridepublicvoiddoGet(HttpServletRequest req, HttpServletResponse resp)
throwsServletException, IOException { // 开启Tomcat异步Servlet支持req.setAttribute(
"org.apache.catalina.ASYNC_SUPPORTED", true); finalAsyncContext ctx =
req.startAsync(); // 启动异步处理的上下文// ctx.setTimeout(30000);ctx.start( newRunnable()
{ @Overridepublicvoidrun() { // 在此处添加异步处理的代码ctx.complete(); } }); } }
2、如何在基于Java的Web项目中实现文件上传和下载?
答:在Sevlet 3 以前,Servlet
API中没有支持上传功能的API,因此要实现上传功能需要引入第三方工具从POST请求中获得上传的附件或者通过自行处理输入流来获得上传的文件,我们推荐使用Apache的commons-fileupload。
从Servlet 3开始,文件上传变得无比简单,相信看看下面的例子一切都清楚了。
上传页面index.jsp:
Select your photo and upload
${hint}
Photo file:
支持上传的Servlet:
packagecom.jackfrued.servlet; importjava.io.IOException;
importjavax.servlet.ServletException;
importjavax.servlet.annotation.MultipartConfig;
***隐藏网址***
***隐藏网址***
***隐藏网址***
@WebServlet( "/UploadServlet")
@MultipartConfigpublicclassUploadServletextendsHttpServlet{privatestaticfinallongserialVersionUID
= 1L; protectedvoiddoPost(HttpServletRequest request, HttpServletResponse
response) throwsServletException, IOException { //
可以用request.getPart()方法获得名为photo的上传附件// 也可以用request.getParts()获得所有上传附件(多文件上传)//
然后通过循环分别处理每一个上传的文件Part part = request.getPart( "photo"); if(part !=
null&& part.getSubmittedFileName().length() 》 0) { //
用ServletContext对象的getRealPath()方法获得上传文件夹的绝对路径String savePath =
request.getServletContext().getRealPath( "/upload"); // Servlet
3.1规范中可以用Part对象的getSubmittedFileName()方法获得上传的文件名//
更好的做法是为上传的文件进行重命名(避免同名文件的相互覆盖)part.write(savePath + "/"+
part.getSubmittedFileName()); request.setAttribute( "hint", "Upload
Successfully!"); } else{ request.setAttribute( "hint", "Upload failed!"); } //
跳转回到上传页面request.getRequestDispatcher( "index.jsp").forward(request, response); }
}
3、服务器收到用户提交的表单数据,到底是调用Servlet的doGet()还是doPost()方法?
答:HTML的
《 %--静态包含 --%》 《 %--动态包含 --%》 《 jsp:includepage= "..."》
《 jsp:param name= "..."value= "..."/》 《 /jsp:include》
4、Servlet中如何获取用户提交的查询参数或表单数据?
答:可以通过请求对象(HttpServletRequest)的getParameter()方法通过参数名获得参数值。如果有包含多个值的参数(例如复选框),可以通过请求对象的getParameterValues()方法获得。当然也可以通过请求对象的getParameterMap()获得一个参数名和参数值的映射(Map)。
5、Servlet中如何获取用户配置的初始化参数以及服务器上下文参数?
答:可以通过重写Servlet接口的init(ServletConfig)方法并通过ServletConfig对象的getInitParameter()方法来获取Servlet的初始化参数。可以通过ServletConfig对象的getServletContext()方法获取ServletContext对象,并通过该对象的getInitParameter()方法来获取服务器上下文参数。当然,ServletContext对象也在处理用户请求的方法(如doGet()方法)中通过请求对象的getServletContext()方法来获得。
2018年的JAVA面试题及答案
Java知识点很多,每个知识点都可能会有面试题,而且不同的企业的考察点是不一样的。下面给你整理了几个Java面试题可以参考:
1、面向对象的特征有哪些方面?
封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。
多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。
2、获得一个类的类对象有哪些方式?
答:
- 方法1:类型.class,例如:String.class
- 方法2:对象.getClass(),例如:"hello".getClass()
- 方法3:Class.forName(),例如:Class.forName("java.lang.String")
3、如何通过反射创建对象?
答:
- 方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance()
- 方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器
(Constructor)对象并调用其newInstance()方法创建对象,例如:
String.class.getConstructor(String.class).newInstance("Hello");
javaMVC架构面试题
model:模型层
view:视图层
controller:控制层
mvc (modal view controler)本来是存在于desktop程序中的,m是指数据模型,v是指用户界面,c则是控制器。使用mvc的目的是将m和v的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据你可以分别用柱状图、饼图来表示。c存在的目的则是确保m和v的同步,一旦m改变,v应该同步更新。
模型-视图-控制器(mvc)是xerox parc在八十年代为编程语言smalltalk-80发明的一种软件设计模式,至今已被广泛使用。最近几年被推荐为sun公司j2ee平台的设计模式,并且受到越来越多的使用 coldfusion 和 php 的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但也有一些缺点。
mvc如何工作
mvc是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用mvc应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。
视图
视图是用户看到并与之交互的界面。对老式的web应用程序来说,视图就是由html元素组成的界面,在新式的web应用程序中,html依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括macromedia flash和象xhtml,xml/xsl,wml等一些标识语言和web services.
如何处理应用程序的界面变得越来越有挑战性。mvc一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。
模型
模型表示企业数据和业务规则。在mvc的三个部件中,模型拥有最多的处理任务。例如它可能用象ejbs和coldfusion components这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
控制器
控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击web页面中的超链接和发送html表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据。
现在我们总结mvc的处理过程,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层呈现给用户。
为什么要使用 mvc
大部分web应用程序都是用像asp,php,或者cfml这样的过程化语言来创建的。它们将像数据库查询语句这样的数据层代码和像html这样的表示层代码混在一起。经验比较丰富的开发者会将数据从表示层分离开来,但这通常不是很容易做到的,
它需要精心的计划和不断的尝试。mvc从根本上强制性的将它们分开。尽管构造mvc应用程序需要一些额外的工作,但是它给我们带来的好处是无庸质疑的。
首先,最重要的一点是多个视图能共享一个模型,正如我所提及的,现在需要用越来越多的方式来访问你的应用程序。对此,其中一个解决之道是使用mvc,无论你的用户想要flash界面或是 wap 界面;用一个模型就能处理它们。由于你已经将数据和业务规则从表示层分开,所以你可以最大化的重用你的代码了。
由于模型返回的数据没有进行格式化,所以同样的构件能被不同界面使用。例如,很多数据可能用html来表示,但是它们也有可能要用macromedia flash和wap来表示。模型也有状态管理和数据持久性处理的功能,例如,基于会话的购物车和电子商务过程也能被flash网站或者无线联网的应用程序所重用。
因为模型是自包含的,并且与控制器和视图相分离,所以很容易改变你的应用程序的数据层和业务规则。如果你想把你的数据库从mysql移植到oracle,或者改变你的基于rdbms数据源到ldap,只需改变你的模型即可。一旦你正确的实现了模型,不管你的数据来自数据库或是ldap服务器,视图将会正确的显示它们。由于运用mvc的应用程序的三个部件是相互对立,改变其中一个不会影响其它两个,所以依据这种设计思想你能构造良好的松偶合的构件。
对我来说,控制器的也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。
mvc的缺点
mvc的缺点是由于它没有明确的定义,所以完全理解mvc并不是很容易。使用mvc需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。
你将不得不花费相当可观的时间去考虑如何将mvc运用到你的应用程序,同时由于模型和视图要严格的分离,这样也给调试应用程序到来了一定的困难。每个构件在使用之前都需要经过彻底的测试。一旦你的构件经过了测试,你就可以毫无顾忌的重用它们了。
根据我个人经验,由于我们将一个应用程序分成了三个部件,所以使用mvc同时也意味着你将要管理比以前更多的文件,这一点是显而易见的。这样好像我们的工作量增加了,但是请记住这比起它所能带给我们的好处是不值一提。
mvc并不适合小型甚至中等规模的应用程序,花费大量时间将mvc应用到规模并不是很大的应用程序通常会得不偿失。
mvc是一条创建软件的好途径
mvc设计模式是一个很好创建软件的途径,它所提倡的一些原则,像内容和显示互相分离可能比较好理解。但是如果你要隔离模型、视图和控制器的构件,你可能需要重新思考你的应用程序,尤其是应用程序的构架方面。如果你肯接受mvc,并且有能力应付它所带来的额外的工作和复杂性,mvc将会使你的软件在健壮性,代码重用和结构方面上一个新的台阶。
java面试题 很急 谢谢
2, 归并排序(merge sort)体现了分治的思想,即将一个待排序数组分为两部分,对这两个部分进行归并排序,排序后,再对两个已经排序好的数组进行合并。这种思想可以用递归方式很容易实现。归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。
实现代码如下:
#include 《stdio.h》
#include "common.h"
void merge(int data, int p, int q, int r)
{
int i, j, k, n1, n2;
n1 = q - p + 1;
n2 = r - q;
int L;
int R;
for(i = 0, k = p; i 《 n1; i++, k++)
L;
for(i = 0, k = q + 1; i 《 n2; i++, k++)
R;
for(k = p, i = 0, j = 0; i 《 n1 && j 《 n2; k++)
{
if(L)
{
data;
i++;
}
else
{
data;
j++;
}
}
if(i 《 n1)
{
for(j = i; j 《 n1; j++, k++)
data;
}
if(j 《 n2)
{
for(i = j; i 《 n2; i++, k++)
data;
}
}
void merge_sort(int data, int p, int r)
{
if(p 《 r)
{
int q = (p + r) / 2;
merge_sort(data, p, q);
merge_sort(data, q + 1, r);
merge(data, p, q, r);
}
}
void test_merge_sort()
{
int data = {44, 12, 145, -123, -1, 0, 121};
printf("-------------------------------merge sort----------------------------\n");
out_int_array(data, 7);
merge_sort(data, 0, 6);
out_int_array(data, 7);
}
int main()
{
test_merge_sort();
return 0;
}
4.对于有n个结点的线性表(e0,e1,…,en-1),将结点中某些数据项的值按递增或递减的次序,重新排列线性表结点的过程,称为排序。排序时参照的数据项称为排序码,通常选择结点的键值作为排序码。
若线性表中排序码相等的结点经某种排序方法进行排序后,仍能保持它们在排序之前的相对次序,称这种排序方法是稳定的;否则,称这种排序方法是不稳定的。
在排序过程中,线性表的全部结点都在内存,并在内存中调整它们在线性表中的存储顺序,称为内排序。在排序过程中,线性表只有部分结点被调入内存,并借助内存调整结点在外存中的存放顺序的排序方法成为外排序。
下面通过一个表格简单介绍几种常见的内排序方法,以及比较一下它们之间的性能特点。
排序方法
简介
平均时间
最坏情况
辅助存储
是否稳定
简单排序
选择排序
反复从还未排好序的那部分线性表中选出键值最小的结点,并按从线性表中选出的顺序排列结点,重新组成线性表。直至未排序的那部分为空,则重新形成的线性表是一个有序的线性表。
O( )
O( )
O(1)
不稳定
直接插入排序
假设线性表的前面I个结点序列e0,e1,…,en-1是已排序的。对结点在这有序结点ei序列中找插入位置,并将ei插入,而使i+1个结点序列e0,e1,…,ei也变成排序的。依次对i=1,2,…,n-1分别执行这样的插入步骤,最终实现线性表的排序。
O( )
O( )
O(1)
稳定
冒泡排序
对当前还未排好序的范围内的全部结点,自上而下对相邻的两个结点依次进行比较和调整,让键值大的结点往下沉,键值小的结点往上冒。即,每当两相邻比较后发现它们的排列顺序与排序要求相反时,就将它们互换。
O( )
O( )
O(1)
稳定
希尔排序
对直接插入排序一种改进,又称“缩小增量排序”。先将整个待排序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。
kn ln n
O( )
O(logn)
不稳定
快速排序
对冒泡排序的一种本质的改进。通过一趟扫视后,使待排序序列的长度能大幅度的减少。在一趟扫视后,使某个结点移到中间的正确位置,并使在它左边序列的结点的键值都比它的小,而它右边序列的结点的键值都不比它的小。称这样一次扫视为“划分”。每次划分使一个长序列变成两个新的较小子序列,对这两个小的子序列分别作同样的划分,直至新的子序列的长度为1使才不再划分。当所有子序列长度都为1时,序列已是排好序的了。
O(nlogn)
O( )
O(logn)
不稳定
堆排序
一种树形选择排序,是对直接选择排序的有效改进。一个堆是这样一棵顺序存储的二叉树,它的所有父结点(e)的键值。初始时,若把待排序序列的n个结点看作是一棵顺序存储的二叉树,调整它们的存储顺序,使之成为一个堆,这时堆的根结点键值是最大者。然后将根结点与堆的最后一个结点交换,并对少了一个结点后的n-1结点重新作调整,使之再次成为堆。这样,在根结点得到结点序列键值次最大值。依次类推,直到只有两个结点的堆,并对它们作交换,最后得到有序的n个结点序列。
O(nlogn)
O(nlogn)
O(1)
不稳定
归并排序
将两个或两个以上的有序子表合并成一个新的有序表。对于两个有序子表合并一个有序表的两路合并排序来说,初始时,把含n个结点的待排序序列看作有n个长度都为1的有序子表所组成,将它们依次两两合并得到长度为2的若干有序子表,再对它们作两两合并……直到得到长度为n的有序表,排序即告完成。
O(nlogn)
O(nlogn)
O(n)
稳定
后面根据各种排序算法,给出了C语言的实现,大家在复习的时候可以做下参考。
u 选择排序
void ss_sort(int e, int n)
{ int i, j, k, t;
for(i=0; i《 n-1; i++) {
for(k=i, j=i+1; j《n; j++)
if(e) k=j;
if(k!=i) {
t=e=t;
}
}
}
u 直接插入排序
void si_sort(int e, int n)
{ int i, j, t;
for(i=0; i《 n; i++) {
for(t=e; j--)
e;
e=t;
}
}
u 冒泡排序
void sb_sort(int e, int n)
{ int j, p, h, t;
for(h=n-1; h》0; h=p) {
for(p=j=0; j《h; j++)
if(e) {
t=e=t;
p=j;
}
}
}
u 希尔排序
void shell(int e, int n)
{ int j, k, h, y;
for(h=n/2; h》0; h=h/2)
for(j=h; j《n; j++) {
y=e;
for(k=j-h; k》0&&y《e; k-=h)
e;
e=y;
}
}
u 堆排序
void sift(e, n, s)
int e;
int n;
int s;
{ int t, k, j;
t=e;
k=s; j=2*k+1;
while(j《n) {
if(j《n-1&&e)
j++;
if(t《e) {
e;
k=j;
j=2*k+1;
}else break;
}
e=t;
}
void heapsorp (int e, int n)
{ int i, k, t;
for(i=n/2-1; i》=0; i--)
sift(e, n, i);
for(k=n-1; k》=1; k--) {
t=e=t;
sift(e, k, 0);
}
}
u 快速排序
void r_quick(int e, int low, int high)
{ int i, j, t;
if(low《high) {
i=low; j=high; t=e;
while(i《j) {
while (i《j&&e》t) j--;
if(i《j) e;
while (i《j&&e《=t) i++;
if(I《j) e;
}
e=t;
r_quick(e,low,i-1);
r_quick(w,i+1,high);
}
}
另外,外排序是对大型文件的排序,待排序的记录存储在外存中,在排序过程中,内存只存储文件的一部分记录,整个排序过程需进行多次的内外存间的交换。
*** 查找
查找就是在按某种数据结构形式存储的数据集合中,找出满足指定条件的结点。
按查找的条件分类,有按结点的关键码查找、关键码以外的其他数据项查找或其他数据项的组合查找等。按查找数据在内存或外存,分内存查找和外存查找。按查找目的,查找如果只是为了确定指定条件的结点存在与否,成为静态查找;查找是为确定结点的插入位置或为了删除找到的结点,称为动态查找。
这里简单介绍几种常见的查找方法。
u 顺序存储线性表的查找
这是最常见的查找方式。结点集合按线性表组织,采用顺序存储方式,结点只含关键码,并且是整数。如果线性表无序,则采用顺序查找,即从线性表的一端开始逐一查找。而如果线性表有序,则可以使用顺序查找、二分法查找或插值查找。
u 分块查找
分块查找的过程分两步,先用二分法在索引表中查索引项,确定要查的结点在哪一块。然后,再在相应块内顺序查找。
u 链接存储线性表的查找
对于链接存储线性表的查找只能从链表的首结点开始顺序查找。同样对于无序的链表和有序的链表查找方法不同。
u 散列表的查找
散列表又称杂凑表,是一种非常实用的查找技术。它的原理是在结点的存储位置和它的关键码间建立一个确定的关系,从而让查找码直接利用这个关系确定结点的位置。其技术的关键在于解决两个问题。
I. 找一个好的散列函数

更多文章:
form表单制作(为什么制作的form表单会在网页显示中多出一行)
2026年10月11日 09:10
teammate(teammate,company,partner)
2026年10月11日 06:10
javascript arraybuffer(javascript可以把base64编码转换成二进制代码吗求示例代码!)
2026年10月11日 04:00
text函数公式(excel中round和text函数的区别是什么)
2026年10月11日 03:50
google chrome打不开(chrome浏览器打不开怎么回事 浏览器打不开的处理方法)
2026年10月11日 02:00
websocket整合springboot(Springboot整合Websocket遇到的坑)
2026年10月11日 01:40
drawerlayout(android 怎样让drawerlayout设置的侧滑菜单的内容充满屏幕)
2026年10月10日 19:20
xor四位数怎么运算(单片机怎样用C语言实现4个数字间的异或)
2026年10月10日 17:50


