尚学堂JavaSE面试题参考答案Word文档下载推荐.docx
《尚学堂JavaSE面试题参考答案Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《尚学堂JavaSE面试题参考答案Word文档下载推荐.docx(47页珍藏版)》请在冰点文库上搜索。
类和对象好比图纸和实物的关系,模具和铸件的关系。
比如人类就是一个概念,人类具有身高,体重等属性。
人类可以做吃饭、说话等方法。
小明就是一个具体的人,也就是实例,他的属性是具体的身高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对象,内容是"
,然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?
答案是没有。
这时,s不指向原来那个对象了,而指向了另一个String对象,内容为"
Hello
,原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。
通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。
因为String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。
这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。
并且,这两种类的对象转换十分容易。
同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。
例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:
public
class
Demo
{
private
String
s;
...
s
=
Initial
Value"
}
而非
new
String("
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为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="
Strings2=s1+"
Strings3="
+"
System.out.println(s2=="
ab"
System.out.println(s3=="
第一条语句打印的结果为false,第二条语句打印的结果为true,这说明javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。
题目中的第一行代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串,所以,上面的代码应该只创建了一个String对象。
写如下两行代码,
Strings="
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&
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进行处理,仍旧可以进行编译和运行