1、String、StringBuffer、StringBuilder区别
String类,被final修饰,不能被继承,也不能被改变,拼接的时候会生成新的对象。
StringBuffer 间接实现了Appendable接口,可以拼接,操作字符串的接口都加了线程同步机制,线程安全,但效率较低。
StringBuilder间接实现了Appendable接口,可以拼接,相对于StringBuffer 而言,操作字符串的接口没有加线程同步机制,所以线程不安全,但效率较高。
2、进程和线程的区别
进程是系统分配资源和调度的基本单位,线程是任务调度和执行的最小单位。
进程可以简单理解是一个程序就是一个进程,一个进程可以有多个线程,线程比进程更轻量级。
3、final,finally,finalize的区别
final 修饰的常量,不能改变
finally是和try catch配合使用,finally包含的代码块始终都会执行
finalize 是对象的方法,当对象在被回收之前会调用这个方法。
4、Serializable 和Parcelable 的区别
serialVersionUID的作用,用于验证用于序列化和反序列化得java类得版本是否是能兼容的版本。如果客户端的序列化的java类serialVersionUID和服务端反序列化的java类的serialVersionUID不一致,系统则认为序列化和反序列化的对象不一致,则会抛异常。如果java类的serialVersionUID一致,属性名有部分不一致,则会抛弃掉不一致的,反序列化成功一致的属性。
Serializable是java的技术,Parcelable是Android的技术。
Serializable使用了java反射技术,并且期间会产生临时对象,内存消耗比Parcelable大。
如果是内存中序列化传输数据,建议用Parcelable。如果是网络传输,或者是本地持久化,建议用Serializable。
5、静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?
静态属性和静态方法可以被继承,但不可以被重写。
6、string 转换成 integer的方式及原理
看Integer.parseInt()的源码,先对传入的字符串进行校验,是不是为null,长度是否大于0等等,然后将字符串拆分成单个的字符,判断单个字符是不是数字,都是数字的话,按Unicode的编码,将字符的数字转为int类型的数字返回
public static int parseInt(String s, int radix)
throws NumberFormatException{
if (s == null) {
// Android-changed: Improve exception message for parseInt.
throw new NumberFormatException("s == null");
}
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
int result = 0;
boolean negative = false;
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;
if (len > 0) {
......
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result;
}
7、哪些情况下的对象会被垃圾回收机制处理掉?
针对强引用申明的对象,java虚拟机的可达性分析算法,java虚拟机会把一些对象作为GCRoot,把GCRoot作为起点,沿着引用链查找,如果某个对象不能找到,就认为这个对象是可回收的对象。
被软引用、弱引用或者是被虚引用接收的对象,
软引用是内存不够的时候,会被GC回收掉,
弱引用是只要系统执行GC的时候,就会被回收掉。
8、静态代理和动态代理的区别,什么场景使用?
静态代理是一个代理类只能代理一个类。动态代理能代理实现一个接口下的所有类。
静态代理中代理类需要实现被代理类中的所有接口方法,而动态代理无需实现所有接口方法。
静态代理在编译期就可以知道代理什么,而动态代理只有在运行期才知道代理什么。
静态代理的使用场景就是如果类A访问类B不方便,就可以用代理类P,P中含有类B的引用。然后类A就可以用类P来访问类B的方法或者属性了。
动态代理是如果以上静态代理的的方法太多,类P过于庞大,就不利于维护,就可以用动态代理。
9、Java中实现多态的机制是什么?
多态指的是一个变量的引用到底是指向哪个类得实例,该引用调用的方法到底是哪个类实现的方法,必须有程序运行期间才能决定。该引用在运行期间,有可能是子类的实例,也有可能是父类的实例,这种引用在运行期间有多种运行状态,就称为多态。
实现机制是,java运行数据区里面有个方法区,方法区里面有方法表,方法表里面有记录方法的入口地址,方法入口的寻找方式就是先去当前引用指向的类里面寻找,找到了就是当前类得方法入口,如果当前类中没有这个方法,就去父类寻找,在父类寻找到了入口就在父类代码中。
10、说说你对Java反射的理解
反射就是程序在运行当中,允许对程序本身进行操作,比如创建某个对象,获取类所有成员变量以及方法,包括修改变量的值,调用某个对象的方法。
11、String为什么要设计成不可变的?
因为为了避免因程序创建大量重复的字符串造成内存大量消耗,Java运行时数据区提供了字符串常量区作为字符串的缓存区域,只要用申明创建的字符串,先到这个区域寻找,如果匹配上了,就直接返回现有字符串的引用。所以这个区域的所有字符串都是被共享的,如果其中一个String对象改了字符串内容,所有引用这个字符串的对象都会随之改变。所以会设计成不可变的。
12、List,Set,Map的区别
List是有序的,可以添加相同元素,包括null。
Set是无序的,不可以添加相同元素,最多只能添加一个null。要想实现有序存储可以用TreeSet,TreeSet是通过实现一个Conparator或者是Comparable来维护排序。
Map是无序的,以Key-Value 的键值对形式存数据,Map的key是不可以重复的,最多只能有一个null,但Value可以重复,可以有多个null。
List,Set,Map都是接口,但List,Set都是继承Collection接口,Map没有继承。
13、ArrayMap和HashMap的对比
ArrayMap的工作原理是,ArrayMap中有2个数组,一个是mHashes,存放key的hash值,以及mArray,存放key-value键值对。mHashes是有序的数组。mArray的数组长度是mHashes的两倍。
插入元素,先取key的hash值,然后用hash值算出在mHashes中的index,然后将key和value放到mArray数组的2*index和2*index+1的位置。