Java基础总结

W3C Java教程

安装JDK&配置环境

JDK8 安装&环境变量配置(Windows、Linux),JDK源码下载

数据类型

  • 基本数据类型
    在这里插入图片描述
  • 引用数据类型
    1
    2
    3
    4
    5
    6
    7
    8
    对象(Object)
    数组(属于Object)
    String[] strs = {"11", "22"};//等同于 String[] strs = new String[]{"11", "22"};
    System.out.println(strs instanceof Object);// true
    System.out.println(new String[]{} instanceof Object);// true
    接口(Interface 因为接口相当于一个抽象类,必须new了要实现方法)

    总结:只要有new关键字创建的对象,都是引用数据类型。

成员变量默认值

在这里插入图片描述

局部变量&成员变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1. 定义的位置不一样【重点】
局部变量:在方法的内部
成员变量:在方法的外部,直接写在类当中

2. 作用范围不一样【重点】
局部变量:只有方法当中才可以使用,出了方法就不能再用
成员变量:整个类全都可以通用。

3. 默认值不一样【重点】
局部变量:没有默认值,如果要想使用,必须手动进行赋值
成员变量:如果没有赋值,会有默认值,规则和数组一样

4. 内存的位置不一样(了解)
局部变量:位于栈内存
成员变量:位于堆内存

5. 生命周期不一样(了解)
局部变量:随着方法进栈而诞生,随着方法出栈而消失
成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失

Java内存划分

在这里插入图片描述

数组

三种创建方式

默认值与成员变量的默认值相同

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args)
{
// 1.
String[] str1 = new String[1];
String str2[] = new String[2];

// 2.
String[] str3 = new String[]{"a", "b", "c"};

// 3.
String[] str4 = {"aa", "bb", "cc"};
}

数组内存图

  • 一个数组 内存图
    在这里插入图片描述
  • 两个独立数组 内存图
    在这里插入图片描述
  • 两个引用指向同一个数组 内存图
    在这里插入图片描述

长度不可变

数组长度运行期间不可变,因为数组是对象,可以执行其他数组。
在这里插入图片描述

类和对象

概念

在这里插入图片描述

对象内存图

  1. 一个对象 内存图
    在这里插入图片描述
  2. 两个对象使用同一个方法 内存图
    在这里插入图片描述
  3. 两个引用指向同一个对象 内存图
    在这里插入图片描述
  4. 用对象类型作为方法参数 内存图
    在这里插入图片描述
  5. 用对象类型作为方法返回值 内存图
    在这里插入图片描述

传值&传引用

可参考传值还是传引用内存语义

==和equals比较

可参考Integer的==和equals比较

String常量池

可参考String对象创建内存语义
在这里插入图片描述

static

静态static关键字

概述

在这里插入图片描述

修饰成员变量

在这里插入图片描述

修饰成员方法

在这里插入图片描述

静态内存图

在这里插入图片描述

extends

继承

概念

继承的基本概念
在这里插入图片描述

Override应用场景

方法(覆盖)重写的应用场景
在这里插入图片描述
在这里插入图片描述

super&this

父子类同名变量_super与this的内存图
在这里插入图片描述

继承的特点

Java继承的三个特点
在这里插入图片描述

abstract

抽象的概念
在这里插入图片描述

interface

生活举例

生活中接口的举例
在这里插入图片描述

接口方法定义

在这里插入图片描述

内容小结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
在Java 9+版本中,接口的内容可以有:

1. 成员变量其实是常量,格式:
[public] [static] [final] 数据类型 常量名称 = 数据值;
注意:
常量必须进行赋值,而且一旦赋值不能改变。
常量名称完全大写,用下划线进行分隔。

2. 接口中最重要的就是抽象方法,格式:
[public] [abstract] 返回值类型 方法名称(参数列表);
注意:实现类必须覆盖重写接口所有的抽象方法,除非实现类是抽象类。

3. 从Java 8开始,接口里允许定义默认方法,格式:
[public] default 返回值类型 方法名称(参数列表) { 方法体 }
注意:默认方法也可以被覆盖重写

