异常
一、异常的概念
异常指的是程序在执行过程中可能会遇见的一种非预期状态或错误。
二、异常的作用
1.用于查询出现Bug的关键信息。
2.异常可以作为方法内部的一种特殊的返回值, 用来通知调用者底层的执行情况。
三、异常的分类
Java中常见的异常可以分为两大类:编译时异常(Checked Exception)和运行时异常(Unchecked Exception)。
编译时异常: 这类异常通常需要在代码中显式处理,包括IOException(输入输出异常)、SQLException(SQL异常)、ClassNotFoundException(类未找到异常)等。这些异常在编译时即可被发现,可以通过捕获或声明抛出来处理。
运行时异常: 这类异常通常由程序逻辑错误引起,在程序中可以选择捕获处理,也可以不处理。Java编译器不会检查运行时异常,但是可以通过throws进行声明抛出,也可以通过try-catch进行捕获处理。如果产生运行时异常,则需要通过修改代码来进行避免。
常见的运行时异常: NullPointerException(空指针异常)、ArrayIndexOutOfBoundsException(数组越界异常)、ClassCastException(类型转换异常)、NumberFormatException(数字格式化异常)、ArithmeticException(算术异常)。
四、异常的处理方式
4.1 JVM的默认处理方式
1. 把异常的名称, 异常的原因以及异常出现的位置等信息输出在控制台上。
2. 将正在运行的程序停止, 发生异常下面的代码不会执行。
4.2 用户自己捕获异常
捕获异常的格式
try{
可能出现异常的地方;
} catch (异常类型 变量名){
异常的处理方式;
}
自己捕获异常的好处:
可以让程序继续运行下去, 不会停止正在运行的程序。
五、捕获异常中的四个问题
问题一: 如果try中没有遇到问题, 程序如何执行?
答: 如果try中没有遇到任何问题, 系统先将try代码段中的代码执行完毕, 随后跳出try...catch体系, 继续执行体系下面的代码, 直到程序运行完毕; 也就是说只有出现了异常, catch代码段才会被执行。
问题二:如果try中可能会遇到多个问题,怎么执行?
答: 如果这样子的话, 我们需要写多个catch代码段去对应可能出现的异常, 但是会以在触发的catch代码段中, 会以第一个触发的为主; 并且在写多个对应catch段时, 如果这些异常存在父子关系的话, 父类一定要写在后面, 写在前面的话, 由于多态的原因, 它可以接收它的所有子类, 那么下面的catch代码段就永远不会触发。
问题三: 如果try中遇到的问题没有被捕获,怎么执行?
答: 如果遇到的问题没有被捕获, 那么会交给JVM去处理, 也就是当前正在运行的程序会停止运行, 随后会在控制台输出有关异常的相关信息, try...carch体系下面的代码就不会在执行。
问题四: 如果try中遇到了问题,那么try代码段中下面的其他代码还会执行吗?
答: 如果遇到了问题, try代码段下面的其他代码不会被执行, 系统会直接跳转到catch代码段中执行catch代码段中的代码, 如果没有与之对应的catch, 那么系统会交付给JVM处理
文件
一、文件的概念
文件是信息的一种组织方式, 是存储在外存上的具有标记名的一组相关信息的集合, 文件可以是文本文档、图片、程序等。
二、文件对象
2.1 File文件类概述
File类是Java中处理文件和目录的基础类之一。表示文件系统中的文件或目录的路径名, 提供了一组方法来操作文件和目录。一下是File类中初始化和常用的方法:
2.1.1 构造方法
File(String str) ---> 全路径,里面包括要操作的文件或目录名
例:String str = "C:\\Users\\86183\\OneDrive\\Desktop\\a.txt";
File f1 = new File(str);
File(String str1, String str2) ---> 字符串拼接形式
例:String str = "C:\\Users\\86183\\OneDrive\\Desktop";
String fileName = "a.txt";
File f2 = new File(str, fileName);
File(File f, String str) ---> 文件对象和字符串拼接形式
例:String fileName = "a.txt";
File f3 = new File("C:\\Users\\86183\\OneDrive\\Desktop");
File f4 = new File(f3, fileName);
2.2.2 常用方法
public boolean isDirectory() 判断此路径名表示的File是否为文件夹
public boolean isFile() 判断此路径名表示的File是否为文件
public boolean exists() 判断此路径名表示的File是否存在
public string getName() 返回文件的名称,带后缀
public long length() 返回文件的大小(字节数量)
public boolean createNewFile() 创建新的空文件
public boolean mkdirs() 创建多级文件 / 单级文件夹
public boolean delete() 删除文件或者空目录
public File[] listFiles() 获取文件夹下的所有内容, 会返回一个文件对象数组
public static File[] listRoots() 列出可用的文件系统根
2.2 字节流概述
Java字节流是用于处理二进制数据的输入输出流,是基于字节的数据流,以字节为单位进行输入和输出。字节流分为输出字节流(FileOutputStream)和输入字节流(FileInputStream)。
2.2.1 构造方法
FileOutputStream(String str / File file)
FileOutputStream(String str / File file, boolean true)
FileInputStream (String str / File file)
注意:
方法的参数可为字符串或者File对象
如果文件不存在会创建一个新文件,但是要保证父级路径存在
如果原文件存在,则新文件会覆盖原文件
参数二:默认false,会覆盖原文件,如果想要追加写入文件,需要设定为true
2.2.2 常用方法
FileInputStream:
void read() 每次读入单个字节
void read(byte[] bytes) 读入一个字节数组中的数据
void read(byte[] bytes, int off, int len) 读入字符数组中,off 索引开始的 len个长度
FileOutputStream:
void write(int b) 写入单个字节
void write(byte[] bytes) 写入一个字节数组中的数据
void write(byte[] bytes, int off, int len) 写入字符数组中,off 索引开始的 len个长度
注意:
如果想以续写的方式写入文件,则需要在创建对象时在第二个参数设定为true
在写的过程中,如需换行,则需在换行的地方写一个换行符
Windows:\r\n
Linux:\n
Mac:\r
2.3 字符流概述
字符流是在字节流的基础上,在输出和输入时自动帮我们转换编码的IO流,也就是说底层先读取到字节,然后在转换为编码表中对应的字符。
2.2.1 构造方法
FileWriter (String str / File file) FileWriter (String str / File file, boolean false)
FileReader (String str / File file)
注: 方法的参数可为字符串或者File对象
参数二:默认false,会覆盖原文件,如果想要追加写入文件,需要设定为true
2.2.2 常用方法
FileReader:
public int read() 读取单个数据,读到末尾返回-1
public int read(char[] buffer) 读取多个数据,读到末尾返回-1
FileWriter:
void write(int c) 写出一个字符
void write(string str) 写出一个字符串
void write(string str, int off, int len) 写出一个字符串的一部分
void write(char[] cbuf) 写出一个字符数组
void write(char[] cbuf, int off, int len) 写出一个字符数组的一部分
2.4 字节 / 字符缓冲流
字节缓冲流构造方法
public BufferedInputStream(FileInputStream is)
public BufferedOutputStream(FileOutputStream os)
字符缓冲流构造方法
public BufferedReader(Reader r) 特有方法:public string readLine() 读一整行
public BufferedWriter(Writer w) 特有方法:public string newLine() 跨平台的换行
多线程
一、线程的概念
在了解线程之前,我们得先了解一下进程。进程是程序运行的基本实体,而线程是操作系统中能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。有了多线程,我们就可以让程序同时做多件事情,可以提高我们的工作效率。
二、线程的实现方式
第一种:继承Thread类,重写run方法 无返回值
// 1.创建两个线程 MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); // 2.启动线程 ---> 交替执行 t1.start(); t2.start();
第二种:实现Runnable接口,重写run方法 无返回值
// 1.创建自己写好的类的对象 MyRun mr = new MyRun(); // 2.创建一个Thread类对象,传入mr对象 Thread t1 = new Thread(mr); Thread t2 = new Thread(mr); // 2.开启线程 t1.start(); t2.start();
第三种:继承Callable接口 有返回值
// 1.创建写好的类的对象(表示多线程要执行的任务) MyCallable mc = new MyCallable(); // 2.创建FutureTask对象 ---> 管理多线程运行的结果 FutureTask<Integer> ft = new FutureTask<>(mc); // 传入要管理的对象 // 3.创建Thread类的对象 Thread t = new Thread(ft); // 传入创建的FutureTask对象 // 4.启动线程 t.start(); // 5.输出结果 System.out.println(ft.get());
三、常用方法
1. String getName() 返回此线程的名称
注: 如果没有给线程设立名称,则会显示默认名称:Thread-X(X从0开始计数)。
2. void setName(string name) 设置线程的名字(构造方法也可以设置名字)
注: 如果想在构造方法中设置名字,那么我们需要重写构造函数,调用super来为线程设置名字。
3. static Thread currentThread() 获取当前线程的对象
注: 在JVM虚拟机启动以后,会自动创建多个线程,其中有一个是main线程 它的作用就是去调用main方法,然后执行里面的代码。
4. static void sleep(long time) 让线程休眠指定的时间,单位为毫秒
注: 哪条线程执行到这个方法,该线程就会陷入沉睡 当时间到了,该线程就会重新唤醒,继续执行下面的代码。
5. getPriority() 获取线程的优先级
6. setPriority() 设置线程的优先
注:优先级高指的是成功抢占cpu的概率高,不代表百分比
7. setDaemon 守护线程
注: 当其他进程执行完毕后,守护线程就会陆续结束 也就是说,不管守护进程是否执行完毕,只要其他进程执行完毕后,守护进程就会陆续结束
网络编程
一、网络编程的概念
计算机和计算机之间通过网络的方式进行数据的传输。
二、常见的软件架构
2.1 B/S架构
也称之为浏览器 / 服务器架构。
优点:
不需要开发出客户端,只需要页面 + 服务器就好。
适合移动互联网应用,可以在任何地方随时访问的系统。
缺点:
如果应用过大,用户的体验会收到影响。
2.2 C/S架构
也称之为客户端 / 服务端架构。
优点:
适合定制专业化的办公类软件如:IDEA、网游。
画面精美,用户体验感好。
缺点:
需要开发客户端 + 服务端。
用户需要下载和更新的时候不方便。
三、网络编程的三要素
IP地址、端口号、协议
IP地址:设备在网络中的唯一标识。
特殊的IP地址:127.0.0.1 ---> 永远代表本机
常见的两个CMD命令:
ipifconfig:查看本机IP地址
ping:查看网络是否联通
端口号:应用程序在设备上的唯一标识。
协议:数据在网络之间进行传输的规则。
常见的协议:TCP、UDP、http、ftp等。
四、UDP协议和TCP协议
UDP协议也称之为用户数据报协议,它是面向无连接的通信协议。传输速度块,但传输数据有大小限制,传输过程不稳定,容易丢失数据。
TCP协议也称之为传输控制协议,它是面向连接的通信协议。传输速度较UDP慢,但传输数据没有大小限制,传输过程稳定,数据不易丢失。
五、UDP编程
发送数据流程:
第一:创建DatagramSocket对象
注:有形参和无参两种方法创建,参数代表的是绑定端口号,就是通过这个端口号往外发送数据。无参:在设备中,随机指定一个可用的端口号进行绑定。有参:指定端口号进行绑定
例如:DatagramSocket ds = new DatagramSocket();
第二:打包数据 DatagramPacket(byte[] bytes, bytes.length, InetAddress ia, int port)
参数一:要发送数据的字节数组 参数二:发送的长度
参数三:目标设备的IP地址 参数四:目标设备中的端口号
例如:
String data = "我勒个去,淦!!!"; byte[] bytes = data.getBytes(); InetAddress iAddress = InetAddress.getByName("127.0.0.1"); // 127.0.0.1代表本机IP int port = 12345; // 目标设备的端口号 DatagramPacket dp = new DatagramPacket(bytes, bytes.length, iAddress, port);
第三:发送数据 ds.send(dp);
第四:关流,释放资源 ds.close();
接收数据流程:
第一:创建DatagramSocket对象
注:接收数据的话,一定要用有参来创建对象,表示要从哪个端口号接收数据,这个端口号必须要与发送的端口一致。
例如:DatagramSocket ds = new DatagramSocket(12345);
第二:接收数据包
参数一:接收到数据保存在哪(一定要为字节数组) 参数二:接收多少长度
例如:
byte[] bytes = new byte[1024]; DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
第三:利用receive方法阻塞,等待数据送达
例如:ds.receive(dp);
第四:解析数据包
byte[] data = dp.getData(); 获得数据
int length = dp.getLength(); 获得数据的长度
InetAddress address = dp.getAddress(); 获得发送设备的主机ip
int port = dp.getPort(); 获得发送端的发出端口
第四:关流,释放资源 ds.close();
六、TCP编程
客户端流程:
第一:Socket(string host,int port) 创建客户端的Socket对象与指定服务端连接
注:在创建对象时会连接服务器,连接不上会报错。
参数一:服务器主机IP地址。 参数二:指定发送目的地端口号。
例如:Socket socket = new Socket("127.0.0.1",13579);
第二:OutputStream getOutputStream() 获取输出流,
例如:OutputStream os = socket.getOutputStream();
第三:os.write(byte byte / byte[] bytes) 写数据
例如:os.write("哈喽,沃德!".getBytes());
第四:close()关流,释放资源
例如:socket.close();
服务端流程:
第一:ServerSocket(int port) 创建服务器端的Socket对象(ServerSocket)
参数:从哪个端口号接收信息
例如:ServerSocket ss = new ServerSocket(13579);
第二:Socket accept() 监听客户端连接,返回一个Socket对象
第三:InputStream getInputStream() 获取输入流,读数据,并把数据显示在控制台
第四:void close() 释放资源