final关键字?
- 修饰类:类不能被继承
- 修饰方法:方法不能被重写,可以被重载
- 修饰变量:变量一旦被赋值就不可以更改值
// public static final int a = 1;
public static final int a;
static {
a = 1;
}
// public final int b = 1;
public final int b;
{
b = 1;
}
修饰成员变量:如果是静态变量,需要声明时赋值或在静态代码块中赋值;
如果是非静态变量,需要在声明时赋值,或在代码块中赋值,或在构造器中赋值;
修饰局部变量:系统不会为局部变量初始化值,局部变量必须由程序员显示声明。final修饰时,既可以在定义时指定值(不可更改),也可以不指定,后续使用之前赋值(仅一次);
修饰基础数据类型:值在初始化之后不可更改;
修饰引用类型:初始化后其地址引用不可更改,值可以修改;
为什么局部内部类和匿名内部类只能访问局部final变量?(jdk1.7及其之前)
public void outPrint(final int x) {
class InClass {
public void InPrint() {
System.out.println(x);
}
}
new InClass().InPrint();
}
外部方法代码执行完后,可能内部类的代码并没有执行完,导致外部的方法的 x 变量一直被占用无法释放。解决办法就是在内部类中做一个 x 的拷贝,但是必须保证内外部的 x 值的一致性性,所以算是为了妥协这种情况,让 final 修饰 x,让其无法被更改;
重载和重写的区别?
重载:发生同一个类中,方法名必须相同,参数个数不同、顺序不同、类型不同,方法返回值和访问修饰符可以相同,重载有问题会在编译时报错;
// 编译报错
public int test(String a)
public String test(String a)
重写:发生在父子类中,方法名和参数列表必须相同,返回值范围 <= 父类,抛出的异常范围 <= 父类,访问修饰符范围 >= 父类,如果父类方法的访问修饰符是 private 则子类无法重写该方法;
List 和 Set 区别?
List: 有序可重复,按照元素添加的顺序保存,可以保存多个 NULL 值,可以使用 iterator 迭代器逐一遍历,也可以使用 get 随机访问;
Set: 无序不可重复,只能保存一个 NULL 值,只能使用 iterator 迭代器进行逐一遍历;
hashCode 与 equals?
hashCode:hashCode() 获取哈希码,int 类型的整数,作用是确定该对象在哈希表中的索引位置,任何类都包含 hashCode 方法;
equals:在 Object 类中,作用是根据两个对象的地址来判断两个对象是否相等;
关于这两个方法,有几个规则:
- 如果两个对象相等,则 hashCode 一定相同;
- 如果两个对象相等,则对两个对象分别调用 equals 方法都返回 true;
- 两个对象即使有相同的 hashCode,两个对象也不一定相等,需要调 equals 进一步判断;
equals 方法被重写,则 hashCode 也必须被重写
hashCode() 在 Object 中的默认行为是对堆上的对象产生独特值。
如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。
比如说向 HashMap 中存对象的时候,会涉及到判断对象是否相等,此时判断就会出现问题。
ArrayList 和 LinkedList 区别?
ArrayList 底层数据结构是数组,LinkedList 底层数据结构是双向链表,两者都实现了 List 接口,LinkedList 额外实现了 Deque 接口,可以作双端队列。两者的适用场景不同,ArrayList 更适合随机查找,LinkedList 更适合删除和添加。
并不能简单的对比两者的查询、删除、插入的效率,对于插入元素来说,ArrayList 需要考虑扩容问题,还要进行数据的移动,LinkedList 虽说插入元素的时候只需改变下指针指向,但是还是需要遍历先找到指定索引的元素,才能进一步移动指针,所以对于效率来说不能简单比较。
HashMap 扩容?
1.7版本
- 生成新数组
- 遍历老数组中的每个位置上的链表上的每个元素
- 取每个元素的 key,并基于新数组长度,计算出每个元素在新数组中的下标
- 将元素添加到新数组中
- 所有元素转移完成之后,将新数组赋值给 HashMap 对象的 table 属性
1.8版本
- 生成新数组
- 遍历老数组中的每个位置上的链表或红黑树
- 如果是链表,则直接将链表中的每个元素重新计算下标,并添加到新数组中
- 如果是红黑树,先遍历红黑树,先计算出红黑树中每个元素在新数组中对应的下标位置,统计每个下标位置的元素个数,如果该位置下的元素个数超过了8,则生成一个新的红黑树,并将根节点添加到新数组的对应位置,如果该位置下的元素个数没有超过8,则生成一个链表,并将链表的头节点添加到新数组的对应位置
- 所有元素转移完成之后,将新数组赋值给 HashMap 对象的 table 属性