java知识体系整理(一)基础知识

版权声明:可以转载,需注明出处 https://blog.csdn.net/wthfeng/article/details/88946210

基础知识

基础知识主要涉及java语法及常见知识点。包括IO、类加载,反射、注解、异常,集合类等。下面以这几个大类分别做汇总,并引出其中若干小问题。

知识梳理

  1. java的集合体系及继承关系,以及主要类的用法及原理。
  2. java类加载机制
  3. BIO与NIO、AIO区别及联系,什么是Reactor模型。
  4. 异常类继承关系,受检异常和非受检异常。
  5. 反射知识梳理。
  6. 其他java特性(枚举,注解,synchronized和volatile)
  7. 序列化相关。
  8. 多线程相关

以下就分别从这几个方面来讲讲java基础知识。

java集合

在这里插入图片描述

上图是java Collection主要类成员。基本上Collection为集合框架的最抽象接口。其下根据功能需要又分为SetListQueue3个主要接口。分别表示无序不重复集合(Set)、有序集合和队列。

在这里插入图片描述

  1. HashSet底层实现由HashMap完成。HashMap的key即为HashSet的值。value则为一固定的Object对象。
   // 部分HashSet源码
   
   private transient HashMap<E,Object> map;
   private static final Object PRESENT = new Object();
   
    public HashSet() {
        map = new HashMap<>();
    }
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
  1. LinkedHashSet实现由LinkedHashMap完成。而LinkedHashMap是HashMap和LinkedList的结合体。由HashMap保证Map属性,再由链表将Map中的元素以插入顺序链起来。LinkedHashSet调用了HashSet的构造函数。
 // 此构造函数专为LinkedHashSet使用 
 HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
 }
  1. TreeSetTreeMap实现,同上一样,TreeSet调用了TreeMap的方法。
  // TreeSet部分源码
  private static final Object PRESENT = new Object();
  public TreeSet() {
        this(new TreeMap<E,Object>());
  }

可以看到,和之前HashSet之于HashMap是类似的处理。TreeMap是一个有序的Map结构,底层通过红黑树实现。

  1. Queue 队列数据结构可简单分为双端队列(Deque)和阻塞队列(BlockingQueue)和优先级队列(PriorityQueue)。主要类结构图已如上图所示。
  2. 队列可用于生产者、消费者模型,尤其阻塞队列,需掌握。
  3. List的实现主要分为数组和链表实现两种。按线程安全又分为线程安全和线程非安全。CopyOnWriteArrayList写时复制数组。
  4. 有关队列的入队出队方法及解释
操作 返回特殊值 抛出异常
插入(队尾) offer(e) add(e)
删除(队首) poll() remove()
查询(获取队首元素) peek() element()

对于阻塞队列BlockingQueue)而言,又多了阻塞和超时的方法。

操作 返回特殊值 抛出异常 阻塞 超时退出
插入(队尾) offer(e) add(e) put(e) offer(e,timeout,unit)
删除(队首) poll() remove() take() poll(timeout,unit)
查询(获取队首元素) peek() element()
java Map结构

在这里插入图片描述

以上是Map的类结构图。除了现已不再推荐使用的Hashtable以外,主要有3类Map。ConcurrentHashMap基于Hash表和分段锁实现,线程安全,在多线程环境最常使用的Map。HashMap基于Hash表实现,日常使用最广的Map。TreeMap,基于红黑树实现。插入元素排序。

集合常见问题

有关java集合的问题挺多,常见如HashMap底层数据结构和实现原理,ConcurrentHashMap原理等。这里总结下以备忘,常看常新。

  1. HashMap在高并发会出现什么问题,能否画出来?此问题在java8还有吗?
  2. TreeMap原理?有关红黑树的左旋和右旋?
  3. java集合类继承关系都是怎样的,能否画一下?
  4. 阻塞队列原理?
  5. 手写实现生产者消费者模型
  6. 优先级队列和延时队列实现原理

java类加载机制

类加载顺序

类的加载过程是: 加载->连接(验证,准备,解析)->初始化->使用->卸载。具体解析如下:

加载 : 将class二进制字节流(文件或jar包或字节流等各种形式)加载到内存中。

验证 :包括文件格式、元数据,以及字节码等验证,看是否合法。

准备 : 为类变量分配内存,设初始值(零值)等。

解析 : 符号引用替换为直接引用。加载这个类所引用的其他所有类。

初始化: 初始化类变量或其他资源。是执行方法的过程。JVM会保证在执行时,其父类的被执行(接口则不会执行父类cinit,除非被用到)。是线程安全的,由JVM保证。

