Java 学习路线图

本文最后更新于:2022年12月18日 下午

本文只列举了一些大纲,如果需要细节知识的读者请移步《Java编程思想》,这也是我的入门书籍,它给了我很大的帮助

Java 学习路线图

Java 核心

类和对象

类、对象关系

  1. 什么是类

    类是对某一种事物的抽象描述,是具备某些共同特征的实体的集合,它是一种抽象的数据类型,它是对所具有相同特征实体的抽象

  2. 什么是对象

    对象是类的实例,是一个真实世界中的实体,对象与实体是一一对应关系的,意思就是现实世界的每一个实体都是一个对象,所以对象是一个具体的概念。对象是一种个性的表示,表示一个独立的个体,每个对象拥有自己独立的属性,依靠属性来区分不同对象。

  3. 对象与类的关系

    类是对象的模版,对象是类的实例

创建对象的几种方式

  1. 使用new关键字
  2. 使用反射机制
  3. 使用clone方法
  4. 使用反序列化

类的成员变量和方法

  1. 成员变量

    1. 成员变量定义在类中

    2. 成员变量随着对象的创建而创建,随着对象的消失而消失,存在对象的堆内存中

      这里可以联想到动态数组,如果一个动态数组中的一个元素引用了一个对象,但是在扩容是放弃了之前的使用过的内存,那么这块变量很有可能还是存在堆内存当中

    3. 成员变量有默认的初始值

  2. 方法

  3. 类的构造函数

  4. Object

  5. Object类是所有类的父类

  6. 封装、继承、多态

    1. 封装
      1. 定义:隐藏对象的属性和实现的细节,仅仅对外公开接口,控制在程序中的属性的读和修改的访问级别
      2. 目的:增强安全性和简化编程
      3. 封装的基本要求,把所有对象私有化,对应该暴露的属性使用getter setter方法,如果类有带参数的构造方法,那么一定要重写一个不带参数的构造方法.
    2. 继承
      1. 定义:当多个类具有相同特征和行为时,可以把多个类的相同部分抽取出来放在一个类中作为父类,其它的类继承这个类
      2. 目的:提高代码的复用
    3. 多态
      1. 定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
      2. 目的:消除类型之间的耦合关系

JDK常用的类

System慎用

  1. System.out.printf
  2. System.out.println
  3. System.arraycopy(Object src, int srcPos,Object dest, int destPos,int length)

基础类型的包装类

  1. Integer
  2. Long
  3. Byte

String StringBuilder StringBuffer

  1. String 每一个new出来的对象都是不一样的,即使你使用了相同的字面量

    1. equals方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      public boolean equals(Object anObject) {
      if (this == anObject) {
      return true;
      }
      if (anObject instanceof String) {
      String anotherString = (String)anObject;
      int n = value.length;
      if (n == anotherString.value.length) {
      char v1[] = value;
      char v2[] = anotherString.value;
      int i = 0;
      while (n-- != 0) {
      if (v1[i] != v2[i])
      return false;
      i++;
      }
      return true;
      }
      }
      return false;
      }
    2. split方法:用于字符串切割

    3. contains方法:是否包含子字符

    4. replace方法:字符串替换

    5. subString方法:剪切字符串

    6. trim方法:去除空格

  2. StringBuilder 使用了内部数组保存数据,内部数组如果不指定则有一个默认的大小,如果超出了内部数组的容量则会扩容

    1. append方法:往内部数组中添加元素
    2. toString方法,根据内部数组保存的内容转化为一个String对象

    为什么要使用StringBuilder

    StringBuilder一般使用在有字符串拼接的情况下,如果使用String则会产生大量无用的对象,而使用StringBuilder则不会

  3. StringBuffer

    StringBufferStringBuilder功能类型,可以看到StringBufferStringBuilder都继承了AbstractStringBuilder类,并且都基本上只使用了父类的方法,StringBuffer只是在方法上面增加了一个synchronized关键字,这个关键字的作用是给方法加锁,表示同一个时间端只能有一个线程访问这个方法,

    如此就可以做到线程安全

正则表达式类

