java面试题基础Word下载.docx
《java面试题基础Word下载.docx》由会员分享,可在线阅读,更多相关《java面试题基础Word下载.docx(59页珍藏版)》请在冰点文库上搜索。
s1+=1;
有错吗?
对于shorts1=1;
由于1是int类型,因此s1+1运算结果也是int型,需要强制转换类型才能赋值给short型。
而shorts1=1;
可以正确编译,因为s1+=1;
相当于s1=(short)(s1+1);
其中有隐含的强制类型转换。
6、Java有没有goto?
goto是Java中的保留字,在目前版本的Java中没有使用。
7、int和Integer的区别?
Integer是int提供的封装类,而int是Java的基本数据类型;
Integer默认值是null,而int默认值是0;
声明为Integer的变量需要实例化,而声明为int的变量不需要实例化;
Integer是对象,用一个引用指向这个对象,而int是基本类型,直接存储数值。
(如果整型字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象)
8、&
和&
&
的区别?
运算符有两种用法:
(1)按位与;
(2)逻辑与。
运算符是短路与运算。
逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true整个表达式的值才是true。
之所以称为短路运算是因为,如果&
左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。
9、解释内存中的栈(stack)、堆(heap)和静态区(staticarea)的用法。
通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;
而通过new关键字和构造器创建的对象放在堆空间;
程序中的字面量(literal)如直接书写的100、”hello”和常量都是放在静态区中。
栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,理论上整个内存没有被其他进程使用的空间甚至硬盘上的虚拟内存都可以被当成堆空间来使用。
实例:
Stringstr=newString(“hello”)
上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而”hello”这个字面量放在静态区。
补充:
较新版本的Java(从Java6的某个更新开始)中使用了一项叫”逃逸分析”的技术,可以将一些局部对象放在栈上以提升对象的操作性能。
10、Math.round(11.5)等于多少?
Math.round(-11.5)等于多少?
Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。
四舍五入的原理是在参数上加0.5然后进行下取整。
11、switch是否能作用在byte上,是否能作用在long上,是否能作用在String上?
在Java5以前,switch(expr)中,expr只能是byte、short、char、int。
从Java5开始,Java中引入了枚举类型,expr也可以是enum类型,从Java7开始,expr还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。
12、用最有效率的方法计算2乘以8?
2<
<
3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。
13、数组有没有length()方法?
String有没有length()方法?
数组没有length()方法,有length的属性。
String有length()方法。
JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。
14、在Java中,如何跳出当前的多重嵌套循环?
在最外层循环前加一个标记如A,然后用breakA;
可以跳出多重循环。
(Java中支持带标签的break和continue语句,作用有点类似于C和C++中的goto语句,但是就像要避免使用goto一样,应该避免使用带标签的break和continue,因为它不会让你的程序变得更优雅,很多时候甚至有相反的作用,所以这种语法其实不知道更好)
15、构造器(constructor)是否可被重写(override)?
构造器不能被继承,因此不能被重写,但可以被重载。
16、两个对象值相同(x.equals(y)==true),但却可有不同的hashcode,这句话对不对?
不对,如果两个对象x和y满足x.equals(y)==true,它们的哈希码(hashcode)应当相同。
Java对于eqauls方法和hashCode方法是这样规定的:
(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;
(2)如果两个对象的hashCode相同,它们并不一定相同。
当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在Set集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。
关于equals和hashCode方法,很多Java程序都知道,但很多人也就是仅仅知道而已,在JoshuaBloch的大作《EffectiveJava》(很多软件公司,《EffectiveJava》、《Java编程思想》以及《重构:
改善既有代码质量》是Java程序员必看书籍,如果你还没看过,那就赶紧去亚马逊买一本吧)中是这样介绍equals方法的:
首先equals方法必须满足自反性(x.equals(x)必须返回true)、对称性(x.equals(y)返回true时,y.equals(x)也必须返回true)、传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true)和一致性(当x和y引用的对象信息没有被修改时,多次调用x.equals(y)应该得到同样的返回值),而且对于任何非null值的引用x,x.equals(null)必须返回false。
实现高质量的equals方法的诀窍包括:
1.使用==操作符检查”参数是否为这个对象的引用”;
2.使用instanceof操作符检查”参数是否为正确的类型”;
3.对于类中的关键属性,检查参数传入对象的属性是否与之相匹配;
4.编写完equals方法后,问自己它是否满足对称性、传递性、一致性;
5.重写equals时总是要重写hashCode;
6.不要将equals方法参数中的Object对象替换为其他的类型,在重写时不要忘掉@Override注解。
17、是否可以继承String类?
String类是final类,不可以被继承。
继承String本身就是一个错误的行为,对String类型最好的重用方式是关联关系(Has-A)和依赖关系(Use-A)而不是继承关系(Is-A)。
18、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
是值传递。
Java语言的方法调用只支持参数的值传递。
当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。
对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。
19、String和StringBuilder、StringBuffer的区别?
String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。
StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改。
StringBuilder是Java5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer要高。
String对象的intern方法会得到字符串对象在常量池中对应的版本的引用(如果常量池中有一个字符串与String对象的equals结果是true),如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用。
20、重载(Overload)和重写(Override)的区别。
重载的方法能否根据返回类型进行区分?
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;
重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。
重载对返回类型没有特殊的要求。
21、描述一下JVM加载class文件的原理机制?
JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。
由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。
当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。
类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。
加载完成后,Class对象还不完整,所以此时的类还不可用。
当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。
最后JVM对类进行初始化,包括:
1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;
2)如果类中存在初始化语句,就依次执行这些初始化语句。
类的加载是由类加载器完成的,类加载器包括:
根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。
从Java2(JDK1.2)开始,类加载过程采取了父亲委托机制(PDM)。
PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。
类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。
JVM不会向Java程序提供对Bootstrap的引用。
下面是关于几个类加载器的说明:
Bootstrap:
一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);
Extension:
从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;
System:
又叫应用类加载器,其父类是Extension。
它是应用最广泛的类加载器。
它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。
22、char型变量中能不能存贮一个中文汉字,为什么?
char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个char类型占2个字节(16比特),所以放一个中文是没问题的。
使用Unicode意味着字符在JVM内部和外部有不同的表现形式,在JVM内部都是Unicode,当这个字符被从JVM内部转移到外部时(例如存入文件系统中),需要进行编码转换。
所以Java中有字节流和字符流,以及在字符流和字节流之间进行转换的转换流,如InputStreamReader和OutputStreamReader,这两个类是字节流和字符流之间的适配器类,承担了编码转换的任务;
对于C程序员来说,要完成这样的编码转换恐怕要依赖于union(联合体/共用体)共享内存的特征来实现了。
23、抽象类(abstractclass)和接口(interface)有什么异同?
相同点:
抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。
一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。
不同点:
接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部都是抽象方法。
抽象类中的成员可以是private、默认、protected、public的,而接口中的成员全都是public的。
抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。
有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法。
24、静态嵌套类(StaticNestedClass)和内部类(InnerClass)的不同?
StaticNestedClass是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。
而通常的内部类需要在外部类实例化后才能实例化
注意:
Java中非静态内部类对象的创建要依赖其外部类对象,上面的面试题中foo和main方法都是静态方法,静态方法中没有this,也就是说没有所谓的外部类对象,因此无法创建内部类对象,如果要在静态方法中创建内部类对象,可以这样做:
newOuter().newInner();
25、Java中会存在内存泄漏吗,请简单描述。
理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因);
然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致内存泄露的发生。
例如hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(close)或清空(flush)一级缓存就可能导致内存泄露。
26、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?
都不能。
抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。
本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。
synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。
27、阐述静态变量和实例变量的区别。
静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;
实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。
静态变量可以实现让多个对象共享内存。
在Java开发中,上下文类和工具类中通常会有大量的静态成员。
28、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。
29、如何实现对象克隆?
有两种方式:
1).实现Cloneable接口并重写Object类中的clone()方法;
2).实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。
让问题在编译的时候暴露出来总是优于把问题留到运行时。
30、GC是什么?
为什么要有GC?
GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。
Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。
要请求垃圾收集,可以调用下面的方法之一:
System.gc()或Runtime.getRuntime().gc(),但JVM可以屏蔽掉显示的垃圾回收调用。
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。
垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。
在Java诞生初期,垃圾回收是Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今Java的垃圾回收机制已经成为被诟病的东西。
移动智能终端用户通常觉得iOS的系统比Android系统有更好的用户体验,其中一个深层次的原因就在于Android系统中垃圾回收的不可预知性。
垃圾回收机制有很多种,包括:
分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。
标准的Java进程既有栈又有堆。
栈保存了原始型局部变量,堆保存了要创建的对象。
Java平台对堆内存回收和再利用的基本算法被称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。
这种方法会跟Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:
-伊甸园(Eden):
这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。
-幸存者乐园(Survivor):
从伊甸园幸存下来的对象会被挪到这里。
-终身颐养园(Tenured):
这是足够老的幸存对象的归宿。
年轻代收集(Minor-GC)过程是不会触及这个地方的。
当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。
与垃圾回收相关的JVM参数:
-Xms/-Xmx—堆的初始大小/堆的最大大小
-Xmn—堆中年轻代的大小
-XX:
-DisableExplicitGC—让System.gc()不产生任何作用
+PrintGCDetails—打印GC的细节
+PrintGCDateStamps—打印GC操作的时间戳
NewSize/XX:
MaxNewSize—设置新生代大小/新生代最大大小
NewRatio—可以设置老生代和新生代的比例
PrintTenuringDistribution—设置每次新生代GC后输出幸存者乐园中对象年龄的分布
InitialTenuringThreshold/-XX:
MaxTenuringThreshold:
设置老年代阀值的初始值和最大值
TargetSurvivorRatio:
设置幸存区的目标使用率
31、Strings=newString(“xyz”);
创建了几个字符串对象?
两个对象,一个是静态区的”xyz”,一个是用new创建在堆上的对象。
32、接口是否可继承(extends)接口?
抽象类是否可实现(implements)接口?
抽象类是否可继承具体类(concreteclass)?
接口可以继承接口,而且支持多重继承。
抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。
33、一个”.java”源文件中是否可以包含多个类(不是内部类)?
有什么限制?
可以,但一个源文件中最多只能有一个公开类(publicclass)而且文件名必须和公开类的类名完全保持一致。
34、AnonymousInnerClass(匿名内部类)是否可以继承其它类?
是否可以实现接口?
可以继承其他类或实现其他接口,在Swing编程和Android开发中常用此方式来实现事件监听和回调。
35、内部类可以引用它的包含类(外部类)的成员吗?
有没有什么限制?
一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
36、Java中的final关键字有哪些用法?
(1)修饰类:
表示该类不能被继承;
(2)修饰方法:
表示方法不能被重写;
(3)修饰变量:
表示变量只能一次赋值以后值不能被修改(常量)。
37、指出下面程序的运行结果。
classA{
static{
System.out.print("
1"
);
}
publicA(){
2"
}
classBextendsA{
a"
publicB(){
b"
publicclassHello{
publicstaticvoidmain(String[]args){
Aab=newB();
ab=newB();
执行结果:
1a2b2b。
创建对象时构造器的调用顺序是:
先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。
38、数据类型之间的转换:
-如何将字符串转换为基本数据类型?
-如何将基本数据类型转换为字符串?
调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;
一种方法是将基本数据类型与空字符串(”"
)连接(+)即可获得其所对应的字符串;
另一种方法是调用String类中的valueOf()方法返回相应字符串
39、如何实现字符串的反转及替换?
方法很多,可以自己写实现也可以使用String或StringBuffer/StringBuilder中的方法。
有一道很常见的面试题是用递归实现字符串反转,代码如下所示:
publics