注意

  1. 类加载阶段不会涉及类构造器的调用,显然那时还不一定有对象实例的产生。
  2. 类变量在准备阶段分配内存并赋零值,在初始化阶段赋真正的值。
  3. 方法实际上是JVM收集所有类变量的赋值语句和静态语句块形成的。
  4. 两个类是否相等的前提是,都由一个类加载器加载。若不是,则一定不相等。(即使是同一个类加载器的两个实例加载出来的类,也不相等)。
  5. 初始化某类数组不会导致该类初始化。
  6. 访问经static和final共同修饰的字段为编译期常量,不会导致该类初始化
双亲委派模型

三种类加载器,分别是BootstrapClassLoaderExtClassLoaderAppClassLoader加载器。从顶到下排列。当前类加载器会先将加载任务委托给父类加载,父类一级一级加载,直到BootstrapClassLoader加载不了(加载不了的意思是指其classpath中没有要加载的类),则向下流转。直到其父类都不能加载,自己才尝试加载。

常见问题
  1. 实现自己的类加载器
  2. 哪些情况会导致类初始化

java IO

常见问题
  1. BIO、NIO的理解?BIO的阻塞理解和NIO的非阻塞理解?
  2. 阻塞模型
  3. AIO的概念
  4. IO涉及到的设计模式
  5. 手写文件读写、缓冲区读写等
java主要IO类

字节流、字符流四个主要接口。为InputStream、 OutputStream、Writer和Reader。前2个为字节流,后2个为字符流。主要方法为write(int b)read()

对于字节流InputStream,read()方法返回int值。

public abstract int read() throws IOException;

返回的int值范围在-1 - 255之间,-1表示流结束。

同理,OutputStream , write(int b) 方法参数为int,

public abstract void write(int b) throws IOException;

传入的参数值只有低8位有效,其余16为会被忽略,也即不能超过255。

为什么BIO会阻塞

讨论为什么传统IO会阻塞?

在系统内核,有关于socket的2个缓存区比较重要。分别是socket的读缓存区(read buffer)和写缓冲区(write buffer)。

流程如下:首先通过操作socket写入数据,先写入写缓冲区(write buffer)系统有一个专门的线程用于检查写缓冲区,有数据后将数据送入网卡设备经网络传送出去。

同时,系统内核有线程会将收到的数据拷贝到socket读缓冲区供用户空间使用。

两个缓冲区的大小是有限的,当写缓冲区写满后,会阻塞写操作,当读缓冲区为空后,会阻塞读操作。

所以,当有线程专门用于读取时,若读不到指定大小的字节,会阻塞该线程。

所以总结来说:

  1. 在我们使用中调用的read/write方法实际上只是将数据写到缓存区或从缓存区拿数据,对于写。它只是将数据写到缓冲区去了,至于什么时发送,由操作系统决定。对于读,只是从系统缓存区读取数据而已。
  2. 对于阻塞读而言,read的原理是 没有数据会一直等待,有数据则会返回(若多于指定大小,会返回指定大小,若小于指定大小,则能返回多少返回多少)。
  3. 对于非阻塞读,没有数据立即返回,有数据则有多少读多少。所以,对于读,阻塞和非阻塞的区别在于,没有数据时是否会立即返回。

当使用IO读取数据时,实际上底层使用的是socket操作的数据。读取时读取socket的 read buffer。若socket读缓冲区没有足够的数据时,读取操作就会阻塞,直到有了足够数据。

其他IO参考文章

  1. java I/O体系总结
  2. BIO、NIO以及AIO特点及比较

异常体系

在这里插入图片描述

java的异常分为错误和异常。

错误(Error)指发生非常严重的异常,通常是JVM发生的。如
内存溢出(OutOfMemoryError)、线程死亡(ThreadDeath)等。这些异常发生时,JVM一般会终止程序,所以一般也不捕获。

Exception指程序发生的异常。分为运行时异常(RuntimeException及其子类)和非运行时异常(其他Exception子类)。运行时异常有空指针异常(NullPointerException)、下标越界异常(IndexOutOfBoundsException)、类型转换异常(ClassCastException) 等。一般是程序错误引起,在运行时才能发现的异常。

非运行时异常也称为受检异常。指必须捕获的异常,如IOException和SQLException等。

反射

  1. 了解反射知识,熟练引用发射方法。

序列化

  1. transient作用
  2. readObject和writeObject
  3. 序列化id
  4. Serializable

多线程相关

  1. synchronized和lock锁区别
  2. AQS实现原理
  3. lock锁实现原理,与AQS关系(线程被阻塞后放在哪里,被await住又放在哪里)
  4. CAS什么意思
  5. 有几种线程池,分别是什么意思
  6. 线程池参数含义
  7. 线程池工具类(CountDownLatch等原理)
  8. ThreadLocal原理及场景,它如何处理垃圾回收
  9. 阻塞队列及原理

其他知识点

  1. synchronized底层原理
  2. volatile作用及原理
  3. Java内存模型介绍
  4. 偏向锁、共享锁概念及理解
  5. wait、notify通知机制
  6. StringBuffer和StringBuilder

猜你喜欢

转载自blog.csdn.net/wthfeng/article/details/88946210