【JAVA CORE_API】Day18 网络编程、线程、在线聊天室v1.0

2024-08-21 20:44

本文主要是介绍【JAVA CORE_API】Day18 网络编程、线程、在线聊天室v1.0,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

C/S:客户端/服务器端,所有网络应用都是基于客户端服务器端进行的,Java写的是服务端,客户端是一个软件,服务端也是一个软件,两个软件之间交互;(只能连接对应的服务器)

B/S:浏览器/服务器端,它本质上也是C/S,只不过它的C是一个浏览器而已;(连接任意服务器都可以、百度、淘宝、京东等)

聊天室:两个程序A和B,一个是客户端、一个是服务端:谁发起连接,谁是客户端;谁接收连接,谁是服务端。

想连在一起需要网络,目的是为了传输数据,发送数据的过程中时需要遵守一些协议的:
TCP协议:可靠传输协议,发送数据后需要对方确认,对方确认后才能继续发送数据,再需要对方确认,100%所有数据发送过去,比较像打电话,需要接电话才能听见。虽然说数据完全可靠,但效率低下;
UDP:不可靠传输协议,只管发,不管对方能否接收到,有点像大广播,播了就播了,不管你听没听见。虽然不能保证数据100%都发送成功,但是效率比较高。

但是我们学习的时候学TCP,因为日后面对的客户端都是B(浏览器),而浏览器和客户端之间采用的协议是Http协议,Http协议要求地下客户端服务端传输时必须建立在可靠传输协议TCP上。

网络编程

什么是Socket编程

什么是Socket编程

  • java.net.SocketJava提供的用于进行网络编程的API;

  • Socket编程可以让软件与软件之间以计算机作为载体,以网络作为信息流动的通道进行远端数据传递,达到交流的目的。

什么是计算机网络

  • 计算机网络是指将具有独立功能的多台计算机通过通信线路连接起来,实现数据共享和交流的计算机系统。

什么是Socket

  • Socket(套接字):网络通信的标准API、进行可靠的网络通讯。

Socket通讯

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

IP地址(楼)

在这里插入图片描述

端口(门)

在这里插入图片描述

IP+端口

在这里插入图片描述

客户端与服务端(C/S)

在这里插入图片描述

Socket通讯

在这里插入图片描述

在这里插入图片描述

ServerSocket

在这里插入图片描述
在这里插入图片描述

多客户端支持

如何接受多客户端

  • ServerSocket提供方法:

    • Socket accept():用于监听服务端口,一旦一个客户端连接即返回一个Socket

    • 多次调用该方法可以感知多个客户端的连接。

在这里插入图片描述

建立连接

