API08

##day08 笔记:

一、throw续和throws

1. throw用来对外主动抛出一个异常,通常两种情况会主动对外抛出异常:

    - 当程序遇到一个满足语法,但是不满足业务要求时,可以抛出一个异常告知调用者。

    - 程序执行遇到一个异常,但是该异常不应当在当前代码片段被解决时可以抛出给调用者

           

        public void setAge(int age)throws Exception{

        if (age<0||age>100){

         //throw new RuntimeException("年龄超出了范围");      只有这个异常时方法上面可以不用throws

            throw new Exception("年龄超出了范围");

        }

        this.age = age;

    }

2. 当我们使用throw主动对外抛出一个异常时,除了RuntimeException以外的其他异常都需要在方法上显示的声明throws来对外告知要抛出该异常

    - 当我们调用一个含有throws声明异常抛出的方法时,编译器要求我们必须处理该异常。处理方式有两种:

       1)使用try-catch主动捕获并处理该异常

       2)在这句代码所在的方法(这里是main方法)上继续使用throws对外声明抛出给上层调用者

      具体选取那种需要结合实际业务分析该异常处理的责任问题。

       3)永远不要在main方法上声明throws

         Person p = new Person();

        //满足语法不满足业务场景

        try {

            p.setAge(1000);

        } catch (Exception e) {

            e.printStackTrace();

        }

        System.out.println("此人年龄:"+p.getAge());

3. 当子类重写超类含有throws声明异常抛出的方法时,对throws的重写规则

        public class ThrowsDemo {

            public void dosome()throws IOException, AWTException { }

        }

        class SubClass extends ThrowsDemo{

            1)允许抛出相同异常

            public void dosome()throws IOException, AWTException { }

          

 2)允许不再抛出任何异常

            public void dosome(){ }

            3)允许仅抛出部分异常

            public void dosome()throws IOException{ }

            4)允许抛出超类方法声明抛出异常的子类型异常

            public void dosome()throws FileNotFoundException { }

            5)不允许抛出额外异常(超类方法没有声明的且不存在继承关系的)

            public void dosome()throws SQLException { }

           6) 不允许抛出超类方法抛出异常的超类型异常

            public void dosome()throws Exception { }

        }

4.  异常分类

1)Java异常可以分为可检测异常,非检测异常:

    - 可检测异常:可检测异常经编译器验证,对于声明抛出异常的任何方法,编译器将强制执行处理或声明规则,不捕捉这个异常,编译器就通不过,不允许编译

    - 非检测异常:非检测异常不遵循处理或者声明规则。在产生此类异常时,不一定非要采取任何适当操作,编译器不会检查是否已经解决了这样一个异常

    - RuntimeException类属于非检测异常,因为普通JVM操作引起的运行时异常随时可能发生,此类异常一般是由特定操作引发。但这些操作在java应用程序中会频繁出现。因此它们不受编译器检查与处理或声明规则的限制。实际上RuntimeException及其子类型表达的都是因为程序漏洞(BUG),即:逻辑不严谨等原因导致的。这类异常都是通过修复代码可完全避免的异常,因此不应当由异常处理机制来处理

2)常见的RuntimeException子类

    - IllegalArgumentException:抛出的异常表明向方法传递了一个不合法或不正确的参数

    - NullPointerException:当应用程序试图在需要对象的地方使用 null 时,抛出该异常

    - ArrayIndexOutOfBoundsException:当使用的数组下标超出数组允许范围时,抛出该异常

    - ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出该异常

    - NumberFormatException:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。

5.异常API

1)Exception上有一些常用的方法

    - void printStackTrace():用于输出当前异常的堆栈跟踪信息

      便于程序员找到错误根源,分析错误原因制定B计划

    - String getMessage():用于获取当前错误消息

      多用于提示给用户或记录日志使用

  

        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("程序结束了");

2)自定义异常

    通常用来声明那些在项目中满足语法但是不满足业务场景的问题

    自定义异常需要做一下几件事:

    1:类名要做到见名知义

    2:继承Exception(直接或间接继承都可以)

    3:提供超类异常提供的所有构造器(单独建个类,后面使用时)