4. 从Java 8开始,接口里允许定义静态方法,格式:
[public] static 返回值类型 方法名称(参数列表) { 方法体 }
注意:应该通过接口名称进行调用,不能通过实现类对象调用接口静态方法

5. 从Java 9开始,接口里允许定义私有很乏,格式:
普通私有方法:private 返回值类型 方法名称(参数列表) { 方法体 }
静态私有方法:private static 返回值类型 方法名称(参数列表) { 方法体 }
注意:private的方法只有接口自己才能调用,不能被实现类或别人使用。

使用注意事项

1
2
3
4
5
6
7
8
9
10
1. 接口是没有静态代码块或者构造方法的。
2. 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
格式:
public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
// 覆盖重写所有抽象方法
}
3. 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
4. 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
5. 如果实现类锁实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
6. 一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。

继承注意事项

1
2
3
4
5
6
7
1. 类与类之间是单继承的。直接父类只有一个。
2. 类与接口之间是多实现的。一个类可以实现多个接口。
3. 接口与接口之间是多继承的。

注意事项:
1. 多个父接口当中的抽象方法如果重复,没关系。
2. 多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,【而且带着default关键字】。

在这里插入图片描述

多态

概念

在这里插入图片描述

好处

使用多态的好处
在这里插入图片描述

上下转型

对象的上下转型
在这里插入图片描述
在这里插入图片描述

instanceof

instanceof关键字类型判断
在这里插入图片描述

案例_笔记本USB接口

在这里插入图片描述

final

代表最终,不可改变的。

修饰类

在这里插入图片描述

修饰方法

在这里插入图片描述

修饰局部变量

在这里插入图片描述

修饰成员变量

在这里插入图片描述

权限修饰符

public > protected > (default) > private
注意事项:(default)并不是关键字“default”,而是根本不写。

位置 public protected (default) private
同一个类(我自己)
同一个包(我邻居) ×
不同包子类(我儿子) × ×
不同包非子类(陌生人) × × ×

内部类

成员内部类

成员内部类的定义&使用
在这里插入图片描述

内部类的同名变量

内部类的同名变量的使用
在这里插入图片描述

局部内部类&类修饰符

局部内部类的使用_类修饰符总结
在这里插入图片描述

局部内部类的final问题

在这里插入图片描述

匿名内部类

匿名内部类使用&注意事项
在这里插入图片描述

包装类

基本类型包装类

在这里插入图片描述

装箱&拆箱

在这里插入图片描述

自动拆箱&自动装箱

在这里插入图片描述

泛型

概念

在这里插入图片描述

好处

在这里插入图片描述

泛型类

在这里插入图片描述

泛型方法

在这里插入图片描述

泛型接口

在这里插入图片描述

泛型通配符

我目前理解,泛型通配符无任何作用,但是配合extendssuper会有用。
例如Collection<?> coll是无用的,但Collection<? extends Number> collCollection<? super Number> coll是有用的。

当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。
通配符基本使用
泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。

1
2
3
4
5
6
7
8
public static void main(String[] args) {
Collection<Intger> list1 = new ArrayList<Integer>();
getElement(list1);
Collection<String> list2 = new ArrayList<String>();
getElement(list2);
}
public static void getElement(Collection<?> coll){}
//?代表可以接收任意类型

在这里插入图片描述

泛型通配符上下兼容

在这里插入图片描述

数据结构

可参考方法栈的执行逻辑一个对象的内存图
在这里插入图片描述

队列

可参考并发容器的队列实现并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解
在这里插入图片描述

数组

可参考ArrayList的实现ArrayList
在这里插入图片描述

链表

可参考LinkedList的实现LinkedList
在这里插入图片描述

红黑树

可参考二叉树,红黑树
以及TreeMap的实现TreeMap
在这里插入图片描述

List&Set&Map

参考List,Map,Set源码分析

案例_斗地主

在这里插入图片描述

可变参数

在这里插入图片描述
注意:

  1. 如果上面两种写法在同一个类中,方法不可以同名。
  2. 如果是可变参数写法,必须写在参数列表的最后面。

异常

return问题

try,catch,finally的return问题

