基础
-
序列化:将一个对象编码为字节流称为序列化,相反的处理过程称为反序列化
-
重写:子类重写父类方法
-
重载:只和方法名和参数有关,如果返回值类型不一样,编译器不会报错
-
String不是基本数据类型,基本类型:byte、short、int、long、float、double、char、boolean
-
varchar(n):n代表字节数
-
值传递与引用传递
-
值传递 :接收的是实参值的拷贝,会创建副本,对形参的改变不影响实参
-
引用传递 :接收的是实参所引用的对象在堆中的地址,不会创建副本,对形参的改变将影响到实参
-
-
反射:程序运行时获取类的相关信息(方法、属性、构造函数)
==和equals
-
==
比较的是两个对象是否是同一对象,对比的是栈中的值,基本数据类型是变量值,引用类型是堆中内存对象的地址 -
一个类没有重写equals方法,默认采用的是
==
(Object类中定义的),重写了equals方法按重写的规则来。String重写了equals方法,比较的是字符串内容
java
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");
}
}
final
-
修饰类:表示类不可被继承
-
修饰方法:表示方法不可被子类覆盖,但是可以重载
-
修饰变量:如果是基本数据类型的变量,则其数值⼀旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另⼀个对象
hashCode()
对对象使用算法产生哈希值,哈希值代表了对象的特征,两个对象可能产生同一hashcode
深拷贝和浅拷贝
深拷贝会重新创建一个对象然后指向它;浅拷贝传递的是对象的地址,两个变量会指向同一对象
状态码
- 200 正常
- 403 Forbidden,服务器拒绝了请求
- 404 找不到对应资源
- 500 服务器内部错误
自动拆箱和装箱
装箱:调用valueOf()
将基本数据类型转换成对象,如 Integer.valueOf(int)
拆箱:将包装类型转换为基本数据类型;如:`Integer.intValue()
静态方法和实例方法区别
静态方法访问本类的成员时,只允许访问静态成员变量、方法,而不允许访问非静态的成员变量和方法
transient 关键字的作用
被该变量修饰的关键字不会被序列化,当对象被反序列化时也不会被恢复
接口和抽象类区别
一个类可以implements多个接口,但只能extends一个抽象类;接口本身可以通过extends扩展多个接口
成员变量与局部变量的区别
-
成员变量会自动初始化;局部变量必须手动赋值
-
成员变量是对象的⼀部分,随着对象的创建而存在;而局部变量随着方法的调用而动消失
-
成员变量可以被 public , private , static 等修饰符所修饰,而局部变量不能被访问控制修饰
String、StringBuffer、StringBuilder
- String是final修饰的,每次操作都会产生新的String对象
- StringBuffer是线程安全的,每个方法都加了
synchronized
- StringBuilder线程不安全
一般优先用StringBuilder,多线程情况下使用StringBuffer
java异常类层次结构
markdown
finally块: ⽆论是否捕获或处理异常, finally 块⾥的语句都会被执⾏。当在 try 块或 catch 块中遇到 return 语句时, finally语句块将在⽅法返回之前被执⾏
Throwable
类常用方法
public string getMessage()
:返回异常发生时的简要描述public string toString()
:返回异常发生时的详细信息public void printStackTrace()
:在控制台上打印Throwable
对象封装的异常信息
如何选用集合
Collection集合体系
Map集合体系
List,Set,Map区别
- List : 存储的元素是有序的、可重复的。
- Set :HashSet存储的元素是无序不可重复的、LinkedHashSet存储的元素是有序不可重复的
- Map:使用键值对(kye-value)存储,Key 是不可重复的,value可重复的
ArrayList扩容机制
添加元素时,先判断数组需要的最小容量 :如果最小容量大于数组长度,扩容1.5倍;如果是空数组,则指定数组最小容量为10DEFAULT_CAPACITY
Arraylist 与 LinkedList
- Arraylist 底层使用的是 Object 数组;对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针
- LinkedList底层使用的是双向链表;对于新增add()和删除操作remove(),LinkedList比较占优势,因为ArrayList要移动数据
HashMap 与 HashSet
HashSet底层使用HashMap实现的,在构造器中是new 了 HashMap,大部分方法都是调用的HashMap中的方法
HashMap存放的是键值对,HashSet存放的是一个个元素
java
private static final Object PRESENT = new Object();
public HashSet() { map = new HashMap<>();}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
HashSet如何检查重复
将要放入的对象作为key,调用HashMap方法,判断两个对象key是否一样,如果一样对象重复,添加失败;如果key不一样,添加成功
HashMap判断key重复:判断hashcode()和equals()
HashMap 与 HashTable
-
对 Null key的支持:HashMap支持存储为空的key,HashTable不允许支持为空的key
-
线程是否安全:HashMap线程不安全,HashTable线程安全,因为HashTable内部的方法基本经过
synchronized
修饰(效率低,全局一把锁) -
底层数据结构:HashMap中当链表的长度大于8,并且数组的长度达到64时就会把链表转换为红黑树;HashTable没有这样的机制
HashMap的结构
HashMap是数组+链表+红黑树实现(红黑树:能够保证平衡的二叉查找树)
当HashMap中元素个数超过 数组大小*loadFactor 时就会扩容。默认数组大小Capacity为16,每次扩容就把数组大小扩大一倍;loadFactor为负载因子,默认为0.75,负载因子的大小决定了HashMap的数据密度
当HashMap中一个链的对象个数达到8个,并且数组容量capacity达到64,这个链表就会用红黑树表示,如果没有达到64就先扩容解决。如果树中结点个数低于6个,树就会转换为链表
ConcurrentHashMap
jdk1.8 采用Node数组 + 链表 +红黑树,和HashMap结构相同,synchronized 只锁定当前链表或红黑树的首节点,这样只要 hash 不冲突,就不会阻塞
线程状态
- NEW:新建
- RUNNABLE:准备就绪
- BLOCKED:阻塞
- Waiting:一直等待
- TIMED_WAITING:过时不候
- Terminated:终结
多线程并发
进程和线程区别
-
一个进程中可以有多个线程,多个线程共享进程的堆和元空间
-
线程和进程最大的不同在于各进程是独立的,而各线程则不⼀定,因为同一进程中的线程极有可能会相互影响
synchronized
synchronized 关键字可以保证被它修饰的方法或者代码块在任意时刻只能有⼀个线程执行
synchronized 实现同步的基础:Java 中的每一个对象都可以作为锁,具体表现为以下 3 种形式:
- 对于普通同步方法,锁是当前实例对象
- 对于静态同步方法,锁是当前类的 Class 对象
- 对于同步方法块,表示进⼊同步代码块前要获得给定对象的锁
volatile
-
用volatile修饰的变量,保证每次读取和写入都会从主内存中读取
-
使⽤volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行
正常情况:1. 为对象分配内存,2. 初始化,3. 将对象引用指向对应内存地址
指令重排可能变成1 3 2,这样可能会发生问题
ThreadLocal
ThreadLocal --> (Thread / ThreadLocalMap)
java
public class ThreadLocal<T> {
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); // 获取当前线程对象的ThreadLocalMap
if (map != null)
map.set(this, value); // 向map中放值,key为ThreaLocal,值为要放的值
else
createMap(t, value);
}
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> { // 弱引用
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
} // Entry
} // ThreadLocalMap
} // ThreadLocal