尚学堂JavaSE面试题参考答案.docx
- 文档编号:5938307
- 上传时间:2023-05-09
- 格式:DOCX
- 页数:47
- 大小:1.63MB
尚学堂JavaSE面试题参考答案.docx
《尚学堂JavaSE面试题参考答案.docx》由会员分享,可在线阅读,更多相关《尚学堂JavaSE面试题参考答案.docx(47页珍藏版)》请在冰点文库上搜索。
尚学堂JavaSE面试题参考答案
JavaSE面试题总结
第一章JavaSE基础
1.Java的跨平台原理(字节码文件、虚拟机)
a)C/C++语言都直接编译成针对特定平台的机器码。
如果要跨平台,需要使用相应的编译器重新编译。
b)Java源程序(.java)要先编译成与平台无关的字节码文件(.class),然后字节码文件再解释成机器码运行。
解释是通过Java虚拟机来执行的。
c)字节码文件不面向任何具体平台,只面向虚拟机。
d)Java虚拟机是可运行Java字节码文件的虚拟计算机。
不同平台的虚拟机是不同的,但它们都提供了相同的接口。
e)Java语言具有一次编译,到处运行的特点。
就是说编译后的.class可以跨平台运行,前提是该平台具有相应的Java虚拟机。
但是性能比C/C++要低。
f)Java的跨平台原理决定了其性能没有C/C++高
2.简述Java的垃圾回收机制
a)传统的C/C++语言,需要程序员负责回收已经分配内存。
显式回收垃圾回收的缺点:
i.程序忘记及时回收,从而导致内存泄露,降低系统性能。
ii.程序错误回收程序核心类库的内存,导致系统崩溃。
b)Java语言不需要程序员直接控制内存回收,是由JRE在后台自动回收不再使用的内存,称为垃圾回收机制。
i.可以提高编程效率。
ii.保护程序的完整性。
iii.其开销影响性能。
Java虚拟机必须跟踪程序中有用的对象,确定哪些是无用的。
c)垃圾回收机制的特点
i.垃圾回收机制回收JVM堆内存里的对象空间,不负责回收栈内存数据。
ii.对其他物理连接,比如数据库连接、输入流输出流、Socket连接无能为力。
iii.垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行。
iv.可以将对象的引用变量设置为null,暗示垃圾回收机制可以回收该对象。
v.现在的JVM有多种垃圾回收实现算法,表现各异。
vi.垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)。
vii.程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否进行垃圾回收依然不确定。
viii.永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。
3.类和对象的关系
类是对象的抽象,而对象是类的具体实例。
类是抽象的,不占用内存,而对象是具体的,占用存储空间。
类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。
类和对象好比图纸和实物的关系,模具和铸件的关系。
比如人类就是一个概念,人类具有身高,体重等属性。
人类可以做吃饭、说话等方法。
小明就是一个具体的人,也就是实例,他的属性是具体的身高200cm,体重180kg,他做的方法是具体的吃了一碗白米饭,说了“12345”这样一句话。
4.面向过程和面向对象的区别
两者都是软件开发思想,先有面向过程,后有面向对象。
在大型项目中,针对面向过程的不足推出了面向对象开发思想。
比喻
蒋介石和毛泽东分别是面向过程和面向对象的杰出代表,这样充分说明,在解决复制问题时,面向对象有更大的优越性。
面向过程是蛋炒饭,面向对象是盖浇饭。
盖浇饭的好处就是“菜”“饭”分离,从而提高了制作盖浇饭的灵活性。
饭不满意就换饭,菜不满意换菜。
用软件工程的专业术语就是“可维护性”比较好,“饭”和“菜”的耦合度比较低。
区别
1.编程思路不同:
面向过程以实现功能的函数开发为主,而面向对象要首先抽象出类、属性及其方法,然后通过实例化类、执行方法来完成功能。
2.封装性:
都具有封装性,但是面向过程是封装的是功能,而面向对象封装的是数据和功能。
3.面向对象具有继承性和多态性,而面向过程没有继承性和多态性,所以面向对象优势是明显。
5.private/默认/protected/public权限修饰符的区别
访问控制
public
protected
默认
private
同一类中成员
是
是
是
是
同一包中其它类
是
是
是
不同包中的子类
是
是
不同包中对非子类
是
类的访问权限只有两种
public公共的可被同一项目中所有的类访问。
(必须与文件名同名)
default默认的可被同一个包中的类访问。
成员(成员变量或成员方法)访问权限共有四种:
public公共的可以被项目中所有的类访问。
(项目可见性)
protected受保护的可以被这个类本身访问;同一个包中的所有其他的类访问;被它的子类(同一个包以及不同包中的子类)访问。
(子类可见性)
default默认的被这个类本身访问;被同一个包中的类访问。
(包可见性)
private私有的只能被这个类本身访问。
(类可见性)
6.方法重载和方法重写(覆盖)的区别
英文
位置不同
修饰符
返回值
方法名
参数
抛出异常
方法体
重载
overload
同一个类中
无关
无关
相同
不同
无关
不同
重写
override
子类和父类间
大于等于
小于等于
相同
相同
小于等于
不同
7.this和super关键字的作用
this是对象内部指代自身的引用
Øthis可以调用成员变量,通常用于解决成员变量和局部变量同名冲突
Øthis可以调用成员方法
Øthis可以在构造方法中调用重载的构造方法,且必须是构造方法的第一条语句。
super代表对当前对象的直接父类对象的引用
1.super可以调用直接父类的成员变量(注意权限修饰符的影响,比如不能访问private成员)
2.super可以调用直接父类的成员方法(注意权限修饰符的影响,比如不能访问private成员)
3.super可以调用直接父类的构造方法,只限构造方法中使用,且必须是第一条语句。
8.static关键字的作用(修饰变量、方法、代码块)
static可以修饰变量、方法和代码块
1.static属性属于这个类所有,即由该类创建的所有对象共享同一个static属性。
可以对象创建后通过对象名.属性名和类名.属性名两种方式来访问。
也可以在没有创建任何对象之前通过类名.属性名的方式来访问。
.static变量和非static变量的区别(都是成员变量,不是局部变量)
1.在内存中份数不同
不管有多少个对象,static变量只有1份。
对于每个对象,实例变量都会有单独的一份
static变量是属于整个类的,也称为类变量。
而非静态变量是属于对象的,也称为实例变量
2.在内存中存放的位置不同
静态变量存在方法区中,实例变量存在堆内存中*
3.访问的方式不同
实例变量:
对象名.变量名stu1.name="小明明";
静态变量:
对象名.变量名stu1.schoolName="西二旗小学";不推荐如此使用
类名.变量名Student.schoolName="东三旗小学";推荐使用
4.在内存中分配空间的时间不同
实例变量:
创建对象的时候才分配了空间。
静态变量:
第一次使用类的时候
Student.schoolName="东三旗小学";或者Studentstu1=newStudent("小明","男",20,98);
2.static方法也可以通过对象名.方法名和类名.方法名两种方式来访问
3.static代码块。
当类被第一次使用时(可能是调用static属性和方法,或者创建其对象)执行静态代码块,且只被执行一次,主要作用是实现static属性的初始化。
9.final和abstract关键字的作用
final和abstract是功能相反的两个关键字,可以对比记忆
Øabstract可以用来修饰类和方法,不能用来修饰属性和构造方法;使用abstract修饰的类是抽象类,需要被继承,使用abstract修饰的方法是抽象方法,需要子类被重写。
Øfinal可以用来修饰类、方法和属性,不能修饰构造方法。
使用final修饰的类不能被继承,使用final修饰的方法不能被重写,使用final修饰的变量的值不能被修改,所以就成了常量。
Ø特别注意:
final修饰基本类型变量,其值不能改变。
但是final修饰引用类型变量,栈内存中的引用不能改变,但是所指向的堆内存中的对象的属性值仍旧可以改变。
例如
classTest{
publicstaticvoidmain(String[]args){
finalDogdog=newDog("欧欧");
dog.name="美美";//正确
dog=newDog("亚亚");//错误
}
}
10.final、finally、finalize的区别
1.final修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。
将变量或方法声明为final,可以保证它们在使用中不被改变。
被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。
被声明为final的方法也同样只能使用,不能重载。
2.finally在异常处理时提供finally块来执行任何清除操作。
如果有finally的话,则不管是否发生异常,finally语句都会被执行。
3.finalize方法名。
Java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
finalize()方法是在垃圾收集器删除对象之前被调用的。
它是在Object类中定义的,因此所有的类都继承了它。
子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。
11.写出java.lang.Object类的六个常用方法
1.publicbooleanequals(java.lang.Object)比较内容
2.publicnativeinthashCode()哈希码
3.publicjava.lang.StringtoString()变成字符串
4.publicfinalnativejava.lang.ClassgetClass()获取类结构信息
5.protectedvoidfinalize()throwsjava.lang.Throwable垃圾回收前执行的方法
6.protectednativeObjectclone()throwsjava.lang.CloneNotSupportedException克隆
7.publicfinalvoidwait()throwsjava.lang.InterruptedException多线程中等待功能
8.publicfinalnativevoidnotify()多线程中唤醒功能
9.publicfinalnativevoidnotifyAll()多线程中唤醒所有等待线程的功能
12.继承条件下构造方法的执行过程
继承条件下构造方法的调用规则如下:
Ø如果子类的构造方法中没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。
在这种情况下,写不写“super();”语句,效果是一样的。
Ø如果子类的构造方法中通过super显式调用父类的有参构造方法,那将执行父类相应构造方法,而不执行父类无参构造方法。
Ø如果子类的构造方法中通过this显式调用自身的其他构造方法,在相应构造方法中应用以上两条规则。
Ø特别注意的是,如果存在多级继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直到执行顶级父类Object类的无参构造方法为止。
13.多态的技能点(前提条件,向上转型、向下转型)
实现多态的三个条件
1.继承的存在;(继承是多态的基础,没有继承就没有多态)
2.子类重写父类的方法。
(多态下会调用子类重写后的方法)
3.父类引用变量指向子类对象。
(涉及子类到父类的类型转换)
向上转型Studentperson=newStudent()
1.将一个父类的引用指向一个子类对象,成为向上转型,自动进行类型转换。
2.此时通过父类引用变量调用的方法是子类覆盖或继承父类的方法,而不是父类的方法
3.此时通过父类引用变量无法调用子类特有的方法
向下转型Studentstu=(Student)person;
1.将一个指向子类对象的引用赋给一个子类的引用,成为向下转型,此时必须进行强制类型转换。
2.向下转型必须转换为父类引用指向的真实子类类型,,否则将出现ClassCastException,不是任意的强制转换
3.向下转型时可以结合使用instanceof运算符进行强制类型转换,比如出现转换异常。
14.接口和抽象类的异同之处
相同点
Ø抽象类和接口均包含抽象方法,类必须实现所有的抽象方法,否则是抽象类
Ø抽象类和接口都不能实例化,他们位于继承树的顶端,用来被其他类继承和实现
两者的区别主要体现在两方面:
语法方面和设计理念方面
语法方面的区别是比较低层次的,非本质的,主要表现在:
Ø接口中只能定义全局静态常量,不能定义变量。
抽象类中可以定义常量和变量。
Ø接口中所有的方法都是全局抽象方法。
抽象类中可以有0个、1个或多个,甚至全部都是抽象方法。
Ø抽象类中可以有构造方法,但不能用来实例化,而在子类实例化是执行,完成属于抽象类的初始化操作。
接口中不能定义构造方法。
Ø一个类只能有一个直接父类(可以是抽象类),但可以充实实现多个接口。
一个类使用extends来继承抽象类,使用implements来实现接口。
二者的主要区别还是在设计理念上,其决定了某些情况下到底使用抽象类还是接口。
Ø抽象类体现了一种继承关系,目的是复用代码,抽象类中定义了各个子类的相同代码,可以认为父类是一个实现了部分功能的“中间产品”,而子类是“最终产品”。
父类和子类之间必须存在“is-a”的关系,即父类和子类在概念本质上应该是相同的。
Ø接口并不要求实现类和接口在概念本质上一致的,仅仅是实现了接口定义的约定或者能力而已。
接口定义了“做什么”,而实现类负责完成“怎么做”,体现了功能(规范)和实现分离的原则。
接口和实现之间可以认为是一种“has-a的关系”
15.String、StringBuffer、StringBuilder区别与联系
1.String类是不可变类,即一旦一个String对象被创建后,包含在这个对象中的字符序列是不可改变的,直至这个对象销毁。
2.StringBuffer类则代表一个字符序列可变的字符串,可以通过append、insert、reverse、setChartAt、setLength等方法改变其内容。
一旦生成了最终的字符串,调用toString方法将其转变为String
3.JDK1.5新增了一个StringBuilder类,与StringBuffer相似,构造方法和方法基本相同。
不同是StringBuffer是线程安全的,而StringBuilder是线程不安全的,所以性能略高。
通常情况下,创建一个内容可变的字符串,应该优先考虑使用StringBuilder
16.==和equals的区别和联系
==:
a)基本类型,比较的是值
b)引用类型,比较的是地址
c)不能比较没有父子关系的两个对象
equals()
a)系统类一般已经覆盖了equals(),比较的是内容。
b)用户自定义类如果没有覆盖equals(),将调用父类的equals(比如是Object),而Object的equals的比较是地址(return(this==obj);)
c)用户自定义类需要覆盖父类的equals()
注意:
Object的==和equals比较的都是地址,作用相同
17.String类型是基本数据类型吗?
基本数据类型有哪些
基本数据类型包括byte、int、char、long、float、double、boolean和short。
java.lang.String类是引用数据类型,并且是final类型的,因此不可以继承这个类、不能修改这个类。
为了提高效率节省空间,我们应该用StringBuffer类
18.String s="Hello";s=s+"world!
";执行后,原始String内容是否改变?
没有。
因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。
在这段代码中,s原先指向一个String对象,内容是"Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?
答案是没有。
这时,s不指向原来那个对象了,而指向了另一个String对象,内容为"Hello world!
",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。
通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。
因为String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。
这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。
并且,这两种类的对象转换十分容易。
同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。
例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非
s = new String("Initial Value");
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。
也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实:
对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。
而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。
至于为什么要把String类设计成不可变类,是它的用途决定的。
其实不只String,很多Java标准类库中的类都是不可变的。
在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。
不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。
当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。
所以Java标准类库还提供了一个可变版本,即StringBuffer。
19.Strings=newString("xyz");创建了几个StringObject?
二者之间有什么区别?
两个或一个,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。
NewString每写一遍,就创建一个新的对象,它一句那个常量”xyz”对象的内容来创建出一个新String对象。
如果以前就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。
20.下面这条语句一共创建了多少个对象:
Strings="a"+"b"+"c"+"d";
答:
对于如下代码:
Strings1="a";
Strings2=s1+"b";
Strings3="a"+"b";
System.out.println(s2=="ab");
System.out.println(s3=="ab");
第一条语句打印的结果为false,第二条语句打印的结果为true,这说明javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。
题目中的第一行代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串,所以,上面的代码应该只创建了一个String对象。
写如下两行代码,
Strings="a"+"b"+"c"+"d";
System.out.println(s=="abcd");
最终打印的结果应该为true。
21.&和&&的区别和联系,|和||的区别和联系
&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。
&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,例如,对于if(str!
=null&&!
str.equals(“”))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException如果将&&改为&,则会抛出NullPointerException异常。
If(x==33&++y>0)y会增长,If(x==33&&++y>0)不会增长
&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如,0x31&0x0f的结果为0x01。
备注:
这道题先说两者的共同点,再说出&&和&的特殊之处,并列举一些经典的例子来表明自己理解透彻深入、实际经验丰富。
22.用最有效率的方法算出2乘以8等于多少
使用位运算来实现效率最高,2乘以8相当于二进制位左移三位。
所以实现方式为2<<3
因为将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即可,而位运算cpu直接支持的,效率最高,所以,2乘以8等於几的最效率的方法是2<<3。
23.Error和Exception的区别
1.Error类,表示仅靠程序本身无法恢复的严重错误,比如说内存溢出、动态链接异常、虚拟机错误。
应用程序不应该抛出这种类型的对象。
假如出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。
所以在进行程序设计时,应该更关注Exception类。
2.Exception类,由Java应用程序抛出和处理的非严重错误,比如所需文件没有找到、零作除数,数组下标越界等。
它的各种不同子类分别对应不同类型异常。
可分为两类:
Checked异常和Runtime异常
24.Checked异常和Runtime异常的区别
1.运行时异常:
包括RuntimeaException及其所有子类。
不要求程序必须对它们作出处理,比如InputMismatchException、ArithmeticException、NullPointerException等。
即使没有使用try-catch或throws进行处理,仍旧可以进行编译和运行
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 学堂 JavaSE 试题 参考答案
![提示](https://static.bingdoc.com/images/bang_tan.gif)