1
2
3
4
5
try或catch中的return正常走完,确定好返回值,此时还不进行返回。
情况1. 如果finally中无内容,就直接返回确定好返回值。
情况2. 如果finally中有内容,就走finally中的内容。
情况2.1 如果finally中有return,就重新确定返回值,在finally中进行返回,结束方法。
情况2.2 如果finally中没有return,走完finally块之后,回头走到try或catch中的return处“把之前确定好的返回值”进行返回,结束方法。

在这里插入图片描述

throw

throw关键字

1
2
3
4
5
6
7
8
9
10
作用:
可以使用throw关键字在指定的方法中抛出指定的异常
使用格式:
throw new xxxException("异常产生的原因");
注意:
1.throw关键字必须写在方法的内部
2.throw关键字后边new的对象必须是Exception或者Exception的子类对象
3.throw关键字抛出指定的异常对象,我们就必须处理这个异常对象
throw关键字后边创建的是RuntimeException或者是 RuntimeException的子类对象,我们可以不处理,默认交给JVM处理(打印异常对象,中断程序)
throw关键字后边创建的是编译异常(写代码的时候报错),我们就必须处理这个异常,要么throws,要么try...catch

异常的处理方式

  1. throws交给别人处理,碰到异常不会往下执行。
  2. try{}catch(Exception e){}自己处理,碰到异常会去执行catch中的代码,并往下执行。

异常的产生过程

在这里插入图片描述

线程

更多内容可参考文章Java并发编程CL0610

并发&并行

在这里插入图片描述

进程的概念

在这里插入图片描述

线程的概念

在这里插入图片描述

多线程创建方式

  1. 通过继承Thread类,重写run方法
  2. 通过实现runable接口
  3. 通过实现callable接口,可参考有一千万个数,写一个程序进行高效求和

在这里插入图片描述

多线程内存图

在这里插入图片描述

线程状态

在这里插入图片描述

案例_包子铺&吃货

更多案例可参考一篇文章,让你彻底弄懂生产者–消费者问题
在这里插入图片描述

线程池

可参考线程池ThreadPoolExecutor实现原理

函数式编程

可参考Java 8 Lambda表达式,常用接口,Stream流式处理

递归

概念

1
2
3
4
5
6
7
8
9
10
11
递归:方法自己调用自己
- 递归的分类:
- 递归分为两种,直接递归和间接递归。
- 直接递归称为方法自身调用自己。
- 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
- 注意事项:
- 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
- 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
- 构造方法,禁止递归
递归的使用前提:
当调用方法的时候,方法的主体不变,每次调用方法的参数不同,可以使用递归

案例_文件搜索

递归案例_文件搜索

案例_计算1~n的和

在这里插入图片描述

Java-IO

Java-IO

网络编程

W3C Java网络编程

BS与CS

软件结构
在这里插入图片描述

通信协议

  • 网络通信协议:通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比交通规则一样。
    在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。
  • TCP/IP协议:传输控制协议/因特网互联协议( Transmission Control Protocol/Internet Protocol),是Internet最基本、最广泛的协议。
    它定义了计算机如何连入因特网,以及数据如何在它们之间传输的标准。
    它的内部包含一系列的用于处理数据通信的协议,并采用了4层的分层模型,每一层都呼叫它的下一层所提供的协议来完成自己的需求。
    在这里插入图片描述
  • 应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。
  • 运输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。
  • 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。
  • 链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。

协议分类

通信的协议还是比较复杂的,java.net 包中包含的类和接口,它们提供低层次的通信细节。
我们可以直接使用这些类和接口,来专注于网络程序开发,而不用考虑通信的细节。

java.net 包中提供了两种常见的网络协议的支持:

  • UDP:用户数据报协议(User Datagram Protocol)。
    UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。
    简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
    由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
    但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。
    UDP的交换过程如图所示。
    在这里插入图片描述
    特点:数据被限制在64kb以内,超出这个范围就不能发送了。
    数据报(Datagram):网络传输的基本单位
  • TCP:传输控制协议 (Transmission Control Protocol)。
    TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。
    在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。
    三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。
    在这里插入图片描述
    完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。
    由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛,例如下载文件、浏览网页等。

三要素

网络编程三要素

