Java常见面试题及答案.docx
- 文档编号:4289624
- 上传时间:2022-11-28
- 格式:DOCX
- 页数:13
- 大小:32.15KB
Java常见面试题及答案.docx
《Java常见面试题及答案.docx》由会员分享,可在线阅读,更多相关《Java常见面试题及答案.docx(13页珍藏版)》请在冰豆网上搜索。
Java常见面试题及答案
1、面向对象的特征有哪些方面?
答:
面向对象的特征主要有以下儿个方面:
1)抽象:
抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。
抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
2)继承:
继承是从已有类得到继承信息创建新类的过程。
提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。
继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段(如果不能理解请阅读阎宏博士的《Java与模式》或《设计模式精解》中关于桥梁模式的部分)。
3)封装:
通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。
面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。
我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。
可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机的差别,明显全自动洗衣机封装更好因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为儿个按键就搞定了所有的事情)。
4)多态性:
多态性是指允许不同子类型的对象对同一消息作出不同的响应。
简单的说就是用同样的对象引用调用同样的方法但是做了不同的事悄。
多态性分为编译时的多态性和运行时的多态性。
如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:
当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,但一切对A系统来说都是透明的(就像电动剃须刀是A系统,它的供电系统是B系统,B系统可以使用电池供电或者用交流电,其至还有可能是太阳能,A系统只会通过B类对象调用供电的方法,但并不知道供电系统的底层实现是什么,究竟通过何种方式获得了动力)。
方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写
(override)实现的是运行时的多态性(也称为后绑定)。
运行时的多态是面向对象最精SI的东西,要实现多态需要做两件事:
1.方法《写(子类继承父类并重写父类中已有的或抽象的方法);2,对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。
2、String是最基本的数据类型吗?
type)。
答:
不是。
Java中的基本数据类型只有8个Jbyte、short、int、long、float、double>char、boolean:
除了基本类型(primitivetype)和枚举类型(enumerationtype),剩下的都是引用类型(reference
+=1;有错吗?
因此S1+1运算结
3、shortsi=1:
si=si+1;有错吗?
shortsi=1:
si答:
对于shortsi=1;si=si+1;山于1是int类型,果也是int型,需要强制转换类型才能赋值给short型。
而shortsi=1:
sl+=1;可以正确编译,因为S1+二1;相当于S1=(short)(S1+1);其中有隐含的强制类型转换。
4、int和Integer有什么区别?
答:
Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入不是对象的基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型Wrapperclass),int的包装类就是Integer,从JDK1.5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。
boolean,charsbyte,short»int,long,float,doubleBoolean,Character»Byte,Short,IntegersLong,Float,
Java为每个原始类型提供了包装类型:
原始类型:
包装类型:
Double
最近还遇到一个面试题,也是和自动装箱和拆箱相关的,代码如下
补充:
所示:
如果不明就里很容易认为两个输出要么都是true要么都是false。
首先需要注意的是fl、f2、f3、f4四个变量都是Integer对象,所以下面的=运算比较的不是值而是引用。
装箱的本质是什么呢?
当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,如果看看valueOf的源代码就知道发生了什么。
简单的说,如果字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象,所以上面的面试题中fl==f2的结果是true,而f3=f4的结果是false。
越是貌似简单的面试题其中的玄机就越多,需要面试者有相当深疗的功力。
5、解释内存中的栈(stack)、堆(heap)和静态存储区的用法。
答:
通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;而通过new关键字和构造器创建的对象放在堆空间:
程序中的字面量(literal)如直接书写的100、“hello”和常ft都是放在静态存储区中。
栈空间操作最快但是也很小,通常大量的对象都是放在堆空间,整个内存包括硬盘上的虚拟内存都可以被当成堆空间来使用。
Stringstr=newString("hello”);
上面的语句中str放在栈上,用new创建出来的字符吊对象放在堆上,而“hello”这个字面量放在静态存储区。
补充:
较新版本的Java中使用了一项叫“逃逸分析“的技术,可以将一些局部对象放在栈上以提升对象的操作性能。
6、swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
答:
早期的JDK中,switch(expr)中,expr可以是byte、shortxcharainto从1.5版开始,Java中引入了枚举类型(enum),expr也可以是枚举,从JDK1.7版开始,还可以是字符宙(String)。
长整型(long)是不可以的。
7、数组有没有length0方法?
String有没有length()方法?
答:
数组没有length0方法,有length的属性。
String有length()方法。
JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和
Java混淆。
8、构造器(constructor)是否可被重写(override)?
答:
构造器不能被继承,因此不能被重写,但可以被重载。
9、是否可以继承String类?
答:
String类是final类,不可以被继承。
补充:
继承String本身就是一个错误的行为,对String类型最好的重用方式是关联(HAS-A)而不是继承(IS-
10、String和StringBuilder^StringBuffer的区别?
答:
Java平台提供了两种类型的字符吊:
String和StringBuffer/StringBuilder,它们可以储存和操作字符串。
其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。
而StringBuffer和StringBuiIder类表示的字符串对象可以直接进行修改©StringBuiIder是JDK1.5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer略高©
补充1:
有一个面试题问:
有没有哪种悄况用+做字符吊连接比调用StringBuffer/StringBuiIder对象的append方法性能更好?
如果连接后得到的字符串在静态存储区中是早已存在的,那么用+做字符串连接是优于StringBuffer/StringBuiIder的append方法的。
补充2:
下面也是一个面试题,问程序的输出,看看自己能不能说出正确答案。
11、描述一下JVM加载class文件的原理机制?
答:
JVM中类的装载是山类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时査找和装入类文件中的类。
补充:
1•山于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。
当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。
类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。
加载完成后,Class对象还不完整,所以此时的类还不可用。
当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。
最后JVM对类进行初始化,包括:
1如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;2如果类中存在初始化语句,就依次执行这些初始化语句。
2•类的加载是山类加载器完成的,类加载器包括:
根加载器(Bootstrap)、扩展加载器(Extension),系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类九从JDK1.2开始,类加载过程采取了父亲委托机制(PDM)。
PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。
类的加载首先请求父类加载器加载,父类加载器无能为力时才山其子类加载器自行加载。
JVM不会向Java程序提供对Bootstrap的引用。
下面是关于儿个类加载器的说明:
a)Bootstrap:
一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);
b)Extension:
从java.ext.dirs系统属性所指定的U录中加载类库,它的父加载器是Bootstrap;
C)System:
乂叫应用类加载器,其父类是Extension。
它是应用最广泛的类加载器。
它从环境变量classpath或者系统属性java,class,path所指定的U录中记载类,是用户自定义加载器的默认父加载器。
12、抽象类(abstractclass)和接口(interface)有什么异同?
答:
抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。
一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。
接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部都是抽象方法。
抽象类中的成员可以是private^默认、protected^public的,而接口中的成员全都是public的。
抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。
有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法。
13、Java中会存在内存泄漏吗,请简单描述。
答:
理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因):
然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收也会发生内存泄露。
一个例子就是Hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象。
下面的例子也展示了Java中发生内存泄露的悄况:
上面的代码实现了一个栈(先进后出(FIL0))结构,乍看之下似乎没有什么明显的问题,它其至可以通过你编写的各种单元测试。
然而其中的pop方法却存在内存泄露的问题,当我们用pop方法弹出栈中的对象时,该对象不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,因为栈内部维护着对这些对象的过期引用
(obsoletereference)o在支持垃圾回收的语言中,内存泄露是很隐蔽的,这种内存泄露其实就是无意识的对象保持。
如果一个对象引用被无意识的保留起来了,那么垃圾回收器不会处理这个对象,也不会处理该对象引用的其他对象,即使这样的对象只有少数儿个,也可能会导致很多的对象被排除在垃圾回收之外,从而对性能造成重大影响,极端悄况下会引发DiskPaging(物理内存与硬盘的虚拟内存交换数据),其至造成OutOfMemoryErroro
14、静态变量和实例变量的区别?
答:
静态变ft是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。
静态变量可以实现让多个对象共学内存。
在Java开发中,上下文类和工具类中通常会有大量的静态成员。
15、如何实现对象克隆?
答:
有两种方式:
1.实现Cloneable接口并車写Object类中的clone()方法;
2•实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下。
注意:
基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。
16、
答:
17、
制?
Strings=newString("xyz”);创建了儿个字符吊对象?
两个对象,一个是静态存储区的"xyz",—个是用new创建在堆上的对象。
一个java”源文件中是否可以包含多个类(不是内部类)?
有什么限
答:
可以,但一个源文件中最多只能有一个公开类(publicclass)而且文件名必须和公开类的类名完全保持一致。
18、内部类可以引用它的包含类(外部类)的成员吗?
有没有什么限制?
答:
一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
19、指出下面程序的运行结果:
答:
执行结果:
Ia2b2bo创建对象时构造器的调用顺序是:
先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。
20、如何实现字符串的反转及替换?
答:
方法很多,可以自己写实现也可以使用String或StringBuffer/StringBuiIder中的方法。
有一道很常见的面试题是用递归实现字符吊反转。
21、日期和时间:
1)如何取得年月日、小时分钟秒?
2)如何取得从1970年1月1日0时0分0秒到现在的毫秒数?
3)如何取得某月的最后一天?
4)如何格式化日期?
答:
操作方法如下所示:
1)创建java.util.Calendar实例,调用其get()方法传入不同的参数即可获得参数所对应的值
2)以下方法均可获得该毫秒数:
3)示例代码如下:
4)利用java.text.DataFormat的子类(如Simp1eDateFormat类)中的format(Date)方法可将日期格式化。
22、比较一下Java和JavaSciprto
答:
JavaScript与Java是两个公司开发的不同的两个产品。
Java是原Sun公司推出的面向对象的程序设计语言,特别适合于互联网应用程序开发:
而JavaScript是Netscape公司的产品,为了扩展Netscape浏览器的功能而开发的一种可以嵌入Web页面中运行的基于对象和事件驱动的解释性语言,它的前身是LiveScript;而Java的前身是Oak语言。
下面对两种语言间的异同作如下比较:
1)基于对象和面向对象:
Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。
它是一种基于对象(Object-Based)和事件驱动(Event-Driven)的编程语言。
因而它本身提供了非常丰S的内部对象供设计人员使用;
2)解释和编译:
Java的源代码在执行之询,必须经过编译;JavaScript是一种解释性编程语言,其源代码不需经过编译,山浏览器解释执行;
3)强类型变量和类型弱变量:
采用强类型变量检査,即所有变量在编译之前必须作声明:
JavaScript中变量声明,釆用其弱类型。
即变量在使用前不需作声明,而是解释器在运行时检查其数据类型;
4)代码格式不一样。
补充:
上面列出的四点是原来所谓的标准答案中给出的。
其实Java和JavaScript最重要的区别是一个是静态语言,一个是动态语言。
U询的编程语言的发展趋势是函数式语言和动态语言。
在Java中类(class)是一等公民,而JavaScript中函数(function)是一等公民。
对于这种问题,在面试时还是用自己的语言回答会更加靠谱。
23、Error和Exception有什么区别?
答:
Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的悄况:
Exception表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的悄况。
补充:
2005年摩托罗竝的面试中曾经问过这么一个问题Tfaprocessreportsastackoverflowrun-timeerror,whatsthemostpossiblecause?
",给了四个选项a.lackofmemory;b.writeonaninvalidmemoryspace:
c.recursivefunctioncalling:
d.arrayindexoutofboundary.Java程序在运行时也可能会遭遇StackOverflowError»这是一个错误无法恢复,只能重新修改代码了,这个面试题的答案是6如果写了不能迅速收敛的递归,则很有可能引发栈溢出的错误,如下所示:
因此,用递归编写程序时一定要牢记两点:
1.递归公式;2.收敛条件(什么时候就不再递归而是回溯了)。
24、Java语言如何进行异常处理,关键字:
throws>throw、try、catch、finally分别如何使用?
答:
Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了ft好的接口。
在Java中,每个异常都是一个对象,它是Throwable类或其子类的实例。
当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。
Java的异常处理是通过5个关键词来实现的:
try、catch、throw、throws和
try
finally。
一般悄况下是用try来执行一段程序,如果出现异常,系统会抛出(throw)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)lli缺省处理器来处理;try用来指定一块预防所有“异常”的程序;catch子句紧跟在try块后面,用来指定你想要捕捉的“异常”的类型;throw语句用来明确地抛出一个“异常”;throws用来标明一个成员函数可能抛出的各种“异常”;finally为确保一段代码不管发生什么“异常”都被执行一段代码;可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。
每当遇到一个try语句,“异常”的框架就放到栈上面,直到所有的try语句都完成。
如果下一级的try语句没有对某种“异常”进行处理,栈就会展开,直到遇到有处理这种“异常”的语句。
final,finally,finalize的区别?
final:
修饰符(关键字)有三种用法:
如果一个类被声明为final,意味
25、答:
着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。
将变量声明为final,可以保证它们在使用中不被改变,被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。
被声明为final的方法也同样只能使用,不能在子类中被重写。
finally:
通常放在try…catch的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。
finalize:
Object类中定义的方法,Java中允许使用finalize0方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
这个方法是山垃圾收集器在销毁对象时调用的,通过重写finalize。
方法可以整理系统资源或者执行其他清理工作。
VM内存可简单分为三个区:
1、堆区(heap):
用于存放所有对象,是线程共享的(注:
数组也属于对象)
2、栈区(stack):
用于存放基本数据类型的数据和对象的引用,是线程私有的(分为:
虚拟机栈和本地方法栈)
3、方法区(method):
用于存放类信息、常量、静态变量、编译后的字节码等,是线程共享的(也被称为非堆,即None-Heap)Java的垃圾回收器(GC)主要针对堆区。
26、如何停止一个正在运行的线程
1、使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
2、使用stop方法强行终止,但是不推荐这个方法,因为stop和suspend及resume—样都是过期作废的方法。
3、使用interrupt方法中断线程。
27、notify()和notifyAlK)有什么区别?
notify可能会导致死锁,而notifyAll则不会任何时候只有一个线程可以获得锁,也就是说只有一个线程可以运行synchronized中的代码使用notifyall.可以唤醒所有处于wait状态的线程,使其重新进入锁的争夺队列中,而notify只能唤醒一个。
wait0应配合while循环使用,不应使用if,务必在wait()调用前后都检査条件,如果不满足,必须调用notify0唤醒另外的线程来处理,自己继续wait0直至条件满足再往下执行。
28、sleep()和wait()有什么区别?
对于sleep0方法,我们首先要知道该方法是属于Thread类中的。
而wait0方法,则是属于Object类中的。
sleep0方法导致了程序暂停执行指定的时间,让dlcpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了乂会自动恢复运行状态。
在调用sleep0方法的过程中,线程不会释放对象锁。
当调用waitO方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify0方法后本线程才进入对象锁定池准备,获取对象锁进入运行状态。
29、Thread类中的start()和run()方法有什么区别?
start0方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用runO方法的效果不一样。
当你调用runO方法的时候,只会是在原来的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java 常见 试题 答案