Thought Coding实验室2016年纳新笔试题
姓名: _______ 班级: ________ 联系方式: ________
Java部分
一、请看下面这段程序,回答问题
public class Test1 {
public static void main(String[] args){
StringBuffer a = new StringBuffer("Thought"); //语句1
StringBuffer b = new StringBuffer("Coding"); //语句2
operate(a, b);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
static void operate(StringBuffer x, StringBuffer y){
x.append(y); //语句3
y = x;
}
}
1、这段程序的输出结果是什么?为什么?
输出:
a = ThoughtCoding
b = Coding
解释:考察Java参数传递机制与StringBuffer的使用。
operat方法传入两个StringBuffer类型的句柄的副本(也可以说是指向堆内存中StringBuffer对象的指针的副本),一个是x,一个是y,执行”x.append(y);”后,y指向的StringBuffer对象内容”Coding”连接在x指向的StringBuffer对象的字符串内容(底层是一个value[]数组)后,执行”y = x;”后,只是修改了y的指向,并没有修改y指向的StringBuffer对象的字符串内容,在方法执行结束后,x、y自然消亡。
2、把上述程序中的语句1、2、3分别修改为:
String a = "Thought";
String b = new String("Coding");
x = x + y;
输出结果又是什么?为什么有这样的区别?
输出:
a = Thought
b = Coding
解释:考察String的使用以及与StringBuffer区别。
String使用private final char value[]来实现字符串的存储,也就是说,String对象创建之后,就不能修改对象中存储的字符串内容。另外,Java对String重载了”+”操作符,可以直接使用”+”对两个字符串进行连接。
operate方法中,执行”x = x + y”,可分为两步,第一步先创建一个新的String对象,它的内容为x与y指向的String对象内容连接后的字符串;第二步使x指向新的String对象,所以a指向的原String内容并未改变。
3、通过引号””创建String对象与通过new关键字创建String对象有什么区别?
解释:考察String对象的创建与对Java运行时内存如常量池、堆内存的了解。
用引号创建String对象是在编译期,在方法区的常量池中,如果常量池中已有字符串内容相同的对象(用equals判定),则直接返回常量池中字符串对象的引用。而使用new关键字会在堆内存中创建一个新对象,不管常量池中是否有值相同的对象,都返回堆内存中对象的引用。
4、”==”与equals的区别?为了比较两个String对象的字符串内容是否相同,请试着重写Object类的equals方法。
解释:考察”==”与equals区别。
“==”比较的是地址,Object类的equals()方法返回”==”比较结果。
public boolean equals(Object anObject)
{
//如果是同一个对象
if (this == anObject)
{
return true;
}
//如果传递进来的参数是String类的实例
if (anObject instanceof String)
{
String anotherString = (String)anObject;
int n = count;//字符串长度
if (n == anotherString.count) //如果长度相等就进行比较
{
char v1[] = value;//取每一个位置的字符
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) //对于每一位置逐一比较
{
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
二、Java集合类在Java程序开发中使用极其频繁,请回答相关问题
1、 请简要说明什么是ArrayList?如何使用?
2、 请简要说明什么是Hash算法?以及HashMap如何通过Hash算法实现数据存储?
3、 通过无参构造方法构造HashMap:HashMap map = new HashMap();
现在往map中存储28对key-value数据,请问map如何扩容,需扩容几次?
4、 请简要说明HashMap与 HashTable的区别?
5、 (选答,加分项)你是否了解Java并发集合类?
解释:考察常见集合ArrayList的使用与HashMap的底层实现,可拓展提问其他集合类如HashSet(由封装value的HashMap实现)等。
可参看博客:给jdk写注释系列之jdk1.6容器(1):ArrayList源码解析
三、请看下面这段程序,回答问题
public class Test3 {
public static StringBuilder output= new StringBuilder();
public static void foo(int i){
try {
if(i == 1)
{
output.append("try1 ");
throw new Exception();
}
output.append("try0 ");
}
catch (Exception e)
{
output.append("catch ");
return ;
}
finally {
output.append("finally ");
}
output.append("end \n");
}
public static void main(String args[]){
foo(0);
foo(1);
System.out.println(output);
}
}
1、 你了解Java的异常捕获机制吗?请根据你的理解写出这段代码的输出结果。
输出:
try0 finally end
try1 catch finally
解释:考察StringBuilder的使用与Java异常捕获机制、try-catch-finally的执行顺序、return语句对执行顺序的影响,可扩展提问,StringBuilder与StringBuffer区别与finally什么情况下不执行。
try中是可能发生异常的程序段;
catch中依次编写对应的异常处理器方法,当抛出异常后,由运行时系统在栈中从当前位置开始依次回查方法,直到找到合适的异常处理方法,如果未找到,则执行
finally或直接结束程序运行。
finally :无论是否捕获或处理异常,finally块里的语句都会被执行。
注意(很重要,面试常问):当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。
在以下4种特殊情况下,finally块不会被执行:
1)在finally语句块中抛出了异常且未处理。
2)在前面的代码中用了System.exit()退出程序。
3)程序所在的线程死亡。
4)CPU出现异常被关闭。
2、 你在平时编程时都遇到过哪些运行时异常?请举例说明。
解释:考察运行时异常的掌握情况与平时编程的积累。
1’ NullPointerException:空指针异常。调用了不存在的对象或未经实例化或初始化的对象时会抛出,如当试图操作一个空对象(赋值为null)的属性、方法时就会抛出。
(实例化:通俗的理解就是为对象开辟空间,使其可在规定范围内被调用。注意:User u;这只是一个对象声明,并没有进行实例化或初始化。
初始化:就是把实例化后的对象中的基本数据类型字段赋默认值或设定值,为非基本类型赋值null,对于static字段只会初始化一次。)
2’ ArithmeticException:算术条件异常。最常见的就是0作除数时会抛出。
3’ ClassNotFoundException:类未找到异常。在通过反射Class.forName(“类名”)来获取类时,如果未找到则会抛出异常。
4’ ArrayIndexOutOfBoundsException:数组索引越界异常。当试图操作数组的索引值为负数或大于等于数组大小时会抛出。
5’ NegativeArraySizeException:数组长度为负值异常。一般在初始化数组大小为负值时抛出。
6’ ArrayStoreException:数组类型不匹配值异常。例如将一个Object数组中加入一个Integer对象与一个String对象时,类型不匹配就会抛出。
7’ IllegalArgumentException:非法参数异常。会在使用Java类库方法时传入参数值越界时抛出。
四、单线程程序的功能往往非常有限,多线程与高并发环境开发已成为趋势。Java提供了非常优秀的多线程支持,请回答相关问题
1、 Java有几种创建线程的方式?有什么区别?
解释:考察线程类的掌握情况。
第一种是继承Thread类重写方法run(),不可以抛异常无返回值
第二种是实现Runnable接口实现方法run()作为target传入Thread类构造器不可以抛异常无返回值适合多线程共享同一份资源情况
第三种是实现Callable<T>接口,接口中要覆盖的方法是
public <T> call() 注意:此方法可以抛异常,而前两种不能,而且此方法可以有返回值,使用时用FutureTask对象包装,作为target传入Thread类构造器
请简述线程的生命周期,Java中哪些方法会导致线程状态变化?
解释:考察线程状态的掌握情况
2、 Thread类的sleep()方法和Object类的wait()方法都可以让线程暂停执行,它们有什么区别?
解释:考察sleep()与wait()方法。注意这个问题百度比较好找,问的时候看是否真正理解了,比如可以让解释一下什么叫不释放对象锁。
对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
在调用sleep()方法的过程中,线程不会释放对象锁。(形象的说是占着CPU睡觉)
而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备。
五、(选答,加分项)
1、 你了解或使用过Json吗?
2、 你了解或使用过什么Java开源框架?(Oracle、Apache开源框架亦可)
3、 你开发过什么Java或Android项目?