Api day05
笔记
- 含有throws方法的类被继承后 子类中重写的规则
- 可以与超类的方法一样抛出(throws)相同异常
- 可以仅抛出部分异常
- 可以不抛出异常
- 可以抛出超类方法异常的子类型异常
- 不可抛出其他额外异常(既不是超类中的异常也不是子类型异常)
- 不可抛出超类方法中异常的超类型异常
/**
* 子类重写超类含有throws声明异常抛出的方法时,对throws的重写规则
*/
public class ThrowsDemo {
public void dosome() throws IOException, AWTException{}
}
class SubClass extends ThrowsDemo{
// public void dosome() throws IOException, AWTException{}
//允许子类只抛出超类方法异常中的一部分
// public void dosome() throws IOException{}
//允许子类抛出超类方法抛出异常的子类型异常 FileNotFoundException extends IOException
// public void dosome() throws FileNotFoundException {}
//允许子类不再抛出任何异常
// public void dosome(){}
//不允许子类抛出额外异常(超类中没有且没有任何继承关系的)
// public void dosome() throws SQLException {} //报错
//不允许子类抛出超类方法抛出异常的超类型异常 IOException extends Exception AWTException extends Exception
// public void dosome() throws Exception {} //Exception是IOException 和 AWTException 的超类型 子类只允许继承关系 等于或小于的异常
}
常见的RuntimeException子类
RuntimeException异常是非检查异常,即无需进行try-catch 或者 throws的异常,通常都是可以通过修改bug直接改好的,可避免异常。
除了RuntimeException之外的其它异常如果使用throw 是非检查异常
抛出则要在当前方法上使用throws声明该异常的抛出 即是检查异常 需throws
- IllegalArgumentException:抛出的异常表面向方向传递了一个不合法或不正确的参数
- NullPointerException:当应用程序试图在需要对象的地方使用null时,抛出该异常
- ArrayIndexOutOfBoundsException:当使用的数组下标超出数组允许范围时,抛出该异常
- ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出该异常
- NumberFormatException:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为合适格式时,抛出该异常
异常中常用的方法
package exception;
/**
* 异常常见的方法
*/
public class ExceptionApiDemo {
public static void main(String[] args) {
System.out.println("程序开始了");
try {
String str = "abc";
System.out.println(Integer.parseInt(str));
} catch (NumberFormatException e) {
//异常最常用的方法,用于将当前错误信息输出到控制台
e.printStackTrace();
//获取错误消息.记录日志的时候或提示给用户可以使用它
String message = e.getMessage();
System.out.println(message);
}
System.out.println("程序结束了");
}
}
自定义异常
自定义异常通常用来定义那些业务上的异常问题
定义自定义异常需要注意以下问题
- 异常的类名要见名知意
- 需要继承或者间接继承Exception
- 提供超类异常提供的所有种类构造器
package test;
public class Person {
private int age;
public Person() {
}
public int getAge() {
return age;
}
public void setAge(int age) throws IllegalAgeException {
if (age<0 || age>100){
throw new IllegalAgeException("年龄不合法"+age);
}
this.age = age;
}
}
class Demo{
public static void main(String[] args) {
Person p = new Person();
System.out.println("开始");
try {
p.setAge(112);
} catch (IllegalAgeException e) {
e.printStackTrace();
String line = e.getMessage();
System.out.println(line);
}
System.out.println("结束");
}
}
package test;
public class IllegalAgeException extends Exception {
public IllegalAgeException() {
}
public IllegalAgeException(String message) {
super(message);
}
public IllegalAgeException(String message, Throwable cause) {
super(message, cause);
}
public IllegalAgeException(Throwable cause) {
super(cause);
}
public IllegalAgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
总结:
异常处理机制是用来处理那些可能存在的异常,但是无法通过修改逻辑完全规避的场景。
而如果通过修改逻辑可以规避的异常是bug,不应当用异常处理机制在运行期间解决!应当在编码时及时修正
java网络编程
java.net.Socket
Socket(套接字)封装了TCP协议的通讯细节,是的我们使用它可以与服务端建立网络链接,并通过 它获取两个流(一个输入一个输出),然后使用这两个流的读写操作完成与服务端的数据交互
java.net.ServerSocket
ServerSocket运行在服务端,作用有两个:
1:向系统申请服务端口,客户端的Socket就是通过这个端口与服务端建立连接的。
2:监听服务端口,一旦一个客户端通过该端口建立连接则会自动创建一个Socket,并通过该Socket与客户端进行数据交互。
如果我们把Socket比喻为电话,那么ServerSocket相当于是某客服中心的总机。
与服务端建立连接案例:
还有需要优化的点,现在没有学习多线程的知识,所以服务器端无法接收多个客户同时连接服务器,并且我独自再客户端中try()添加了流自动关闭的功能,这样才能让客户端顺利退出,服务器端不报错。只有一个客户端退出,另一个才能连接,否则会直接报错。
- Server服务器端代码
package socket1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private ServerSocket serverSocket;
public Server() {
try {
System.out.println("启动服务器。。。");
serverSocket = new ServerSocket(8088);
System.out.println("服务器启动完毕!");
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
try {
while (true) {
System.out.println("等待客户端连接。。。");
Socket socket = serverSocket.accept();
System.out.println("有一个客户连接");
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
String message;
while ((message = br.readLine()) != null) {
System.out.println("客户端说:" + message);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
}
- Client客户端代码
package socket1;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class Client {
private Socket socket;
public Client() {
try {
System.out.println("客户端启动。。。");
socket = new Socket("localhost",8088);
System.out.println("客户端启动成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
try (
OutputStream out = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(out);
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw,true);
)
{
Scanner scan = new Scanner(System.in);
while (true){
String line = scan.nextLine();
if ("exit".equals(line)){
System.out.println("退出成功");
pw.println("我下线了");
break;
}
pw.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
Client client = new Client();
client.start();
}
}
多线程
线程:一个顺序的单一的程序执行流程就是一个线程。代码一句一句的有先后顺序的执行。
多线程:多个单一顺序执行的流程并发运行。造成"感官上同时运行"的效果。
并发:
多个线程实际运行是走走停停的。线程调度程序会将CPU运行时间划分为若干个时间片段并
尽可能均匀的分配给每个线程,拿到时间片的线程被CPU执行这段时间。当超时后线程调度
程序会再次分配一个时间片段给一个线程使得CPU执行它。如此反复。由于CPU执行时间在
纳秒级别,我们感觉不到切换线程运行的过程。所以微观上走走停停,宏观上感觉一起运行
的现象成为并发运行!
用途:
- 当出现多个代码片段执行顺序有冲突时,希望它们各干各的时就应当放在不同线程上"同时"运行
- 一个线程可以运行,但是多个线程可以更快时,可以使用多线程运行
创建线程
方式一:继承Thread并重写run方法
定义一个线程类,重写run方法,在其中定义线程要执行的任务(希望和其他线程并发执行的任务)。
注:启动该线程要调用该线程的start方法,而不是run方法!!!
package test;
public class ThreadDemo {
public static void main(String[] args) {
Thread t1 = new Thread1();
Thread t2 = new Thread2();
/*
需要注意,启动线程要调用线程的start方法,而不是直接调用run方法!
*/
t1.start();
t2.start();
}
}
class Thread1 extends Thread{
public void run(){
for (int i = 0; i < 10000; i++) {
System.out.println("今天天气怎么样啊?");
}
}
}
class Thread2 extends Thread{
public void run(){
for (int i = 0; i < 10000; i++) {
System.out.println("还不错吧,就是风有些大");
}
}
}