• Java复习六:内部类+异常处理


    内部类

    java允许将一个类A声明在另一个类B中,则A是内部类,类B称为外部类

    内部类的分类:

    ​ 成员内部类 静态+非静态

    ​ 局部内部类 方法内,代码块内,构造器内

    成员内部类 :

    ​ 1 作为外部类的成员

    ​ 调用外部类的结构 外部class.this.结构

    ​ 可以被static修饰

    ​ 可以被四种不同的

    ​ 2 作为一个类

    ​ 类可以定义属性,方法,构造器等

    ​ 可以被final修饰,表示此类不能被继承

    ​ 可以被abstract修饰

    package t1_InnerClass;
    
    /**
     * 内部类是在类里定义的类
     * @Author: zhangfan
     * version 1.0
     * @Date: 2022/07/18/10:48
     */
    public class InnerClassTest {
        private String name="小花";
        public static void main(String[] args) {
            //static修饰的结构随着类的加载而加载
            InnerClassTest.EE ee=new InnerClassTest.EE();
            ee.show();
    
            //非静态成员应该由对象调用
            InnerClassTest innerClassTest=new InnerClassTest();
            InnerClassTest.DD dd=innerClassTest.new DD();
            dd.show();
    
        }
        //代码块内内部类
        {
            class AA{
    
            }
        }
    
        //方法内内部类
        void method() {
            class BB{
                void method(){
                }
            }
        }
    
        public InnerClassTest(){
            //构造器内内部类
            class CC{
    
            }
        }
    
        //成员内部类
        class DD{
            String name="静态";
            public void show(){
                String name="小紫";
                System.out.println("我是一个非静态成员内部类");
                //成员内部类访问内部类方法里的同名属性
                System.out.println(name);
                //成员内部类访问内部类的同名属性
                System.out.println(this.name);
                //成员内部类访问外部类的同名属性
                System.out.println(InnerClassTest.this.name);
            }
        }
    
        //静态成员内部类
        static class EE{
            public void show(){
                System.out.println("我是一个静态成员内部类");
            }
        }
    }
    
    • 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    成员内部类和局部内部类,在编译之后都会生成字节码文件,

    格式: 成员内部类:外部类$内部类名.class

    ​ 局部内部类:外部类$数字内部类.class

    方法里的局部内部类调用外部类的方法中的属性时,属性默认为final的

    package t1_InnerClass;
    
    /**
     * 内部类的字节码文件
     * @Author: zhangfan
     * version 1.0
     * @Date: 2022/07/18/16:25
     */
    public class InnerClassTest2 {
        public static void main(String[] args) {
            System.out.println(AA.class);
            InnerClassTest2 innerClassTest2=new InnerClassTest2();
            innerClassTest2.method();
        }
        class AA{
    
        }
         void method(){
            int num=10;
       
            class BB{
                public void show(){
                    //方法里的局部内部类调用外部类的方法中的属性时,属性默认为final的
                    //num=200; 会报错
                    System.out.println(num);
                }
            }
            System.out.println(BB.class);
        }
    }
    
    • 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
    • 29
    • 30

    异常

    throwable异常区分为两类:Error和Exception

    Error:Java虚拟机无法解决的严重问题

    Exception:其他因编程错误或偶然的外在因素导致的一般性问题

    ​ 编译时异常(受检异常),执行javac.exe时可能出现

    ​ 运行时异常(非受检异常),执行java.exe时可能出现

    常见异常举例

    package t1_InnerClass;
    
    import org.junit.jupiter.api.Test;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.util.Date;
    import java.util.Scanner;
    
    /**
     * 常见运行时异常
     *
     * @Author: zhangfan
     * version 1.0
     * @Date: 2022/07/18/17:16
     */
    public class t2_exception {
        //NullPointerException
        @Test
        public void test1(){
            String str=null;
            System.out.println(str.charAt(0));
        }
    
        //ArrayIndexOutofBoundsException
        @Test
        public void test2(){
            int[] arr=new int[3];
            arr[3]=5;
        }
    
        //ClassCastException
        @Test
        public void test3(){
            Date date = new Date();
            String str=(String)(Object)date;
        }
    
        //NumberFormatEcception
        @Test
        public void test4(){
            Integer integer=Integer.parseInt("abc");
        }
    
        //InputMismatchException
        @Test
        public void test5(){
            Scanner scanner=new Scanner(System.in);
            int score=scanner.nextInt();
            System.out.println(score);
            scanner.close();
        }
    
        //ArithmeticException
        @Test
        public void test6(){
            int a=10;
            int b=0;
            System.out.println(a/b);
        }
    
        //编译时异常
        //FileNotFoundException
        @Test
        public void test7(){
            String road="hello.txt";
            File file=new File(road);
            FileInputStream fis=new FileInputStream(file);
    
            int data = fis.read();
            while (data!=-1){
                System.out.println((char)data);
                data=fis.read();
            }
            fis.close();
        }
    }
    
    • 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    异常处理:抓抛模型

    抛 程序遇到异常,在异常代码处生成一个异常类对象,将对象抛出,后续代码不再执行

    抓 对抛出的异常进行处理1 try catch finally, throws

    说明:

    finally是可选的

    使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常的都西昂,根据此对象的类型,去catch中进行匹配。

    一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理,一旦处理完成,就跳出当前的try-catch结构,在没有finally的情况下,继续执行其后的代码

    catch中的异常类型如果没有子父类关系,则声明在上在下无所谓

    catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面,否则报错

    常用的异常处理方式:1 String getMessage() 2 printStackTrace()

    try-catch-finally 处理编译时异常,编译时不再报错,运行时仍然可能报错,相当于将编译时可能出现的异常延迟到运行时出现

    try中声明的变量出了try之后不可以再用。

    try-catch-finally中finally的使用

    1 finally是可选的,即可写可不写

    2 finally中声明的代码是一定会执行的代码。例如以下情况也会执行

    ​ 1 try中return

    ​ 2 catch中有异常

    ​ 3 cathch中有return

    3 finally内部一般语句。数据库连接,输入输出流,网络编程Socket等资源,JVM不会自动回收,我们需要手动进行资源释放。此时资源释放,需要放入finally中

    public class finallyTest1 {
    
        /**
         *TODO
         * finally代码和异常之后代码的区别
         * 1 try中无异常有return语句,finally执行
         * 2 try中有位于return语句之前的异常发生,且此异常catch语句中有return,finally执行
         */
        @Test
        public void test1(){
            try {
                //两者都会执行
                int a=2,b=0;
                //b=1; 普通执行不会执行
                System.out.println(a/b);
                //return; 普通执行不会执行
            }catch (ArithmeticException e){
                e.printStackTrace();
               //return; 普通执行不会执行
            }finally {
                System.out.println("finally执行");
            }
            System.out.println("普通执行");
        }
    
        /**
         * TODO
         * try,catch,finally中都有返回值,且会执行catch语句时
         * 结论:finally中有返回finally
         *      如果无try无异常返回try,try有异常返回catch
         */
        @Test
        public void test2(){
            System.out.println(method());
        }
    
        public int method(){
            try {
                //两者都会执行
                int a=2,b=0;
                System.out.println(a/b);
                return 1;
            }catch (ArithmeticException e){
                e.printStackTrace();
                return 2;
            }finally {
                System.out.println("finally执行");
                return 3;
            }
        }
        
        /**
         * TODO
         * finally在文件读取中的使用
         * 1 创建文件对象
         * 2 创建文件输入流
         * 3 绑定文件
         * 4 读取文件
         * 5 处理FileNotFoundException
         * 6 处理IOException
         * 7 关闭文件输入流
         * 8 处理IOException
         */
        @Test
        public void test3(){
            String road="hello.txt";
            File file=new File(road);
            FileInputStream fis= null;
            try {
                fis = new FileInputStream(file);
                int data = fis.read();
                while (data!=-1){
                    System.out.println((char)data);
                    data=fis.read();
                }
                fis.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }catch (IOException e){
                e.printStackTrace();
            }finally {
                //如果没找到文件直接进入异常可能会导致fis为空指针,所以要进行判断
                if (fis!=null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    • 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92

    throws一般是将异常往上抛,但是一般main中就不应该再抛了,try—catch才是处理异常

    一旦当方法体执行时,出现异常,仍会再异常代码处生成一个异常对象,
    此对象满足throws后异常类型时,就会被抛出。异常代码后续代码不会
    再执行

    开发中异常处理的选择:

    ​ 1 父类被重写的方法没有throws方式处理异常,子类重写也不能使用throws,如果子类重写的方法有异常,必须使用try-catch-finally处理

    ​ 2 在执行方法中,又调用另外的几个方法,这几个方法是递进关系,建议使用throws处理,执行方法中可以考虑使用try-catch-finally处理,因为前面的方法中出现异常,意味着要抛出,而不应当是处理之后将无用的数据继续执行

    手动抛出异常

    使用throw手动抛出异常:

    throws处理的是系统自动生成的异常对象,throw用于手动生成对象并抛出

    public class ThrowTest {
        public static void main(String[] args) {
            try {
                Student student = new Student();
                student.register(-1001);
                System.out.println(student);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
    
    class Student{
        private int id;
    
        public void register(int id) throws Exception {
            if(id>0){
                this.id=id;
            }else{
                //生成异常并抛出
                throw new Exception("您输入的数据非法!");
            }
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    '}';
        }
    }
    
    • 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
    • 29
    • 30
    • 31
    自定义异常:

    ​ 1 继承于现有的结构:RuntimeException,Exception

    ​ 2 提供全局常量:serialVersionUID 用于标识异常的序列号

    ​ 3 提供重载的构造器

    public class MyException extends RuntimeException{
        //标识异常的序列号
        static final long serialVersionUID = -7034897190745766939L;
        
        public MyException() {
            
        }
        
        public MyException(String msg){
            //调用父类构造器
            super(msg);
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    异常练习
    
    public class EcmDef {
        public static void main(String[] args) {
            try{
                Integer a=Integer.parseInt(args[0]);
                Integer b=Integer.parseInt(args[1]);
                System.out.println(ecm(a,b));
            }catch (ArithmeticException e){
                System.out.println("除0");
            }catch (NumberFormatException e){
                System.out.println("数据格式不对");
            }catch (ArrayIndexOutOfBoundsException e){
                System.out.println("缺少参数");
            }catch (EcDef e){
                System.out.println(e.getMessage());
            }
    
        }
        public static int ecm(int a,int b)throws EcDef{
            if(a<0||b<0){
                throw new EcDef("不可以为负数");
            }
            return a/b;
        }
    }
    class EcDef extends RuntimeException{
        private static final long serialVersionUID = -7034897190745766940L;
    
        public EcDef(){
    
        }
    
        public EcDef(String msg){
            super(msg);
        }
    }
    
    • 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    使用命令行调试:

    记得去掉包名,并且注意文档的字符编码,我用的ANSI编码中文才不会乱码

  • 相关阅读:
    《WEB前端框架开发技术》HTML5响应式旅游景区网站——榆林子州HTML+CSS+JavaScript
    开源IDaaS方舟一账通ArkID系统内置OIDC 认证插件配置流程
    leetcode做题笔记162. 寻找峰值
    vite介绍
    《PolarDB-X学习》第一讲
    乘方(pow) CSP-J2022
    在 Streamlit 中使用自定义 CSS 创建加密仪表板
    【C++】智能指针
    mysql-执行计划
    java中的自定义对象排序
  • 原文地址:https://blog.csdn.net/zf111212/article/details/126075131