Date

  1. 构造函数

    1. public Date(long date) 根据Unix时间戳来生成Date对象
    2. 无参构造函数:生成当前时间的Date对象,实际上是调用了Date(System.currentTimeMillis())这也是多态的一个体现
    3. after(Date when) 如果调用此方法的Date对象在指定日期之后返回true
    4. before(Date when) 如果调用此方法的Date对象在指定日期之前返回true
  2. SimpleDateFormat

    1. 指定时间生成字符串
    1
    2
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String s = sdf.format(date)
    1. 生成指定时间的Date对象
    1
    2
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date = sdf.parse("2006-01-02 15:03:04")

Random

  1. math包中的random方法,只能生成double类型的0~1之间的随机数
  2. Random

Math

  1. round(double x) 返回x的四舍五入的值
  2. ceil(double x) 向上取整
  3. floor(double x)向下取整
  4. abs()

Scanner

看看就好

抽象类

抽象类规则:

  1. 抽象类不能被实例化
  2. 抽象类中的方法可以包含方法体也可以不包括方法体
  3. 构造方法、静态方法不能声明为抽象方法

接口

接口的特性

  1. 接口中的每一个方法也是隐式抽象的,接口中的方法会饿毙隐式指定为public abstract
  2. 接口中可以包含变量,接口中的变量会被隐式指定为public static final
  3. 接口可以多继承、多实现

JDK 1.8+接口可以有静态代码块和方法体,定义方法体使用了预留关键字default

异常

Java异常框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    ,---------.                  
|Throwable|
|---------|
|---------|
`---------'
^
|
----------
| |
| |
,-----. ,---------.
|Error| |Exception|
|-----| |---------|
|-----| |---------|
`-----' `---------'
^
|
-------------------
| |
| |
| |
,-----------. ,----------------.
|IOException| |RuntimeException|
|-----------| |----------------|
|-----------| |----------------|
`-----------' `----------------'

异常通常被分为三类:

  1. 错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
  2. 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
  3. 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。

集合

集合框架

Java中的集合框架大致可以分为CollectionMap类,两者的区别如下:

  1. Collection是单列集合;Map是双列集合
  2. Collection中只有Set系列要求元素唯一;Map中键需要唯一,值可以重复
  3. Collection的数据结构是针对元素的;Map的数据结构是针对键的。

Collection体系

Collection包含了两大体系:ListSet

  1. List 存取有序,有索引,可以根据索引来取值,元素可以重复
  2. Set 存取无序,元素不可重复
List

List主要学习以下两种:ArrayListLinkedList

ArrayList底层使用了数组实现,所以查询速度是O(1),所以查询速度快,但是增删速度慢

LinkedList是基于双向循环链表结构实现的,所以查询速度为O(n),但是增加删除速度快

Set

Set集合的特点:元素不会重复,存取是无序的,无下标Set集合下面有:HashSet LinkedHashSet TreeSet

LinkedHashSet是基于链表和hash表共同实现的,所以具有存取有序,元素唯一的特点

TreeSet: 存取无序,元素唯一,可以进行排序(排序是在添加的时候进行排序)

Map体系

Map是一个双列集合,其中保存的是键值对,键要求保持唯一性,值可以重复,

Map最重要的一个结构就是HashMap

课后习题

  1. 实现一个简单的ArrayListLinkedList,LinkedList可以考虑使用双向循环链表作为低层实现,存储的数据类型可以只考虑int类型

范型

范型的意思就是就可以编写模版代码来适应任意类型

  1. 范型类
1
2
3
4
//  定义一个泛型类
public class Generator<T> {
T item;
}
  1. 范型方法
1
2
3
4
5
6
7
public class Generator<T> {
T item;
// 定义一个泛型方法
public T getItem(){
return this.item;
}
}
  1. 范型接口
1
2
3
4
//定义一个泛型接口
public interface Generator<T> {
public T next();
}

课后习题

  1. 使用范型支持ArrayList多类型存储

注解

注解可以理解其为标签,标签本身并没有什么用处,但是我们可以给这个标签赋予含义

注解的声明和元注解

1
2
3
4
5
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {

}

