java android面试题分析总结
本文参考多处,一并感谢!
http://www.blogjava.net/fanyingjie/archive/2007/06/27/126467.aspx
http://baike.baidu.com/view/1788559.htm
http://jeff-tang.blog.163.com/blog/static/141686909201022010522906/
http://www.cnblogs.com/mgod/archive/2007/08/05/844011.html
参考过的书籍
《深入理解Java虚拟机:JVM高级特性与最佳实践》
12.ArrayList,Vector,LinkedList的区别
ArrayList | Vector | LinkedList | |
实现原理 | 数组 | 数组 | 双向链表 |
线程安全 | 否 | 是 | 否 |
优点 | 1.数组实现优于遍历 2.非线程安全,效率较高 | 1.数组实现优于遍历 2.线程安全 | 1.节点的增删无需对象的重建 2.空间利用毫无浪费 |
缺点 | 1.非线程安全 2.数组中未使用元素照成了空间的浪费 3.扩容可能引起对象的重建 4.增删有可能引起数组元素的移动 | 1.数组中未使用的元素造成空间的浪费 2.扩容可能引起对象的重建 3.线程安全,效率相对低 4.增删有可能引起数组元素的移动 | 1.遍历效率较低 2.非线程安全 |
扩容 | 0.5倍增量 | 1倍增量 | 按需增删 |
使用场景 | 1.无线程的要求。 2.遍历较多,增删较少 | 1.有线程安全的要求 2.遍历场景较多,增删场景较少 | 增删场景较多的时候 |
11.int与Integer的区别
int | Integer | |
类型 | 基本类型 | 复合类型 |
默认值 | 0 | null |
存储 | 栈(局部变量) 堆(成员变量,有待进一步确认) | 堆上(只能通过new创建) |
方法 | 基本类型无方法 | 有 |
速度 | 快(栈上 的操作相对快) | 慢 |
泛型支持 | 否(java中的泛型不支持,C++中的模板支持) | 支持 |
容器类支持 | 否(直接使用通常会进行装箱操作) | 支持 |
存在意义 | 1.历史原因(顺延C/C++中存在) 2.方便快速(无需new) | 基本类型int的包装类 提供了对泛型,容器类的支持 |
9.向一个List<Integer>的容器里放入String对象
需要了解的一些知识
- Java中的泛型是伪泛型。(可参见周志明的《深入理解Java虚拟机:JVM高级特性与最佳实践》)
- 泛型是编译器的语法糖,并非产生了实际类型List<Integer>。
- 对于List<Integer>和List<String>都是在编译之后,都是作为List<Object>类型来使用的。
- 在Java虚拟机中,没有泛型的概念。
- 通过反射可以把一些强制性的检查推迟到运行期。
- 如果直接向List<Integer>中插入String对象,肯定会得到编译器的检查,并提示错误。
- 而反射机制可以把这种错误的检查延迟到运行期。(这是反射的一个缺点,会把编译期能够检查到的问题,推迟到了运行期发现)
- 由于List<Integer>对象在运行期,本身就是以List<Object>的形式存在,故其在运行期不会产生错误。
- 反射机制,通过编译期的检查骗过了我们。而我们又可以通过反射骗过了编译器的检查。
packagecom.jue.test; importjava.lang.reflect.InvocationTargetException; importjava.lang.reflect.Method; importjava.util.ArrayList; importjava.util.List; publicclassTestMain{ List<Integer>mIntList=newArrayList<Integer>(); publicstaticvoidmain(String[]args)throwsSecurityException, NoSuchFieldException,IllegalArgumentException, IllegalAccessException,InvocationTargetException, NoSuchMethodException{ TestMaintm=newTestMain(); MethodaddMethod=List.class.getMethod("add", newClass[]{Object.class}); //使用反射,我们避免了编译期的强制检查 addMethod.invoke(tm.mIntList,newObject[]{newString("abc")}); addMethod.invoke(tm.mIntList,newObject[]{newString("123")}); addMethod.invoke(tm.mIntList,newObject[]{newString("cde")}); addMethod.invoke(tm.mIntList,newObject[]{newString("fgh")}); for(Objecto:tm.mIntList){ System.out.println(o); } } }
输出结果:
abc
123
cde
fgh
10.List<Integer>与List<String>在编译后都是List<Object>形式存在
packagecom.jue.test; importjava.util.List; publicclassTestMain{ publicvoidtestList(List<Integer>list){ } publicvoidtestList(List<String>list){ } }
结果:编译失败!
分析:
- 如上所述,Java的泛型是编译器的语法糖,在编译后,统一使用List<Object>代替。
- 对于重载,方面名相同,而签名不同,由于参数都将是List<Object>,故编译失败,因为不可能产生签名一样的两个方法。
1.short转换相关的
其一,
packagecom.jue.test; publicclassTestMain{ publicstaticvoidmain(Stringargs[]){ shorts1=1; s1=s1+1; } }
编译结果
DescriptionResourcePathLocationType
Type mismatch: cannot convert from int to short TestMain.java/TestShort/src/com/jue/testline 6Java Problem
分析:
s1+1会自动转换成int类型,导致s1= s1+1;损失精度。
其二,
packagecom.jue.test; publicclassTestMain{ publicstaticvoidmain(Stringargs[]){ shorts2=2; s2+=2; } }
编译结果:成功
分析:
反编译之后
packagecom.jue.test; publicclassTestMain { publicstaticvoidmain(String[]args) { shorts2=2; s2=(short)(s2+2); } }
故猜测:这可能是java编译器的语法糖。
2.RuntimeException与普通异常,error的区别。
Checked Exception:在编译时就能够被Java编译器所检测到的。
UncheckedException:则是编译时,java编译器不能检查到。
RuntimeException | 普通Exception | Error | |
受控异常 | 否 | 是 | 否 |
产生原因 | 开发者的编程错误 | 由于外界环境所限, 本身潜在的一些问题 | Java运行时的系统错误,资源耗尽,是一种严重的, 程序无法修复的问题 |
例子 | NullPointerException ArrayOutOfIndexException ClassCastException ArithmeticException UnsupportedOperationException | ClassNotFoundException IOException FileNotFoundException | VirtualMachineError StackOverflowError OutOfMemoryError |
3.finally的一个面试题
packagecom.jue.test; importjava.util.ArrayList; importjava.util.List; publicclassTestMain{ publicstaticvoidmain(String[]args){ test(); } privatestaticvoidtest(){ Listlist=newArrayList(); try{ System.out.println("return!!"); return; }catch(Exceptione){ System.out.println("catchException!!"); }finally{ System.out.println("finally!!"); } } }
结果:
return!!
finally!!
分析:即便在try中return;finally总会被执行的意义不变,仍然会执行。
4.final,finalize,finally的区别
final:关键字,表不变
修饰:
- 方法:方法不可Override
- 类:不可被继承
- 基本类型量:常量,值不可变
- 符合类型量:引用不可变,即引用的值不可变
finalObjecto1=newObject(); o1=newObject();
finally:关键字,Java异常处理机制的一部分,在异常发生时,用来提供一个必要的清理的机会。
finalize:Object类的方法(参考自百度百科)
意义:Java技术允许使用finalize()方法在垃圾回收器将对象回收之前,做一些必要的清理操作。
调用前提:这个对象确定没有被引用到。
工作原理:
- 垃圾收集器准备好释放对象占用的空间。
- 首先调用其finalize方法。
- 下一次垃圾收集过程中,真正回收内存。
不确定性:
- finalize的执行时间是不缺定的。
- 一个对象引用另一个对象,并不能保证finalize的方法按照特定的执行顺序。
5.Override,Overload
Override Overload 签名+返回值 相同 方法名相同,签名不同 关系 父子类继承关系 通常是同一类层次中 识别 运行时多态
根据具体的对象,
查询对象的虚方法表,确定调用关系编译时多态
由对象的外观类型(即声明类型)决定修饰符限制 非private
非static
非final无特别 异常关系 子类方法不能抛出被父类方法更多的异常 无特别 可见性关系 子类不能比父类访问权限更窄
(里氏替换原则决定)无特别
6.Collection Collections
Collection:接口,集合类的接口,一个契约,提供了集合基本的大小,添加,清除,遍历方法等。
Collections:工具类,提供了很多静态方法,给集合提供一些查询,比较,排序,交换,线程安全化等方法。
7.Integer 缓存
packagecom.jue.test; publicclassTestMain{ publicstaticvoidmain(String[]args){ Integeri1=1; Integeri11=1; System.out.println(i1==i11); Integeri2=200; Integeri22=200; System.out.println(i2==i22); } }
结果 :
true
false
分析:反编译结果为
packagecom.jue.test; importjava.io.PrintStream; publicclassTestMain { publicstaticvoidmain(String[]args) { Integeri1=Integer.valueOf(1); Integeri11=Integer.valueOf(1); System.out.println(i1==i11); Integeri2=Integer.valueOf(200); Integeri22=Integer.valueOf(200); System.out.println(i2==i22); } }
可以看出,对于Integer i = 1;编译器做了额外的处理,即Integer.valueof();
Integer source code
publicstaticIntegervalueOf(inti){ assertIntegerCache.high>=127; if(i>=IntegerCache.low&&i<=IntegerCache.high) returnIntegerCache.cache[i+(-IntegerCache.low)]; returnnewInteger(i); }
可以看出Integer对于一定 范围内的数字从Cache中取得,对于额外的,调用new创建。
IntegerCache源码如下:
privatestaticclassIntegerCache{ staticfinalintlow=-128; staticfinalinthigh; staticfinalIntegercache[]; static{ //highvaluemaybeconfiguredbyproperty inth=127; StringintegerCacheHighPropValue=sun.misc.VM .getSavedProperty("java.lang.Integer.IntegerCache.high"); if(integerCacheHighPropValue!=null){ inti=parseInt(integerCacheHighPropValue); i=Math.max(i,127); //MaximumarraysizeisInteger.MAX_VALUE h=Math.min(i,Integer.MAX_VALUE-(-low)); } high=h; cache=newInteger[(high-low)+1]; intj=low; for(intk=0;k<cache.length;k++) cache[k]=newInteger(j++); } privateIntegerCache(){ } }故可以知道Integer的大小,默认是从-128到127,对于这个范围内的数组做了缓存的处理。
8.sleep方法和wait方法的区别
wait | sleep | |
所属类 | Object | Thread |
意义 | 让线程挂起 | 让线程休眠指定的时间 |
释放锁 | 是 | 否(这个跟锁本来就没有关系) |
恢复 | 1.有参:wait指定时间 2.无参:等待其他线程notify | 1.根据参数长度自动恢复。 2.异常打断 |
使用限制 | wait,notify必须持有当前对象锁的情况下调用 | 无特别 |
抛出异常 | 否 | 是 |
静态方法 | 否 | 是 |