0316 笔试题整理
前言
最近开始刷java笔试题了,于是将一些刷题过程中遇到的错题记录在博客里,以便日后回顾复习,如题目解释中有不足望各位大神批评指正!
1. 代码String str=”123456a”;int i=Integer.parseInt(str);会报异常____________________
【分析】
parseInt是将字符串参数解析为带符号的十进制整数。
字符串中的字符都必须是十进制数字,除了第一个字符可能是ASCII减号’-’ ( ‘\u002D’ )以指示负值或ASCII号’+’ ( ‘\u002B’ )以指示正值,返回所得到的整数值。
【答案】
java.lang.NumberFormatException
2. 下列外部类的定义中不正确的是
A.class x { … }
B.class x extends y { … }
C.static class x implements y1,y2 { … }
D.public class x extends Applet { … }
【分析】
static修饰的为类成员,会随着类的加载而加载,比如静态代码块,静态成员,静态方法(这里只是加载,并没有调用)等等,可以想象一下,如果把一个Class文件中的外部类设为static,目的难道是让这个类随着应用的启动而加载吗?如果在这次使用过程中根本没有使用过这个类,那么是不是就会浪费内存。这样来说设计不合理,总而言之,设计不合理的地方,Java是不会让它存在的。
而为什么内部类可以使用static修饰呢,因为内部类算是类的成员了,如果没有使用静态来修饰,那么在创建内部类的时候就需要先有一个外部类的对象,如果我们一直在使用内部类,那么内存中就会一直存在外部类的引用,而我们有时候只需要使用内部类,不需要外部类,那么还是会浪费内存,甚至会造成内存溢出。使用static修饰内部类之后,内部类在创建对象时就不需要有外部类对象的引用了。
最终结论就是:static可以用来修饰内部类,但是不可以用来修饰外部类
【答案】
C选项
3. 下列哪种说法是正确的
A. 实例方法可以直接调用超类的实例方法
B. 实例方法可以直接调用超类的类方法
C. 实例方法可以直接调用本类的类方法
D. 实例方法可以直接调用其他类的实例方法
【分析】
A选项错误,实例方法可以调用超类公有实例方法
C选项错误,实例方法可以直接调用超类的公有类方法
D选项错误,实例方法可以通过类名调用其他类的类方法
【答案】
B选项
4. 以下程序的执行结果是
public class ThreadTest {
public static void main(Sring[] args) {
Runnable runner = new Runnable() {
@Override
public void run() {
System.out.print("foo");
}
}
Thread t = new Thread(runner);
t.run();
Sysytem.out.print("bar");
}
}
【执行结果】
foobar
【程序分析】
线程的启动方式只能通过start方法,才能体现出多线程的效果,本程序代码中手动调用run()方法和普通调用类的方法没有任何区别
5. 以下程序的输出结果是
public class Example {
String str = new String("good");
char[] ch = { 'a', 'b', 'c' };
public static void main(String args[]) {
Example ex = new Example();
ex.change(ex.str, ex.ch);
System.out.print(ex.str + " and ");
System.out.print(ex.ch);
}
public static void change(String str, char ch[])
{
str = "test ok";
ch[0] = 'g';
}
}
【分析】
对于String,是被final修饰的特殊的类,所以每次对String的更改都会重新创建内存地址并存储(也可能是在字符串常量池中创建内存地址并存入对应的字符串内容),但是因为这里String是作为参数传递的,在方法体内会产生新的字符串而不会对方法体外的字符串产生影响。
char数组是引用传递,和原值指向同一块地址,因此数组的元素值会发生改变。
【结果】
good and gbc
6. 下列哪个修饰符可以使在一个类中定义的成员变量只能被同一包中的类访问?
A. private
B. 无修饰符
C. public
D. protected
【分析】
【答案】
B选项
7. 关于访问权限说法正确的是( )
A. 外部类前面可以修饰public,protected和private
B. 成员内部类前面可以修饰public,protected和private
C. 局部内部类前面可以修饰public,protected和private
D. 以上说法都不正确
【分析】
修饰符的访问权限定义见上题中表格
对于选项A,对于外部类而言,它也可以使用访问控制符修饰,但外部类只能有两种访问控制级别: public 和默认。因为外部类没有处于任何类的内部,也就没有其所在类的内部、所在类的子类两个范围,因此 private 和 protected 访问控制符对外部类没有意义。
对于选项B,内部类的上一级程序单元是外部类,它具有 4 个作用域:同一个类( private )、同一个包( protected )和任何位置( public)。
对于选项C,因为局部成员的作用域是所在方法,其他程序单元永远不可能访问另一个方法中的局部变量,所以所有的局部成员都不能使用访问控制修饰符修饰。
【答案】
选项B
8. 关于ASCII码和ANSI码,以下说法不正确的是()
A. 标准ASCII只使用7个bit
B. 在简体中文的Windows系统中,ANSI就是GB2312
C. ASCII码是ANSI码的子集
D. ASCII码都是可打印字符
【分析】
选项A,标准ASCII只使用7个bit,扩展的ASCII使用8个bit。
选项B,ANSI通常使用 0x00~0x7f 范围的1 个字节来表示 1 个英文字符。超出此范围的使用0x80~0xFFFF来编码,即扩展的ASCII编码。不同 ANSI 编码之间互不兼容。在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。
选项C,ANSI通常使用 0x00~0x7f 范围的1 个字节来表示 1 个英文字符,即ASCII码
选项D,ASCII码包含一些特殊空字符
【答案】
选择D,特殊空字符无法打印
9. 有关中间件的描述
中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或OS环境。
(简单来说,中间件并不能提高内核的效率,一般只是负责网络信息的分发处理)
10. 以下程序的运行结果是
class Base{
public Base(String s){
System.out.print("B");
}
}
public class Derived extends Base{
public Derived (String s) {
System.out.print("D");
}
public static void main(String[] args){
new Derived("C");
}
}
A. BD
B. DB
C. C
D. 编译错误
【分析】
这道题着实坑了我一把,主要是对基本概念没有熟练,子类构造方法在调用时必须先调用父类的,由于父类没有无参构造,必须在子类中显式调用。
修改子类构造方法如下即可:
public Derived(String s){
super("s");
System.out.print("D");
}
【选项】
D
11. 下面代码输出的结果是()
public class Base {
private String baseName = "base";
public Base() {
callName();
}
public void callName() {
System. out. println(baseName);
}
static class Sub extends Base {
private String baseName = "sub";
public void callName() {
System. out. println (baseName) ;
}
}
public static void main(String[] args) {
Base b = new Sub();
}
}
A. null
B. sub
C. base
【分析】
派生类创建对象时,首先创建基类对象,默认调用基类的构造方法Base(),基类的构造方法调用callName()方法,调用的是派生类中的callName,此时派生类还未构造,所以变量baseName的值为null。
【知识点】
1. 类的加载顺序
(1) 父类静态代码块(包括静态初始化块,静态属性,但不包括静态方法)
(2) 子类静态代码块(包括静态初始化块,静态属性,但不包括静态方法 )
(3) 父类非静态代码块( 包括非静态初始化块,非静态属性 )
(4) 父类构造函数
(5) 子类非静态代码块 ( 包括非静态初始化块,非静态属性 )
(6) 子类构造函数
其中:类中静态块按照声明顺序执行,并且(1)和(2)不需要调用new类实例的时候就执行了(意思就是在类加载到方法区的时候执行的)
2. 子类覆盖父类方法(方法重写实现多态)
Base b = new Sub();它为多态的一种表现形式,声明是Base,实现是Sub类, 理解为 b 编译时表现为Base类特性,运行时表现为Sub类特性。
当子类覆盖了父类的方法后,意思是父类的方法已经被重写,题中 父类初始化调用的方法为子类实现的方法,子类实现的方法中调用的baseName为子类中的私有属性。
由知识点1可知,此时只执行到步骤4,子类非静态代码块和初始化步骤还没有到,子类中的baseName还没有被初始化。所以此时 baseName为空。 所以为null。
【答案】
A
12. (多选)在JAVA中,下列哪些是Object类的方法()
A. synchronized()
B. wait()
C. notify()
D. notifyAll()
E. sleep()
【分析】
Object类有12个成员方法,分别是
- clone():Object
- equals(Object):boolean
- finalize():void
- getClass()
- hashCode():int
- notify():void
- notifyAll():void
- toString():String
- wait():void
- wait(long):void
- wait(long,int):void
【答案】
BCD
13. (多选)jvm中垃圾回收分为scanvenge gc和full GC,其中full GC触发的条件可能有哪些
A. 栈空间满
B. 年轻代空间满
C. 老年代满
D. 持久代满
E. System.gc()
【分析】
这题是真的把我问傻了,完全的知识盲区啊!!!!
full GC触发的条件
除直接调用System.gc外,触发Full GC执行的情况有如下四种。
旧生代空间不足
旧生代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行Full GC后空间仍然不足,则抛出如下错误:
java.lang.OutOfMemoryError: Java heap space
为避免以上两种状况引起的FullGC,调优时应尽量做到让对象在Minor GC阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。
Permanet Generation空间满
PermanetGeneration中存放的为一些class的信息等,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下会执行Full GC。如果经过Full GC仍然回收不了,那么JVM会抛出如下错误信息:
java.lang.OutOfMemoryError: PermGen space
为避免Perm Gen占满造成Full GC现象,可采用的方法为增大Perm Gen空间或转为使用CMS GC。
CMS GC时出现promotion failed和concurrent mode failure
对于采用CMS进行旧生代GC的程序而言,尤其要注意GC日志中是否有promotion failed和concurrent mode failure两种状况,当这两种状况出现时可能会触发Full GC。
promotionfailed是在进行Minor GC时,survivor space放不下、对象只能放入旧生代,而此时旧生代也放不下造成的;concurrent mode failure是在执行CMS GC的过程中同时有对象要放入旧生代,而此时旧生代空间不足造成的。
应对措施为:增大survivorspace、旧生代空间或调低触发并发GC的比率,但在JDK 5.0+、6.0+的版本中有可能会由于JDK的bug29导致CMS在remark完毕后很久才触发sweeping动作。对于这种状况,可通过设置-XX:CMSMaxAbortablePrecleanTime=5(单位为ms)来避免。
统计得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间
这是一个较为复杂的触发情况,Hotspot为了避免由于新生代对象晋升到旧生代导致旧生代空间不足的现象,在进行Minor GC时,做了一个判断,如果之前统计所得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间,那么就直接触发Full GC。
例如程序第一次触发MinorGC后,有6MB的对象晋升到旧生代,那么当下一次Minor GC发生时,首先检查旧生代的剩余空间是否大于6MB,如果小于6MB,则执行Full GC。
当新生代采用PSGC时,方式稍有不同,PS GC是在Minor GC后也会检查,例如上面的例子中第一次Minor GC后,PS GC会检查此时旧生代的剩余空间是否大于6MB,如小于,则触发对旧生代的回收。
除了以上4种状况外,对于使用RMI来进行RPC或管理的Sun JDK应用而言,默认情况下会一小时执行一次Full GC。可通过在启动时通过- java-Dsun.rmi.dgc.client.gcInterval=3600000来设置Full GC执行的间隔时间或通过-XX:+ DisableExplicitGC来禁止RMI调用System.gc。
【答案】
CDE