我们使用@interface声明了一个注解,并使用@Target注解传入ElementType.METHOD参数来表示这个注解只能应用在方法上,@Retention(RetentionPolicy.RUNTIME)则用来表示改注解生存期是在在运行时.

其中@Target@Retention是由Java提供的元注解,元注解的意义在于标注其它注解

@Target注解

@Target可以用来约束任何可以应用的地方,其中ElementType是一个枚举类型

如果一个注解未指定@Target注解则表示可以应用在任意元素上

@Retention注解

@Retention用来约束注解的生命周期,分别有三个值,源码级别(source),类文件级别(class)或者运行时级别(runtime),其含有如下:

SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)

CLASS:注解在class文件中可用,但会被JVM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机中),请注意,当注解未定义Retention值时,默认值是CLASS,如Java内置注解,@Override@Deprecated@SuppressWarnning

RUNTIME:注解信息将在运行期(JVM)也保留,因此可以通过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息),如SpringMvc中的@Controller@Autowired@RequestMapping等。

文件、IO

文件IO操作是重点中的重点,Java中的IO是以为基础进行输入输出的

IO流的划分

IO流我们可以使用两种形式来划分:

  1. 输入输出流:程序从外部读取数据使用输入流(InputStream、Reader),程序向外部写数据使用输出(OutputStream、Writer)
  2. 字节流、字符流:这是按照流中最小数据单元来区分的,字节流以8位作为一个数据单元,字符流以16位作为一个数据单元,其中字节流命名主要以InputStream、OutputStream为后缀,而字符流主要以Reader、Writer为后缀

主要的类和方法

IO的最基本的四个类为:InputStream、OutputStream、Reader、Writer,这四个类均为抽象类,我们具体使用的时候更多的是使用它们的子类,而使用它们作为声明,比如:InputStream inputStream = new FileInputStream(file),(想想这里是为什么)

下面列举了基本的方法

InputStream
方法方法介绍
public abstrcat int read()读取一个字节的数据,返回值为所对应的ANSCii码值
public int read(byte b[])读取b.length个字节的数据填充到数组中,返回具体读了多少字节的数据,如果到了文件末尾则返回-1
public int read(byte b[], int off, int len)从第 off 位置读取 len 长度字节的数据放到 byte 数组中,流是以 -1 来判断是否读取结束的
public long skip(long n)跳过多少个字节不被读取
public int available()返回有多少个字节可被读取
public void close()关闭流,释放资源
public synchronized void mark(int readlimit)标记读取位置,下次还可以从这里开始读取,使用前要看当前流是否支持,可以使用 markSupport() 方法判断
public synchronized void reset()重置读取位置为上次 mark 标记的位置
public boolean markSupported()判断当前流是否支持标记流,和上面两个方法配套使用
OutputStream
方法方法介绍
public abstract void write(int b)写入一个字节
public void write(byte b[])写入b数组中的数据
public void flush()把缓冲区中的数据刷入文件中
public void close()关闭流
Reader

InputStream类似

Writer

OutputStream类似,多出

方法方法介绍
public Writer append(char c)追加一个字符

常用的类

  1. FileInputStream、FileOutputStream,文件读写

  2. BufferedInputStream、DataInputStream、BufferedOutputStream、DataOutputStream用作缓冲区

  3. ByteArrayOutputStream常用缓存

  4. FileReader、FileWriter 文件读写

  5. BufferedWriter、BufferReader 用作缓冲区

课后习题

  1. 使用流进行文件的拷贝
  2. 使用流进行图像的翻转

线程

线程和进程的区别

进程是程序的一次动态执行过程,而线程是进程的一个执行单元,一个进程可以拥有多个线程,多个线程之间可以共享一个进程的资源

为什么需要多线程

可以发挥多处理的强大功能,简单来说就是为了加快程序的运行效率

Java实现多线程的几种方式

  1. 实现Runnable接口,实现run方法
  2. 继承Thread类,实现run方法,其中Thread也是实现了Runable
  3. 实现Callable接口,实现call方法

线程状态的变化