案例: 聊天室客户端

public class Client {

    /*      java.net.Socket 套接字

             Socket封装了TCP协议的通讯细节,使用它可以通过网络与远端计算机进行TCP链接

             并基于两条流(输入与输出)与远端计算机通讯。

             Socket可以想象为我们使用的"手机"。    */

    private Socket socket;

    // 构造器,用来初始化客户端

    public Client(){

        try {

            /* 实例化Socket时需要传入两个参数用于与远端计算机建立链接。

                实例化的过程就是与远端计算机建立链接的过程。

                如果实例化成功说明与远端计算机建立链接。如果建立链接失败则会抛出异常

                参数1:远端计算机的IP地址

                参数2:远端计算机上的服务端程序开启的服务端口

                我们通过IP可以找到网络上服务端所在的计算机,通过端口找到该计算机上 运行的服务端应用程序

                注:localhost代表本机      */

            System.out.println("正在链接服务端...");

            socket = new Socket("localhost",8088);

            System.out.println("与服务端成功链接!");

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    // 客户端开始工作的方法

    public void start() {

        try {

            /* Socket提供的重要方法

                OutputStream getOutputStream()

                通过socket获取的字节输出流写出的数据就会发送给与之连接的远端

                计算机。  */

            OutputStream out = socket.getOutputStream();

            OutputStreamWriter osw = new OutputStreamWriter(out, StandardCharsets.UTF_8);

            BufferedWriter bw = new BufferedWriter(osw);

            PrintWriter pw = new PrintWriter(bw,true);

            Scanner scanner = new Scanner(System.in);

            while(true) {

                String line = scanner.nextLine();//获取控制台输入的一行字符串

                if("exit".equalsIgnoreCase(line)){

                    break;

                }

                pw.println(line);

            }

        } catch (IOException e) {

            e.printStackTrace();

        } finally {

            //最终交互完毕后,要断开连接

            try {

                //close方法内部会进行TCP的四次挥手操作

                socket.close();

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

    }

    public static void main(String[] args) {

        Client client = new Client();

        client.start();

    }

}

// 聊天室服务端

public class Server {

    /* java.net.ServerSocket

     * 运行在服务端的ServerSocket主要有两个工作:

     * 1:打开服务端口,客户端就是通过这个端口与服务端建立连接的

     * 2:监听服务端口,一旦一个客户端连接,则立即返回一个Socket实例    */

    private ServerSocket serverSocket;

    public Server(){

        try {

            /*ServerSocket实例化的同时指定服务端口

                如果该端口被其他程序占用则会抛出异常:

                java.net.BindException:address already in use

                此时我们需要更换端口,或者杀死占用该端口的进程。

                端口号范围:0-65535     */

            System.out.println("正在启动服务端...");

            serverSocket = new ServerSocket(8088);

            System.out.println("服务端启动完毕!");

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    // 服务端开始工作的方法

    public void start(){

        try {

            /*  ServerSocket的一个重要方法:

                Socket accept()

           该方法用于接受客户端的连接。这是一个阻塞方法,调用后会"卡住",直到一个客户端与ServerSocket连接,此时该方法会立即返回一个Socket实例

           通过这个Socket实例与该客户端对等连接并进行通讯。

           相当于"接电话"的动作         */

            System.out.println("等待客户端连接...");

            Socket socket = serverSocket.accept();

            System.out.println("一个客户端连接了!");

            /*   Socket一个重要的方法

                InputStream getInputStream()

                通过socket获取的字节输入流可以读取远端计算机发送过来的数据*/

            InputStream in = socket.getInputStream();

            InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);

            BufferedReader br = new BufferedReader(isr);

            String line;

            /* 当客户端断开连接时,如果是异常断开,服务端这里readLine方法会

                抛出异常:ava.net.SocketException: Connection reset

               客户端正常挥手操作,那么服务端这里readLine方法会返回null*/

            while((line = br.readLine())!=null){

                System.out.println("客户端说:" + line);

            }

         } catch (IOException e) {

            e.printStackTrace();

        }

    }

    public static void main(String[] args) {

        Server server = new Server();

        server.start();          }    }

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值