基础篇
基本类型
- byte、short、int、long、float、double、char、boolean
- int, float占用4个字节,long, double占用8个字节
- String不是基本数据类型
java对象头
- 对象实例分为三个部分:对象头、实例数据和对齐填充
- 对象头由Mark Word、指向类的指针以及数组长度 组成
hashCode
根据对象的内存地址生成一个哈希值,两个对象可能产生同一hashcode
transient
被该变量修饰的关键字不会被序列化,当对象被反序列化时也不会被恢复
equals
-
==:基本类型比较的是变量值,引用类型比较的是内存地址 -
一没有重写equals方法,默认采用的是
==,重写了equals方法按重写的规则来public class test1 { public static void main(String[] args) { String a = new String("ab"); // a 为⼀个引⽤ String b = new String("ab"); // b 为另⼀个引⽤ String aa = "ab"; // 放在常量池中 String bb = "ab"; // 从常量池中查找 if (a == b) // false,⾮同⼀对象 System.out.println("a==b"); if (aa == bb) // true System.out.println("aa==b"); } }
字符串常量池
-
String s1 = "hello"会直接将字符串创建在常量池中 -
String s2 = new String("hello")会在堆上创建一个对象,如果常量池中没有hello,也会在常量池中一个hello对象 -
地址比较
String s1 = "11"; String s2 = "11"; System.out.println(s1==s2); // true String s3 = new String("11"); System.out.println(s1==s3); // false
StringBuffer & StringBuilder
- String是final修饰的,每次操作都会产生新的String对象
- StringBuffer是线程安全的,每个方法都加了
synchronized - StringBuilder线程不安全
jdk8新特性
- 元空间替代了永久代
- 引入lambda、Stream、CompletetableFuture
final
- 修饰类:表示类不可被继承
- 修饰方法:表示方法不可被子类覆盖,但是可以重载
- 修饰变量:如果是基本数据类型的变量,则其数值⼀旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另⼀个对象
final、finally、finalize
final:修饰的类不能被继承,修饰的方法不能被重写,修饰的变量不可被重新赋值finally:用于try-catch中释放资源finalize:对象被jvm回收前会执行这个方法
重载和重写
-
重写:子类重写父类方法
-
重载:只和方法名、参数有关,方法名和参数加在一起计算方法签名,只要签名不同就不会报错
自动拆箱和装箱
装箱:调用valueOf()将基本数据类型转换成对象,如 Integer.valueOf(int)
拆箱:将包装类型转换为基本数据类型;如:Integer.intValue()
深拷贝和浅拷贝
深拷贝会重新创建一个对象然后指向它;浅拷贝传递的是对象的地址,两个变量会指向同一对象
反射
动态的获取类的结构信息,如字段、方法、构造函数,动态创建对象,调用对象的属性、方法
泛型
-
在编译时进行类型检查,确保不会出现类型不匹配问题,比如一个集合类型是
List<String>,如果向集合里面添加Integer类型的数据就会编译时报错 -
泛型擦除:只有编译的时候泛型有效,运行时泛型的类型信息会被擦除,变为Object
抽象类
- 抽象类被abstract修饰,不能被new,其他都和正常类一样
- 抽象方法不能有方法体,有抽象方法的类必须是抽象类
- 抽象方法要么在子类中被重写,要么在子类也是抽象类
接口和抽象类区别
- 接口中不能有构造函数,抽象类中可以有
- 一个类可以implements多个接口,但只能extends一个抽象类;接口本身可以通过extends扩展多个接口
静态方法和实例方法
静态方法访问本类的成员时,只允许访问静态成员变量、方法,而不允许访问非静态的成员变量和方法
对象实例化过程
- 父类的静态成员变量和静态代码块
- 子类的静态成员变量和静态代码块
- 父类成员变量和构造块
- 父类的构造函数
- 子类成员变量和构造块
- 子类的构造函数
异常类层次结构
- 异常:空指针、数组索引越界、类找不到
- Error:内存溢出、栈溢出

Throwable的方法:
public string getMessage():返回简要描述public string toString():返回详细信息public void printStackTrace():在控制台上打印
集合篇
Collection
ArrayList扩容机制: 初始容量是10,当ArrayList中元素数量超过当前容量时,新建一个数组,容量是原来的1.5倍,然后将原来数组中的元素复制到新数组中Arraylist&Vector: 两者结构一样,但 Vector是线程安全的,所有方法都加了synchorized
Map
-
TreeMap:基于红黑树实现的Map集合,key可以按照自定义的规则进行排序 -
HashMap:- HashMap的结构是数组+链表+红黑树,
HashMap使用key的hashcode()计算哈希值,当发生哈希冲突时,节点被添加到链表中; - 默认容量是16,负载因子是0.75,当存储的元素超过
16 * 0.75 = 12个时会促发扩容操作,每次扩容容量x2,并重新计算所有元素的哈希值,并移动到新的数组中 - 当链表长度超过8,链表会转换为红黑树;如果树中元素数量低于6,红黑树会转换回链表,红黑树能够在最坏情况下将查找的复杂度从
O(n)降低到O(log n) LinkedHashMap在HashMap的基础上给每个节点增加了前后指针,节点间形成了一个双向链表,可以记录元素的插入顺序
- HashMap的结构是数组+链表+红黑树,
-
HashSet:- 将要放入的对象作为key,调用HashMap方法,判断两个对象key是否一样,如果一样对象重复,添加失败;如果key不一样,添加成功
- HashMap判断key重复:判断hashcode()和equals()
-
HashMap和HashSet:-
HashMap允许
null键和null值,HashSet也允许存null值 -
HashSet底层使用HashMap实现的,在构造器中是new 了 HashMap,大部分方法都是调用的HashMap中的方法
private static final Object PRESENT = new Object(); public HashSet() { map = new HashMap<>();} public boolean add(E e) { return map.put(e, PRESENT)==null; }
-
-
HashMap和HashTable:- HashMap允许存
null的键或值,HashTable不允许 - HashMap线程不安全,HashTable线程安全(大部分方法加了
synchronized修饰)
- HashMap允许存
-
ConcurrentHashMap和HashTable:- HashTable与ConcurrentHashMap都能保证线程安全,但HashTable性能较低
- HashTable是在方法上进行加锁,所有的操作都用一个锁,效率低;ConcurrentHashMap采用的是
CAS+synchorized,如果某个节点为空则通过CAS插入数据,如果不为空则使用synchorized锁定链表头节点