任何线程一半具有5种状态,即为创建、就绪、运行、阻塞、终止

  1. 创建状态:当程序中用构造方法创建了一个线程对象之后,新的线程就处于创建状态,此时它已经有了对应的内存空间和其它的资源,但是还是处于不可运行的状态
  2. 就绪状态:新建线程对象之后,调用该线程的start()方法就可以启动一个线程,线程进入就绪状态,此时线程就可以进去线程队列,可以抢占CPU了
  3. 运行状态:当就绪状态的线程获取到了CPU资源的时候,线程就进入了运行状态,CPU会自动调用该线程的run方法进行操作
  4. 阻塞状态:一个处于运行状态的线程由于某些特殊的原因,放弃CPU暂时中止自己的运行,在运行过程中,调用sleep() wait()方法会使程序进入阻塞状态
  5. 死亡状态:调用stop()方法或者run()方法执行结束后线程处于死亡状态

线程状态转化图如下

线程状态转化图

Java锁

课后习题

  1. 实现生产者消费者模型

网络编程

类加载和反射机制

JDBC

编码规范

Java Web基础

JSON

1
https://www.json.org/json-en.html

json解析库:fastjsongson

json使用{}表示一个对象,使用[]表示一个数组

HTTP 协议

请求报文

一个HTTP请求报文分为四个部分:请求行、请求头、空行、请求数据,这四个部分排列顺序是固定的!!!

  1. 请求行:请求行主要由请求方法字段、URL字段和HTTP协议版本字段三个字段组成,他们分别用空格分割开来,一个最经典的请求报文的请求行就是GET / HTTP/1.1

  2. 请求头:HTTP客户端程序向服务器请求是必须指明请求类型:如GET POST,如有必要,也可以选择发送其它的请求头,大多数请求头不是必须的,但是Content-Length除外,对于POST请求来说,Content-Length是必须出现的.常见的请求头字段含义:

    1. Accept:浏览器可以接受的MIME类型
    2. Content-Length:表示请求报文的正文长度
    3. Host:客户急通过这个告诉服务器想要访问的主机名,Host头域指定请求资源的Intenet主机和端口号,必须表示请求URL的原始服务器或者网关地址,HTTP/1.1请求必要包含主机头域,不然系统会以400状态码返回
    4. User-Agent:这里面的内容包含发出请求的用户信息、浏览器类型.(这个爬虫非常有用)
    5. Cookie:客户端通过这个头像服务器发送数据,CookieSession的基础
    6. Connection:处理完这次请求释放断开连接还是继续保持连接,其中Keep-Alive是持久连接
    7. Content-Type:表示请求数据的类型
  3. 空行:即使空了一行,可以告诉服务器头部到此为止

  4. 请求数据:这个部分是携带的数据

响应报文

一个HTTP响应报文也主要分为四个部分:响应行、响应头、空行、数据行

  1. 响应行:这个主要行扩了三个部分:协议类型和版本号、状态码、状态码的描述信息

    这里主要叙述HTTP状态码,HTTP状态码主要分为五大类

    1. 100~199 (信息性状态码)
    2. 200~299(成功状态码)
    3. 300~399(重定向状态码)
    4. 400~499(客户端错误状态码)
    5. 500~599(服务端错误状态码)
  2. 响应头部

    重要的几个:

    1. Set-Cookie:在客户端设置数据
    2. Warning:比原因短语更详细的一些的警告报文
  3. 空行

  4. 数据行

RESTFul

我们可以通过HTTP方法来对资源进行CURD

  1. GET: 我们使用GET来进行查询,如

    1
    2
    3
    GET /user   查询所有用户的信息
    GET /user/1 查询指定用户ID为1 的用户信息
    GET /user/1/age 查询指定用户ID为1 的用户信息的年龄
  2. POST: 创建单个资源

    1
    2
    POST /user 新增一个用户
    POST /user/1/teacher 为用户ID为1 的用户新增家教
  3. PUT: 更新单个资源

    1
    PUT /user/1 更改用户为1 的用户信息
  4. DELETE 删除某个资源

    1
    DELETE /user/1 删除ID为1 的用户信息,不过删除操作一半是把数据库的is_del字段置为true

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!