协议

就是规则,上面已经阐述。

IP地址

IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。
IP地址用来给一个网络中的计算机设备做唯一的编号。
假如我们把“个人电脑”比作“一台电话”的话,那么“IP地址”就相当于“电话号码”。
IP地址分类如下:

  • IPv4:是一个32位的二进制数,通常被分为4个字节,表示成a.b.c.d 的形式,例如192.168.65.100
    其中a、b、c、d都是0~255之间的十进制整数,那么最多可以表示42亿个。
  • IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。
    为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,表示成ABCD:EF01:2345:6789:ABCD:EF01:2345:6789
    号称可以为全世界的每一粒沙子编上一个网址,这样就解决了网络地址资源数量不够的问题。
1
2
3
4
5
6
7
8
查看本机IP地址
ipconfig

更全面,可查物理地址
ipconfig /all

检查网络是否连通`ping ip地址`
ping 192.168.0.1

注意:本机IP地址可表示成localhost 127.0.0.1

端口号

网络的通信,本质上是两个进程(应用程序)的通信。
每台计算机都有很多的进程,那么在网络通信时,如何区分这些进程呢?
如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的进程(应用程序)了。

  • 端口号:用两个字节表示的整数,它的取值范围是0~65535
    其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。
    注意:如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

总结:利用协议+IP地址+端口号 三元组合,就可以标识网络中的进程了,那么进程间的通信就可以利用这个标识与其它进程进行交互。

TCP通信

概述

TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。
两端通信时步骤:

  1. 服务端程序,需要事先启动,等待客户端的连接。
  2. 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。

在Java中,提供了两个类用于实现TCP通信程序:

  1. 客户端:java.net.Socket 类表示。创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。
  2. 服务端:java.net.ServerSocket 类表示。创建ServerSocket对象,相当于开启一个服务,并等待客户端的连接。

在这里插入图片描述

Socket

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
27
28
TCP通信的客户端:向服务器发送连接请求,给服务器发送数据,读取服务器回写的数据
表示客户端的类:
java.net.Socket:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
套接字:包含了IP地址和端口号的网络单位

构造方法:
Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。
参数:
String host:服务器主机的名称/服务器的IP地址
int port:服务器的端口号

成员方法:
OutputStream getOutputStream() 返回此套接字的输出流。
InputStream getInputStream() 返回此套接字的输入流。
void close() 关闭此套接字。

实现步骤:
1.创建一个客户端对象Socket,构造方法绑定服务器的IP地址和端口号
2.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
3.使用网络字节输出流OutputStream对象中的方法write,给服务器发送数据
4.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
5.使用网络字节输入流InputStream对象中的方法read,读取服务器回写的数据
6.释放资源(Socket)
注意:
1.客户端和服务器端进行交互,必须使用Socket中提供的网络流,不能使用自己创建的流对象
2.当我们创建客户端对象Socket的时候,就会去请求服务器和服务器经过3次握手建立连接通路
这时如果服务器没有启动,那么就会抛出异常ConnectException: Connection refused: connect
如果服务器已经启动,那么就可以进行交互了

ServerSocket

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
TCP通信的服务器端:接收客户端的请求,读取客户端发送的数据,给客户端回写数据
表示服务器的类:
java.net.ServerSocket:此类实现服务器套接字。

构造方法:
ServerSocket(int port) 创建绑定到特定端口的服务器套接字。

服务器端必须明确一件事情,必须的知道是哪个客户端请求的服务器
所以可以使用accept方法获取到请求的客户端对象Socket
成员方法:
Socket accept() 侦听并接受到此套接字的连接。

服务器的实现步骤:
1.创建服务器ServerSocket对象和系统要指定的端口号
2.使用ServerSocket对象中的方法accept,获取到请求的客户端对象Socket
3.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
4.使用网络字节输入流InputStream对象中的方法read,读取客户端发送的数据
5.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
6.使用网络字节输出流OutputStream对象中的方法write,给客户端回写数据
7.释放资源(Socket,ServerSocket)

简单使用

在这里插入图片描述

练习_文件上传

在这里插入图片描述

练习_模拟B/S服务器

在这里插入图片描述