建立连接

  • Server.java

     package socket;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;/*** 服务端*/public class Server {/*** java.net.ServerSocket:* 运行在服务端,主要作用两个:* 1.向系统申请服务端口,客户端通过该端口与服务端建立连接* 2.监听服务端口,一旦有客户端连接了,就会立即创建一个Socket对象与客户端进行交互*   如果将Socket比喻为"电话",那ServerSocket就相当于客户中心的"总机"*/private ServerSocket serverSocket;public Server(){try {System.out.println("正在启动服务器");/*** 创建ServerSocket对象时,会申请一个端口* 如果该端口被其它程序占用,会抛出异常:*   java.net.BindException: Address already in use:* 解决办法:* 1.更换端口号* 2.杀死占用该端口的进行(通常由于服务端启动两次导致)*/serverSocket = new ServerSocket(8088);System.out.println("服务器启动完毕");} catch (IOException e) {e.printStackTrace();}}/*** 该方法用于启动程序的执行*/public void start(){try {System.out.println("等待客户端连接...");/*accept():用于接收客户端连接,并返回一个Scoket对象与所连接的客户端进行交互该方法是一个阻塞方法,调用后程序会"卡住",直接一个客户端连接为止*/Socket socket = serverSocket.accept();System.out.println("一个客户端连接了!");} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {Server server = new Server();server.start();}}
    
  • Client.java

    package socket;
    import java.io.IOException;
    import java.net.Socket;
    /*** 客户端*/
    public class Client {/*java.net.Socket:套接字它封装了TCP协议的通信细节,使用它可以和服务器建立连接并进行交互*/private Socket socket;public Client(){try {System.out.println("正在连接服务端...");/*实例化Socket对象,就是与远端计算机建立连接的过程需要传入两个对数:1.服务端的IP地址,用于找到网络上对方的计算机2.服务端口,用于找到服务端计算机上的应用程序查看IP操作:Windows: win+r,输入cmd,回车,输入ipconfig,IPv4就是IP地址Mac:触控板上五指向中间抓,选择"终端"程序打开,输入/sbin/ifconfig查看IP地址*/socket = new Socket("localhost",8088);System.out.println("服务端连接成功!");} catch (IOException e) {e.printStackTrace();}}/*** 该方法用于启动客户端程序的执行*/public void start(){}public static void main(String[] args) {Client client = new Client();client.start();}
    }
    
  • 注意在尝试连接本地时要提前打开服务端Server.java,再连接自己,之后就可以通过其他人给出的端口号及IP地址连接其他人。

客户端发送文本数据

  • 利用IO只是中的流连接,使用客户端的Socket获取输出流进行流连接,利用PrintWriter来实现发送一行字符串的操作。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Server.java

package day18;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;/*** 服务端*/
public class Server {/*** java.net.ServerSocket:* 运行在服务端,主要作用有两个:* 1.像系统申请服务端口,客户端通过该端口与服务端建立连接* 2.监听服务端口,一旦有客户链接了,就会立即创建一个Socket对象与客户端进行交互*      如果将Socket比喻为“电话”,那ServerSocket就相当于客户中心的“总机”。* 解决方法:* 1.更换端口号;* 2.杀死占用该端口的进行(通常由于服务端启动了两次导致)*/private ServerSocket serverSocket;public Server(){try {System.out.println("正在启动服务端......");serverSocket = new ServerSocket(8888);System.out.println("服务端启动完成!");} catch (IOException e) {e.printStackTrace();}}// 启动服务端方法:public void start(){try {while (true){System.out.println("服务端正在等待客户端连接......");/*** accept():* 用于接收客户端连接,并返回一个Socket对象与所连接的客户端进行交互* 该方法是一个阻塞方法,调用后程序会“卡住”,直到一个客户端连接为止*/Socket socket = serverSocket.accept();System.out.println("一个客户端连接了!");// 接收客户端发送过来的消息InputStream inputStream = socket.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String message;while ((message = bufferedReader.readLine()) != null) {    // 读取客户端发送过来的消息System.out.println("客户端说:" + message);}}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {Server server = new Server();server.start();}}

Client.java

package day18;
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;/*** 客户端*/
public class Client {/*** java.net.Socket:套接字* 它封装了TCP协议的通信细节,使用它可以和服务器建立连接并进行交互* 可以理解为是电话*/private Socket socket;public Client() {// 实例化Socket对象,就是与远端计算机建立连接的过程// 需要传递两个对数:// 1.远端计算机的IP地址,用于找到网络上对方的计算机// 2.远端计算机的端口号,用于找到对方计算机中的应用程序try {System.out.println("正在连接服务端......");/*** 如何查找本机IP地址:* Windows:Win+R,输入cmd,回车,输入ipconfig,回车* Mac:触控板上五指向中间抓,选择"终端"程序打开,输入/sbin/ifconfig查看IP地址*/socket = new Socket("172.40.140.102", 8088);System.out.println("连接成功!");} catch (IOException e) {e.printStackTrace();}}// 该方法用于启动客户端程序的执行public void start() {// 通过Socket获取输出流用于向服务端发送消息try {OutputStream outputStream = socket.getOutputStream();OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);PrintWriter printWriter = new PrintWriter(bufferedWriter,true);  // 自动行刷新Scanner scanner = new Scanner(System.in);while (true) {String line = scanner.nextLine();if ("exit".equalsIgnoreCase(line)) {break;}printWriter.println(line);  // 发送消息给服务端}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {Client client = new Client();client.start();}
}

三次握手与四次挥手

客户端断开连接的操作

  • 我们在上方代码中输入“exit”后,服务器会出现一大堆红字;

什么是三次握手四次挥手

  • 异常出现的原因:

    • TCP协议是面向连续的可靠传输协议,双方建立连接及断开连接需要双向确认后才可以进行

    • 当任意一方在没有进行确认断开操作就擅自结束,另一方就会出现该异常。

  • 三次握手与四次挥手:

    • 客户端与服务端建立TCP连接时需要进行三次握手,以确保双方可以建立可靠连接;

    • 任意一方需要断开TCP连接时需要进行四次挥手,以确保双方可靠断开。

三次握手(Three-way Handshake)

  • 第一次握手(SYN):

    • 客户端发送一个带有SYN(同步)标志的数据包到服务器,并指定客户端的初始化序列号(ISN);

    • 客户端进入SYN_SENT状态,以等待服务器的确认。

  • 第二次握手(SYN-ACK):

    • 服务器收到客户端的SYN数据包后,会发送一个带有SYNACK(确认)标志的数据包到客户端,确认客户端的请求,并指定服务器的初始化序列号(ISN)。

    • 服务器进入SYN_RCVD状态;

  • 第三次握手(ACK):

    • 客户端收到服务器的SYN-ACK数据包后,会发送一个带有ACK标志的数据包给服务器,表示确认连线请求;

    • 服务器收到客户端的ACK后,双方都进入ESTABLISHED状态,建立起可靠的连接。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四次挥手(Four-way Wavehake)

  • Socket提供方法:

    • void close():用于和对方断开TCP连接,底层会进行四次挥手操作。

在这里插入图片描述

  1. 客户端发送FIN报文:客户端首先向服务器发送一个带有FIN标志位的保温,表示客户端不再发送数据,并请求关闭连接。此时客户端进入“FIN_WAIT_1”状态;

  2. 服务器发送ACK报文:服务器收到客户端的FIN报文后,会发送一个确认保温,即ACK报文,告知客户端已经收到关闭请求。此时服务器进入“CLOSE_WAIT”状态,等待确认关闭;

  3. 服务器发送FIN报文:服务器在发送ACK报文后,会继续检查是否还有剩余的数据需要发送。如果有,服务器会继续发送数据;如果没有,服务器会发送一个带有FIN标志位的报文给客户端,表示服务器也不在发送数据了。此时服务及进入“LAST_ACK”状态;

  4. 客户端发送ACK报文:客户端收到服务器的FIN报文后,会发送一个确认报文,即ACK报文,告知服务器已经收到关闭请求,并进入“TIME_WAIT”状态。再“TIME_WAIT”状态下,客户端等待一段时间(通常为2倍的最大报文段生存时间,即MSL),以确保服务器已经收到了ACK报文;

  5. 服务器收到ACK报文:服务器收到客户端的ACK报文后,确认客户端已经收到了服务器的关闭请求,此时服务器进入“CLOSED”状态,完成连接的关闭。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 package day18;import java.io.*;import java.net.Socket;import java.nio.charset.StandardCharsets;import java.util.Scanner;/*** 客户端*/public class Client {/*** java.net.Socket:套接字* 它封装了TCP协议的通信细节,使用它可以和服务器建立连接并进行交互* 可以理解为是电话*/private Socket socket;public Client() {// 实例化Socket对象,就是与远端计算机建立连接的过程// 需要传递两个对数:// 1.远端计算机的IP地址,用于找到网络上对方的计算机// 2.远端计算机的端口号,用于找到对方计算机中的应用程序try {System.out.println("正在连接服务端......");/*** 如何查找本机IP地址:* Windows:Win+R,输入cmd,回车,输入ipconfig,回车* Mac:触控板上五指向中间抓,选择"终端"程序打开,输入/sbin/ifconfig查看IP地址*/socket = new Socket("localhost", 8888);System.out.println("连接成功!");} catch (IOException e) {e.printStackTrace();}}// 该方法用于启动客户端程序的执行public void start() {// 通过Socket获取输出流用于向服务端发送消息try {OutputStream outputStream = socket.getOutputStream();OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);PrintWriter printWriter = new PrintWriter(bufferedWriter,true);  // 自动行刷新Scanner scanner = new Scanner(System.in);while (true) {String line = scanner.nextLine();if ("exit".equalsIgnoreCase(line)) {break;}printWriter.println(line);  // 发送消息给服务端}} catch (IOException e) {e.printStackTrace();} finally {try {socket.close();  // 进行四次挥手} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {Client client = new Client();client.start();}}

多线程

概念

什么是线程与多线程

  • 线程是一个单一的顺序执行流程;

  • 多线程是多个单一顺序执行流程一起执行。

顺序执行与并发执行

  • 顺序执行:程序从上至下一句一句执行;

  • 并发执行:多个线程一起执行称为“并发执行”。

使用场景

  • 互不干扰:多线程通常用于在一个程序中需要同时处理多个互不干扰的任务;

  • 多线程更快:单线程可以完成,但是多线程更快。

单线程和多线程比喻

  • 可以把单线程看作只有一个灶台,一次只能做一道菜;或看作电路中的串联;

  • 多线程则是有很多灶台,一次能做很多菜;或看作电路中的并联。

CPU与多线程

CPU 的多线程操作通过时间片轮转Time Slicing)来实现。虽然一个 CPU 在某一时刻只能执行一个线程,但它可以在多个线程之间快速切换,使得每个线程都能获得一定的执行时间。这种快速的切换让用户感觉多个线程是同时运行的。

线程的创建

第一种创建线程形式

  • 继承Thread来定义一个线程:

    • 重写run方法,在其中定义该线程的任务代码。
 package day18;/*** 线程的第一种创建方式:继承Thread类* 更方便地使用匿名内部类创建线程、结构简单* 缺点:Java是单继承的,所以不能再继承其他类*      意味着继承了Thread就无法再继承其他类了,不利于复用*      定义线程的同时定义了线程的任务,导致线程和任务绑定在了一起,不利于复用*/public class ThreadDemo01 {public static void main(String[] args) {Thread thread01 = new MyThread01();Thread thread02 = new MyThread02();// 启动线程要调用star(),而不是直接调用run()方法thread01.start();thread02.start();}}class MyThread01 extends Thread {public void run() {for (int i = 0; i < 1000; i++) {System.out.println("Hi!" + i);}}}class MyThread02 extends Thread {public void run() {for (int i = 0; i < 1000; i++) {System.out.println("ByeBye!" + i);}}}

第二种创建线程的方式

  • 启动线程:

    • 实例化线程任务;

    • 实例化线程,同时将任务通过现成的构造器传递给线程;

    • 调用线程的start()方法。

 package day18;/*** 第二种创建线程的方式:实现Runnable接口*/public class ThreadDemo02 {public static void main(String[] args) {// 创建线程任务Runnable runnable01 = new MyRunnable01();Runnable runnable02 = new MyRunnable02();// 创建线程Thread thread01 = new Thread(runnable01);Thread thread02 = new Thread(runnable02);// 启动线程thread01.start();thread02.start();}}class MyRunnable01 implements Runnable {@Overridepublic void run() {for (int i = 1; i <= 1000; i++) {System.out.println("Hello!" + i);}}}class MyRunnable02 implements Runnable {@Overridepublic void run() {for (int i = 1; i <= 1000; i++) {System.out.println("Hi!" + i);}}}

使用匿名内部类实现线程的两种创建方式

 package day18;/*** 使用匿名内部类方式实现线程的两种创建方式*/public class ThreadDemo03 {public static void main(String[] args) {//第一种创建方式:继承Thread并重写run方法Thread thread01 = new Thread() {public void run() {for (int i = 0; i < 100; i++) {System.out.println("线程01:" + i);}}};thread01.start();//第二种创建方式:实现Runnable接口并重写run方法Thread thread02 = new Thread(() -> {for (int i = 0; i < 100; i++) {System.out.println("线程02:" + i);}});thread02.start();}}

并发解决聊天室不能多用户使用问题

 package day18;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket;import java.nio.charset.StandardCharsets;/*** 服务端*/public class Server {/*** java.net.ServerSocket:* 运行在服务端,主要作用有两个:* 1.像系统申请服务端口,客户端通过该端口与服务端建立连接* 2.监听服务端口,一旦有客户链接了,就会立即创建一个Socket对象与客户端进行交互*      如果将Socket比喻为“电话”,那ServerSocket就相当于客户中心的“总机”。* 解决方法:* 1.更换端口号;* 2.杀死占用该端口的进行(通常由于服务端启动了两次导致)*/private ServerSocket serverSocket;public Server(){try {System.out.println("正在启动服务端......");serverSocket = new ServerSocket(8888);System.out.println("服务端启动完成!");} catch (IOException e) {e.printStackTrace();}}// 启动服务端方法:/*** accept():* 用于接收客户端连接,并返回一个Socket对象与所连接的客户端进行交互* 该方法是一个阻塞方法,调用后程序会“卡住”,直到一个客户端连接为止*/public void start(){try {while (true){System.out.println("服务端正在等待客户端连接......");Socket socket = serverSocket.accept();System.out.println("一个客户端连接了!");// 启动单独的线程来处理与客户端的通信ClientHandler clientHandler = new ClientHandler(socket);Thread thread = new Thread(clientHandler);thread.start();}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {Server server = new Server();server.start();}/*** 该线程任务用于负责与指定的客户端通信*/private class ClientHandler implements Runnable{private Socket socket;public ClientHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {// 接收客户端发送过来的消息InputStream inputStream = socket.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String message;while ((message = bufferedReader.readLine()) != null) {    // 读取客户端发送过来的消息System.out.println("客户端说:" + message);}} catch (IOException e) {e.printStackTrace();} finally {try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}}}

主线程

  • Java程序的任何代码都是靠线程进行,main方法也是;

  • 程序启动后,JVM创建一条线程执行main方法,这条线程我们叫“主线程main”;

什么是主线程

  • Thread提供的静态方法:

    • static Thread currentThread()

    • 该方法用于返回执行他的线程;

查看线程的相关信息

  • Thread提供了获取线程信息的相关方法:

    • long getId():返回该线程的标识符;

    • String getName():返回该线程的名称;

    • int getPriority():返回线程的优先级;

    • boolean isAlive():检测线程是否处于活跃状态;

    • boolean isDeamon():测试线程是否为守护线程;

    • boolean isInterrupted():测试线程是否已经中断;

 package day18;import static java.lang.Thread.currentThread;/*** 线程信息*/public class ThreadInfoDemo {public static void main(String[] args) {Thread main = currentThread();  // 获取主线程System.out.println(main);doSome();  // 主线程调用doSome方法}public static void doSome() {Thread t = currentThread();  // 获取的是doSome方法的线程System.out.println("运行doSome方法的线程:" + t);System.out.println("运行doSome方法的线程名称:" + t.getName());System.out.println("运行doSome方法的线程优先级:" + t.getPriority());System.out.println("运行doSome方法的线程是否是守护线程:" + t.isDaemon());System.out.println("运行doSome方法的线程是否是活动线程:" + t.isAlive());System.out.println("运行doSome方法的线程是否是中断状态:" + t.isInterrupted());System.out.println("运行doSome方法的线程标识符:" + t.getId());}}

这篇关于【JAVA CORE_API】Day18 网络编程、线程、在线聊天室v1.0的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1094240

相关文章

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

SpringCloud集成AlloyDB的示例代码

《SpringCloud集成AlloyDB的示例代码》AlloyDB是GoogleCloud提供的一种高度可扩展、强性能的关系型数据库服务,它兼容PostgreSQL,并提供了更快的查询性能... 目录1.AlloyDBjavascript是什么?AlloyDB 的工作原理2.搭建测试环境3.代码工程1.

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

SpringBoot操作spark处理hdfs文件的操作方法

《SpringBoot操作spark处理hdfs文件的操作方法》本文介绍了如何使用SpringBoot操作Spark处理HDFS文件,包括导入依赖、配置Spark信息、编写Controller和Ser... 目录SpringBoot操作spark处理hdfs文件1、导入依赖2、配置spark信息3、cont

springboot整合 xxl-job及使用步骤

《springboot整合xxl-job及使用步骤》XXL-JOB是一个分布式任务调度平台,用于解决分布式系统中的任务调度和管理问题,文章详细介绍了XXL-JOB的架构,包括调度中心、执行器和Web... 目录一、xxl-job是什么二、使用步骤1. 下载并运行管理端代码2. 访问管理页面,确认是否启动成功

Java中的密码加密方式

《Java中的密码加密方式》文章介绍了Java中使用MD5算法对密码进行加密的方法,以及如何通过加盐和多重加密来提高密码的安全性,MD5是一种不可逆的哈希算法,适合用于存储密码,因为其输出的摘要长度固... 目录Java的密码加密方式密码加密一般的应用方式是总结Java的密码加密方式密码加密【这里采用的

Java中ArrayList的8种浅拷贝方式示例代码

《Java中ArrayList的8种浅拷贝方式示例代码》:本文主要介绍Java中ArrayList的8种浅拷贝方式的相关资料,讲解了Java中ArrayList的浅拷贝概念,并详细分享了八种实现浅... 目录引言什么是浅拷贝?ArrayList 浅拷贝的重要性方法一:使用构造函数方法二:使用 addAll(

解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题

《解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题》本文主要讲述了在使用MyBatis和MyBatis-Plus时遇到的绑定异常... 目录myBATis-plus-boot-starpythonter与mybatis-spring-b