最近一朋友在找工作,发来了一部分面试题,在这里分享给大家,希望有用。
1.写出至少两种你认为可行的单例模式实现方案(java,考虑多线程)
懒汉式
public class SingletonDemo1{
private static SingletonDemo1 instance;
private SingletonDemo1(){}
public static synchronized SingletonDemo1 getInstance(){
if (instance == null) {
instance = new SingletonDemo1();
}
return instance;
}
}
虽然做到了线程安全,并且解决了多实例的问题,但是它并不高效。因为在任何时候只能有一个线程调用 getInstance() 方法。
饿汉式
public class SingletonDemo2 {
private static final SingletonDemo2 instance = new SingletonDemo2();
private SingletonDemo2(){}
public static SingletonDemo2 getInstance(){
return instance;
}
}
因为单例的实例被声明成 static 和 final 变量了,在第一次加载类到内存中时就会初始化,所以创建实例本身是线程安全的。
双重校验锁
public class SingletonDemo3 {
private volatile static SingletonDemo3 instance;
private SingletonDemo3(){}
public static SingletonDemo3 getSingletonDemo3(){
if (instance == null) {
synchronized (SingletonDemo3.class) {
if (instance == null) {
singletonDemo3 = new SingletonDemo3();
}
}
}
return instance;
}
}
使用 volatile 的主要原因是其另一个特性:禁止指令重排序优化。只有在第一次实例化时,才启用同步机制,提高了性能。
在Java1.5以后,volatile关键字被加强,这种方法可以正常使用。
2.请写出二分插入排序、简单选择排序、堆排序、冒泡排序、快速排序、归并排序任意两种排序方法的平均时间复杂度及实现(java).
3.写出工具方法,判断给定int值对应的二进制中第n位值是否为1。
这个比较简单,随手甩出几行代码
public Boolean DecimalTest(int num, int n){//默认n>=0
String str = "";
Boolean flag = false;
while(num>0){
str = num%2+str;
num = num/2;
}
char[] temp = str.ToCharArray();
if(temp.length()>=n && "1".equals(temp[n]) ){
flag = true;
}
return flag;
}
4.自定义java类,模拟栈功能。
使用数组作为栈的存储结构
public class StackDemo {
// 初始容量
private int capacity = 10;
// 增量
private double increment = 1.5;
// 栈中数据数量
private int length = 0;
// 用来实现栈功能的数组
private Object[] src = new Object[capacity];
//默认大小
public StackDemo() { }
public StackDemo(int initCapacity) { // 自定义初始栈的大小
this.capacity = initCapacity;
}
public boolean isEmpty() { // 判断栈是否为空
return length == 0 ? true : false;
}
public Object[] extend(){ //扩充栈的容量
Object[] dest = new Object[(int)(src.length * increment)];
System.arraycopy(src, 0, dest, 0, src.length);
return dest;
}
public void push(Object obj){ //压栈
if(length >= src.length){
src = extend();
}
src[length] = obj;
length ++;
}
public Object peek(){ //取栈顶元素
if(isEmpty()){
throw new NullPointerException();
}
return src[length-1];
}
public Object pop(){ //取出栈顶元素并删除
if(isEmpty()){
throw new NullPointerException();
}
length --;
return src[length];
}
//获得栈的元素个数
public int size(){
return length;
}
}
测试类
public class StackTest {
public static void main(String[] args) {
StackDemo sd = new StackDemo();
for(int i=0; i<20; i++){
sd.push(new Integer(i));
}
while(!sd.isEmpty()){
System.out.print("栈的大小: "+sd.size()+" ");
System.out.println("栈顶元素为: "+sd.pop());
}
//sd.pop();
}
}
输出结果为:
栈的大小: 20 栈顶元素为: 19
栈的大小: 19 栈顶元素为: 18
栈的大小: 18 栈顶元素为: 17
栈的大小: 17 栈顶元素为: 16
栈的大小: 16 栈顶元素为: 15
栈的大小: 15 栈顶元素为: 14
栈的大小: 14 栈顶元素为: 13
栈的大小: 13 栈顶元素为: 12
栈的大小: 12 栈顶元素为: 11
栈的大小: 11 栈顶元素为: 10
栈的大小: 10 栈顶元素为: 9
栈的大小: 9 栈顶元素为: 8
栈的大小: 8 栈顶元素为: 7
栈的大小: 7 栈顶元素为: 6
栈的大小: 6 栈顶元素为: 5
栈的大小: 5 栈顶元素为: 4
栈的大小: 4 栈顶元素为: 3
栈的大小: 3 栈顶元素为: 2
栈的大小: 2 栈顶元素为: 1
栈的大小: 1 栈顶元素为: 0
5.Activity 启动流程
6.viewroot是干嘛的?
7.decorview是什么,是怎么和activiry关键的,又是怎么和viewroot关键上
8.Activitythread了解过吗?
9.looper.perpar干了什么?looper.loop又干了什么?为什么for循环不会死机?
10.apt是干嘛的?编译时注解和运行时注解都是干嘛的?
11.你的热插拔形式属于什么设计模式?
12.用过组建化吗?两个组件怎么通信,怎么划分?
13.view绘制流程
14.事件分发流程
15.measure是干嘛的,draw是干嘛的?draw中绘制的流程是背景,主体,ondraw之类的,那么主体是什么?
16.invalidate 原理,是怎么通知父容器刷新的
17.requestlayout的原理
18.如何检测内存,检测卡顿,用traceview工具
19.如何检测内存泄露,不用工具
20.map的结构?
21.treemap了解过吗?
22.hashmap的数据结构,他是怎么扩容的
23.vetor了解过吗
24.list是什么?arraylist的结构?linkedlist结构,以及它们的优缺点
25.gc是怎么回收的?
26.gc root 了解过吗
java四种引用区别是?
网友评论