Java技术面试常见问题.docx

上传人:b****8 文档编号:30286113 上传时间:2023-08-13 格式:DOCX 页数:85 大小:157.65KB
下载 相关 举报
Java技术面试常见问题.docx_第1页
第1页 / 共85页
Java技术面试常见问题.docx_第2页
第2页 / 共85页
Java技术面试常见问题.docx_第3页
第3页 / 共85页
Java技术面试常见问题.docx_第4页
第4页 / 共85页
Java技术面试常见问题.docx_第5页
第5页 / 共85页
点击查看更多>>
下载资源
资源描述

Java技术面试常见问题.docx

《Java技术面试常见问题.docx》由会员分享,可在线阅读,更多相关《Java技术面试常见问题.docx(85页珍藏版)》请在冰豆网上搜索。

Java技术面试常见问题.docx

Java技术面试常见问题

 

正文

数据结构:

用java代码实现链表?

(代码)

publicclassSortableLinkedList>extendsLinkedList

{

publicvoidaddinOrder(Etarget)

{

Predecessorprev=this;

ListNodenode=getNext();

while((node!

=null)&&(node.getitem().compareTo(target)<0)){

prev=node;

node=node.getNext();

}

prev.setNext(newListNode(target,node));

}

/*链表排序*/

publicvoidinsertSort(){

SortableLinkedListnewList=newSortableLinkedList();

for(Ee:

this){

newList.addinOrder(e);

}

setNext(newList.getNext());

}

publicstaticvoidmain(String[]args)

{

SortableLinkedListslist=newSortableLinkedList();

slist.add("3");

slist.add("5");

slist.add("2");

slist.insertSort();

System.out.println(slist);

}

}

用java代码实现基本的二叉树?

(代码)

publicclassTree{

publicNoderoot=newNode();

//树的节点类

privateclassNode{

privateNodeleft;

privateNoderight;

privateIntegerobject;

}

publicvoidadd(Integero){

if(root.object==null){

root.object=o;

return;

}

Nodenode=root;

while(node.object!

=null){

//小的在左边,大的在右边

if(pareTo(node.object)<=0){

if(node.left!

=null){

node=node.left;

}else{

node.left=newNode();

node=node.left;

}

}else{

if(node.right!

=null){

node=node.right;

}else{

node.right=newNode();

node=node.right;

}

}

}

node.object=o;

}

}

用java代码实现栈结构?

(代码)

publicclassStackX{

privateintmaxSize;//栈的队列大小

privatelong[]stackArray;

privateinttop=-1;//栈的顶部

/**

*初始化

*根据参数规定的容量创建一个新栈,栈的域包括表示最大容量的变量

*数组本身及变量top,它存储栈顶元素的下标

*/

publicStackX(ints){

maxSize=s;//setarraysize

this.stackArray=newlong[maxSize];//createarray

}

/**

*入栈

*将top值增加一,使它指向原顶端数据项上面的一个位置

*并在一个位置存储一个数据项

*/

publicvoidpush(longj){

this.stackArray[++top]=j;//takeitemfromtopofstack

}

/**

*出栈

*返回top标识的数据项值,然后top减一

*其效果是从栈中移除一个数据项

*/

publiclongpop(){

returnthis.stackArray[top--];//accessitem,decrementtop

}

/**

*返回位于栈top的值,但不做任何改动

*/

publiclongpeek(){

returnthis.stackArray[top];

}

/**

*判断是否空栈,栈空时top变量为-1

*/

publicbooleanisEmpty(){

returnthis.top==-1;

}

/**

*判断栈是否以满,栈满时top变量为maxSize-1

*/

publicbooleanisFull(){

returntop==this.maxSize-1;

}

}

测试类

