java笔试题目
1。请大概描述一下Vector和ArrayList的区别,Hashtable和HashMap的区别。(5)// thread-safe or unsafe, could contain null values or not
就ArrayList 与Vector 主要从二方面来说. 一.同步性:Vector 是线程安全的,也就是说是同步的,而ArrayList 是线程序不安全的,不是 同步的 二.数据增长:当需要增长时,Vector 默认增长为原来一培,而ArrayList 却是原来的一半 就HashMap 与HashTable 主要从三方面来说。 一.历史原因:Hashtable 是基于陈旧的Dictionary 类的,HashMap 是Java 1.2 引进的Map 接口 的一个实现 二.同步性:Hashtable 是线程安全的,也就是说是同步的,而HashMap 是线程序不安全的, 不是同步的 三.值:只有HashMap 可以让你将空值作为一个表的条目的key 或value
2。请问你在什么情况下会在你的JAVA代码中使用可序列化?(5)
为什么放到HttpSession中的对象必须要是可序列化的?(5)
// save, communicate
因为在我们的系统中,某些类实例化为对象后,将会在网络中传送。而我们知道,网络传输只能2进制文件。
这就像你要搬一个大家俱通过一个小门,你得先把家俱拆散,到屋里后再把这些组件重新组合为你的大家俱。 也就是说,当你的对象会被通过网络来传送时,那就必须要序列化。 放到httpSession中的对象,必定会被使用网络来传输的。
3。为什么在重写了equals()方法之后也必须重写hashCode()方法?(10)
// implementations of dictionaries need hashCode() and equals()
要求是需要重写的,实践上是可以不重写的,反正编译器不会报错,一般情况下也不回出问题,只要你不用类似于Hashtable存放这些对象。 之所以要求hashcode和equals一致,主要考虑的还是Hashtable问题。举个例子: 假如你了重写A类的equals方法,而且有两个对象a1和a2按照这个方法比较是相等的。现在你要把这两对象分别作为另外两个对象v1和v2的key(类似于名字)放入Hashtable h中,也就是要: h.put(a1,v1); h.put(a2,b2); 这样,由于a1和a2是相等的,按理说put(a2,b2);时应该把a1覆盖掉。换句话说如果你put(a1,b1);之后,用get方法h.get(a1)和h.get(a2)应该都能的到b1。如果你觉得这样说不太直观,你可以把a1、a2想象成两个String。 但如果你要是不重写hashcode方法,则上述目标完成不了。因为,虽然我们认为a1和a2是相等的,并且equals的确如此,但问题是哈希表她不是按照equals来判断两个对象是否相等的! 给哈希表一个键值,他会用hashcode方法取得这个键值的哈希码也就是hashcode值,把它作为实际的索引来管理整个表,如果你学过数据结构,应该知道管理的过程。 反过来说,假如String类的作者仅仅重写equals而没重写hashcode方法,那么我们两次这样执行:h.put("aaa", b1); h.put("aaa", b2); 会在Hashtable中建立两个键值对,而h.get("aaa")则得不到b1或b2.
4。sleep()和wait()有什么区别?(10)
// threads communication: wait() and notifyAll()
sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
5。编程题:用最有效率的方法算出2乘以17等于多少?(5)
// 2<<4+2#include <iostream.h>
#include<time.h>
#define times 3000000000
int main ()
{
time_t t1,t2,t3,t4;
t1 = time (NULL);
for(long i=1;i<times;i++)
17<<1;
t2 = time (NULL);
for(long j=1;j<times;j++)
(2<<4)+2;
t3 = time (NULL);
for(long k=1;k<times;k++)
17+17;
t4 = time (NULL);
cout<<"17<<1: "<<t2-t1<<" s"<<endl;
cout<<"(2<<4)+2: "<<t3-t2<<" s"<<endl;
cout<<"17+17: "<<t4-t3<<" s"<<endl;
return 0;
}
结果如下:
17<<1: 14 s
(2<<4)+2: 25 s
17+17: 22 s
6。JAVA是不是没有内存泄漏问题?看下面的代码片段,并指出这些代码隐藏的问题。(10)
…
Object[] elements = new Object[10];
int size;
…
public Object pop() {
if (size == 0)
return null;
Object o = elements[--size];
return o;
}
// elements[size] = null;
7。请阐述一下你对JAVA多线程中“锁”的概念的理解。(10)
// optimistic lock, pessimistic lock, signal, dead lock, starvation, synchronization
当有多个线程共用一种临界资源的时候,便会出现冲突,锁就是用来解决这种冲突的,跟上厕所一样,假如有ABC三个人都来上厕所而厕所只有一个一次只能进一人,A先来了,那么在A出来之前,这个厕所就处在了“锁”定状态,B和C憋死也要在外面等着,直到A出门(原因很多,如睡着了,方便完了,忘带厕纸了跑出来找人要....)“锁”定解除B和C才能进入,当然牛逼的进(A和B有一腿只让B进或者优先级高或者...),SB的在外面继续等。此乃吾理解之锁定,希望能够对你有所帮助
8。所有的递归实现都可以用循环的方式实现,请描述一下这两种实现方式各自的优劣。
并举例说明在什么情况下可以使用递归,而在什么情况下只能使用循环而不能使用递归?(5)
// recursive: when you need a stack and stack memory is enough
// non-recursive: when you need a queue
9。请简要讲一下你对测试驱动开发(TDD)的认识。(10)
// write unit testing code first
10。请阐述一下你对“面向接口编程”的理解。(10)
// adapter, listener, bridge, decorator, proxy… patterns
接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。
我们在一般实现一个系统的时候,通常是将定义与实现合为一体,不加分离的,我认为最为理解的系统设计规范应是所有的定义与实现分离,尽管这可能对系统中的某些情况有点繁烦。
接口的本身反映了系统设计人员对系统的抽象理解。
接口应有两类:第一类是对一个体的抽象,它可对应为一个抽象体(abstract class);
第二类是对一个体某一方面的抽象,即形成一个抽象面(interface);
一个体有可能有多个抽象面。
抽象体与抽象面是有区别的。
11。在J2EE中有一个“容器(Container)”的概念,不管是EJB、PICO还是Spring都有他们
各自实现的容器,受容器管理的组件会具有有生命周期的特性,请问,为什么需要容器?
它的好处在哪里?它会带来什么样的问题?(15)
// encapsulation
12。请阐述一下你对IOC(Inversion of Control)的理解。(可以以PICO和Spring的IOC作为例子说明他们在实现上各自的特点)(10)
// reduce classes’ dependencies
13。下面的代码在绝大部分时间内都运行得很正常,请问在什么情况下会出现问题?问题的根源在哪里?(10)
import java.util.LinkedList;
public class Stack {
LinkedList list = new LinkedList();
public synchronized void push(Object x) {
synchronized(list) {
list.addLast( x );
notify();
}
}
public synchronized Object pop()
throws Exception {
synchronized(list) {
if( list.size() <= 0 ) {
wait();
}
return list.removeLast();
}
}
}
// dead lock, synchronized on both ‘list’ and ‘this’