publicclassStackApp{

publicstaticvoidmain(String[]args){

//初始化栈,设置栈的队列大小

StackXsx=newStackX(10);

//入栈

sx.push(100);

sx.push(200);

sx.push(300);

sx.push(400);

sx.push(500);

//判断是否为空栈

Stringtemp;

if(sx.isEmpty())

temp="空栈";

else

temp="非空栈";

System.out.println("sx栈为:

"+temp);

//打印顶栈

System.out.println("topofstack:

"+sx.peek());

//循环输出栈值

while(!

sx.isEmpty()){

longvalue=sx.pop();

System.out.println("出栈值为:

"+value);

}

}

}

算法:

各种排序的算法?

(代码)

冒泡排序:

//初始化变量

int[]data={12,8,3,59,132,1236,3400,8,352,37};

//是否打印排序后结果

//循环整个数组

for(inti=0;i

//循环每个数字

for(intj=0;j

if(data[j]>data[j+1]){

//将两个数字的位置进行对调

inttemp=data[j];

data[j]=data[j+1];

data[j+1]=temp;

}

}

for(intk=0;k

System.out.print(data[k]+"");

System.out.println();

}

插入排序:

int[]data=newint[]{12,8,3,59,132,1236,3400,8,352,37};

intin,out;

for(out=1;out

inttemp=data[out];

in=out;

while(in>0&&data[in-1]>=temp){

data[in]=data[in-1];

--in;

}

data[in]=temp;

}

选择排序:

int[]data=newint[]{12,8,3,59,132,1236,3400,8,352,37};

intminValue;

intindexMin;

inttemp;

for(inti=0;i

intlowIndex=i;

for(intj=data.length-1;j>i;j--){

if(data[j]

lowIndex=j;

}

}

temp=data[i];

data[i]=data[lowIndex];

data[lowIndex]=temp;

for(intk=0;k

System.out.print(data[k]+"");

System.out.println();

}

各种排序的优点和使用场合?

冒泡排序:

排序方法:

相邻两元素进行比较,如有需要则进行交换,每完成一次循环就将最大元素排在最后(如从小到大排序),下一次循环是将其他的数进行类似操作。

优点

–若数据已有部分排好序,则使用冒泡排序法可以很快的完成排序。

缺点

–会造成反复扫描数据,比较相邻的两个数据,速度不快也没有效率。

插入排序:

排序方法:

每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。

优点:

–最简单的排序

缺点

–比其他排序消耗时间多

选择排序:

排序方法:

将一个记录插入到已排好序的有序表(有可能是空表)中,从而得到一个新的记录数增1的有序表

优点

–利用一个一个的元素的插入比较,将元素放入适当的位置,也属于简单排序

缺点

–但是每次都与之前数据相比较,故耗费时间

递归算法的使用和使用场合

递归算法的使用

  递归过程一般通过函数或子过程来实现。

  递归算法:

在函数或子过程的内部,直接或者间接地调用自己的算法。

  递归算法的实质:

是把问题转化为规模缩小了的同类问题的子问题。

然后递归调用函数(或过程)来表示问题的解。

递归算法解决问题的特点:

  

(1)递归就是在过程或函数里调用自身。

  

(2)在使用递增归策略时,必须有一个明确的递归结束条件,称为递归出口。

  (3)递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。

所以一般不提倡用递归算法设计程序。

  (4)在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。

递归次数过多容易造成栈溢出等。

所以一般不提倡用递归算法设计程序。

案例分析:

●思考一下,13×4的答案是如何算出的呢,13×4是不是13连加四次呢?

那我们如何得到13还要连加几次呢?

何时停止呢?

●分析:

递归的实例

步骤1:

了解是否为适合用递归解题

步骤2:

决定递归的结束条件

步骤3:

决定递归执行部分

publicstaticintmul(inta,intb){

intresult;

if(b==1){//结束条件

result=a;

}else{//执行部分

result=a+mul(a,b-1);

}

returnresult;

}

模式:

设计模式的分类?

每种类型的作用?

设计模式可以分为三大类,分别是创建型设计模式、行为型设计模式以及结构型设计模式。

创建型的设计模式:

单例模式(Singleton)

构建模式(Builder)

原型模式(Prototype)

抽象工厂模式(AbstractFactory)

工厂方法模式(FactoryMethod)

行为设计模式:

策略模式(Strategy)

状态模式(State)

责任链模式(ChainofResponsibility)

解释器模式(Interpreter)

命令模式(Command)

观察者模式(Observer)

备忘录模式(Memento)

迭代器模式(Iterator)

模板方法模式(TemplateMethod)

访问者模式(Visitor)

中介者模式(Mediator)

结构型设计模式:

装饰者模式(Decorator)

代理模式(Proxy)

组合模式(Composite)

桥连接模式(Bridge)

适配器模式(Adapter)

蝇量模式(Flyweight)

外观模式(Facade)

===================================================================

各种模式的表述:

单例模式(Singleton):

确保有且只有一个对象被创建。

抽象工厂模式(AbstractFactory):

允许客户创建对象的家族,而无需指定他们的具体类。

工厂方法模式(FactoryMethod):

由子类决定要创建的具体类是哪一个。

装饰者模式(Decorator):

包装一个对象,以提供新的行为。

状态模式(State):

封装了基于状态的行为,并使用委托在行为之间切换。

迭代器模式(Iterator):

在对象的集合之中游走,而不暴露集合的实现。

外观模式(Facade):

简化一群类的接口。

策略模式(Strategy):

封装可以互换的行为,并使用委托来决定要使用哪一个。

代理模式(Proxy):

包装对象,以控制对此对象的访问。

适配器模式(Adapter):

封装对象,并提供不同的接口。

观察者模式(Observer):

让对象能够在状态改变时被通知。

模板方法模式(TemplateMethod):

有子类决定如何实现一个算法中的步骤。

组合模式(Composite):

客户用一致的方法处理对象集合和单个对象。

命令模式(Command):

封装请求成为对象。

什么是工厂模式?

在程序中如何使用?

工厂模式,也叫做说虚构造器,在简单工厂中间插入了一个具体产品工厂,这个工厂知道产品构造时候的具体细节,而简单工厂模式的产品具体构造细节是在一个个if/else分支,或者在switch/case分支里面的。

工厂模式的好处就在于将工厂和产品之间的耦合降低,将具体产品的构造过程放在了具体工厂类里面。

在以后扩展产品的时候方便很多,只需要添加一个工厂类,一个产品类,就能方便的添加产品,而不需要修改原有的代码。

而在简单工厂中,如果要增加一个产品,则需要修改工厂类,增加if/else分支,或者增加一个case分支,工厂模式符合软件开发中的OCP原则(opencloseprinciple),对扩展开放,对修改关闭。

什么是单例,多例模式?

在程序中如何使用?

1.谁给我讲讲在Java中什么是单例模式,它主要用在什么地方。

[此问题的推荐答案]比如调用连接数据库的时候

publicclassDBopen{

privateConnectionconn;

privatestaticDBopendb;

privateDBopen(){

conn=this.getConnection();

}

publicstaticDBopenopen(){

if(db==null){

db=newDBopen();

}

returndb;

}

其他类在生成DBopen对象的时候

DBopendb=DBopen.open();

这样保证只连接一次

2.我也说说:

单例模式就是只能创建一个实例,就是只能一个对象。

这个实例在全局被所有类都能调用。

publicclassSingleton{

privateSingleton(){

}

privatestaticSingletonS;

publicstaticSingletongetS(){

if(S==null){

S=newSingleton();

}

returnS;

}

}

3.java模式之单例模式:

单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例。

特点:

1,一个类只能有一个实例

2,自己创建这个实例

3,整个系统都要使用这个实例

例:

在下面的对象图中,有一个"单例对象",而"客户甲"、"客户乙"和"客户丙"是单例对象的三个客户对象。

可以看到,所有的客户对象共享一个单例对象。

而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。

在很多操作中,比如建立目录数据库连接都需要这样的单线程操作。

一些资源管理器常常设计成单例模式。

外部资源:

譬如每台计算机可以有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机中。

每台计算机可以有若干个通信端口,系统应当集中管理这些通信端口,以避免一个通信端口被两个请求同时调用。

内部资源,譬如,大多数的软件都有一个(甚至多个)属性文件存放系统配置。

这样的系统应当由一个对象来管理这些属性文件。

一个例子:

Windows回收站。

在整个视窗系统中,回收站只能有一个实例,整个系统都使用这个惟一的实例,而且回收站自行提供自己的实例。

因此,回收站是单例模式的应用。

两种形式:

1,饿汉式单例类

publicclassSingleton{

privateSingleton(){}

//在自己内部定义自己一个实例,是不是很奇怪?

//注意这是private只供内部调用

privatestaticSingletoninstance=newSingleton();

//这里提供了一个供外部访问本class的静态方法,可以直接访问

publicstaticSingletongetInstance(){

returninstance;

}

}

2,懒汉式单例类

publicclassSingleton{

privatestaticSingletoninstance=null;

publicstaticsynchronizedSingletongetInstance(){

//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次

//使用时生成实例,提高了效率!

if(instance==null)

instance=newSingleton();

returninstance;

}

}

第二中形式是lazyinitialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。

什么是适配器模式?

在程序中如何使用?

适配器是英语adapter的汉语翻译。

适配器可以是一个独立的硬件接口设备,也可以是信息接口。

比如:

电源适配器、三角架基座转接部件、USB与串口的转接设备等。

在实际开发过程中,我们经常遇到这样的事情,我们根据初步的需求制定了一个基类,在开发过程中才了解到详细的需求或者需求发生了变动。

而开发工作中的接口早已经定义完毕,并已经大规模投入编码。

此时若改动接口的定义会造成很多编码上重复性的修改工作,并进而有可能造成修改不完全而导致的语义错误或逻辑错误。

语义错误尚可以在编译阶段发现,而一旦发生逻辑性的错误,后果将会非常严重,甚至足以导致系统崩溃。

此时就需要用到适配器模式的设计方法。

适配器模式主要应用于,当接口里定义的方法无法满足客户的需求,或者说接口里定义的方法的名称或者方法界面与客户需求有冲突的情况。

适配器模式的使用方法:

用一个类同时继承接口和已知类,利用已知类中定义的方法和属性等,实现接口中的定义(主要利用了重载接口方法的办法)。

用此类作为其他业务类的基类,也就是这个类适配了接口和已知类。

若已知类发生变化,只需修改类适配器,就可以满足接口的实现。

适配器模式和代理模式是二个比较容易混淆的模式,我想谈一下这两个模式的差别,不过我先分别介绍一下这二个模式,然后再做比较,我想这样大家可能会比较容易理解,对于不懂这两个模式的人来说也多个了解的机会。

适配器说通俗点就是把一个东西包装一下变成另外一个东西,为什么要包装而不直接就用这个东西呢?

呵呵,如果能直接用就犯不着适配了,要适配当然就是由于某些原因你用不了当前这个东西。

最容易理解的就是电器的例子,比如你在中国买的电器使用电压是220V,结果你跑到国外去了,国外提供的电压是110V,问题就来了,你必须使用的是220V的,国外提供给你的却只有110V的,所以你根本就用不了,除非你能够将110V的转化成为220V才能行。

此时适配器就排上用场了,你使用一个转压器不就可以把110V专成220V了吗?

对于程序设计亦然。

下面举一个例子,假如你开始做一个项目的时候你需要写一个集合的枚举接口如下:

publicinterfaceEnumeration{

boolHasMoreElement();

objectnextElement();

}

调用的方法如下:

publicvoidBeforeDisplay(Enumeratione){

while(e.HasMoreElement()){

e.nextElement();

}

}

后来由于某一种原因(可能是代码重构、或者类库升级),你定义了另外一个新的集合枚举接口如下:

publicinterfaceIterator{

boolMoveNext();

objectCurrent();

voidReset();

}

使用新的接口调用方法如下:

publicvoidOldDisplay(Iteratore){

while(e.MoveNext()){

e.Current();

}

}

现在如果要求新的方法都只使用新的接口一切都很顺利,但是由于原来的很多方法用的仍然是旧的接口,而由于逻辑的重用或者为了升级后类库的向前兼容,你需要将当前的新接口Iterator转换成旧的接口Enumeration以调用原来的方法,这时候就需要我们写一个适配器。

如何编写适配器?

由于我们需要用的是Enumeration接口,所以适

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 中考

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1