Java入门(二十七)

内部类

  • 内部类就是在一个类的内部再定义一个类,比如在A类中定义一个B类,那么B类相对于A类就是一个内部类了。它分为很多种:
  1. 成员内部类
  2. 静态内部类
  3. 局部内部类
  4. 匿名内部类
  • 成员内部类,定义一个Outer类(外部类的意思)
    在这里插入图片描述
public class Outer {
    private int id;
    public void out(){
        System.out.println("这是外部类的方法");
    }
    class Inner{
        public void in(){
            System.out.println("这是内部类的方法");
        }
    }
}
  • 然后我们想办法测试他一下,外部类是通过new关键词实现的,内部类通过外部类来实例化。
public class Application {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
    }
}
  • 看看能不能打印出内部类的方法,比如内部类还可以直接访问外部类的一些私有变量和方法。
    在这里插入图片描述
  • 还有一种静态内部类,现在的类是通过public去修饰他。但是可以通过public static去修饰就变成静态的了。这个id就拿不到了
    在这里插入图片描述
  • 静态内部类无法访问非静态的属性。
  • 下面这样写也叫做内部类,相当于他在java文件里面写了两个不同的类。
    在这里插入图片描述
  • 一个java文件只能有一个public class,但是能有多个class类
  • 局部内部类,像方法里面定义的类就是局部内部类。
public class Outer {
    public void method(){
        class Inner{
            
        }
    }
}
  • 还可以写一些没有名字的类,这些类实例出来是没有名字的,就相当于把他给实现出来。不用把实例保存在变量中
public class Test {
    public static void main(String[] args) {
        //没有名字初始化类
        new Apple().eat();
    }
}
class Apple{
    public void eat(){
        System.out.println("1");
    }
}
  • 假设是接口
public class Test {
    public static void main(String[] args) {
        //没有名字初始化类
        new Apple().eat();
        UserService userService = new UserService(){
            @Override
            public void hello() {
                
            }
        };
        
    }
}
class Apple{
    public void eat(){
        System.out.println("1");
    }
}
interface UserService{
    void hello();
}

异常机制

  • java的异常机制Exception。在生活中,开车上班一般不会迟到,但是今天车坏了或限行了,你改做公交就有可能会迟到,这就是属于异常情况。
  • 实际工作中写的代码,正常来说用户应该输入一个数字,但是他输入了字符串或汉字,不一定符合我们的要求。包括程序要打开某个文件,但文件不存在。又或者程序跑着跑着内存满了,也是不行的。
public class demo01 {
    public static void main(String[] args) {
        new demo01().a();
    }
    public void a(){
        b();
    }
    public void b(){
        a();
    }
}
  • 程序报error了,并不是异常。
    在这里插入图片描述
  • 我们还可以输出11/0,0是不能成为被除数的。
    在这里插入图片描述
  • 有些错误要等程序跑起来才知道。有可能是jvm造成的,也有可能是因为程序员的问题。
  • 异常指程序运行中出现的不期而至的各种状况:文件找不到、网络连接失败、非法参数等。
  • 总共来说可以分为以下三大类:
  • 检查性异常:最具代表性的是检查性异常,用户错误或问题引起的异常,这是程序员无法预见的。例如打开一个不存在的文件,一个异常就发生了。这些异常不能再编译时简单地被忽略。
  • 运行时异常:运行时异常可能被程序员避免的异常。与检查性异常相反,运行时异常可以再编译时被忽略。
  • 错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如栈溢出时,一个错误就发生了,他在编译也检查不到的。
  • java提出了异常处理框架的思想,所有的异常都可以用一个异常类来表示。
    在这里插入图片描述
  • 异常体系结构:java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类,就是一个顶层,所有的都会在里面。
  • Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。error是无法预见的,exception可以预见。
  • 所有的异常都是Throwable的子类,Error主要是虚拟机错误和AWT错误(GUI)。一旦程序发生错误,后果比较严重。
  • 异常有IO异常和运行时异常:空指针异常,数组下标越界异常,未知类型异常。当这个异常出来之后我们要捕获他。

Error

  • Error类对象由Java虚拟机生成并抛出,大多数错误和代码编写者执行的操作无关。比如内存溢出、JVM直接就终止了。
  • 还有就是虚拟机想去跑一些应用的时候,突然类定义错误,他就会抛出NoClassDefFoundError、LinkAgeError错误。写代码觉察不到,并不在应用程序控制范围之内。

Exception

  • 运行时异常会帮程序运行的时候自定义一些异常:ArrayIndexOutOfBoundsException、NullPointerException、ArithmeticException、MissingResourceException、ClassNotFoundException。这些异常是不检查异常,程序可以选择捕获处理,也可以不处理。
  • 这些异常一般由程序逻辑错误引起,程序应该从逻辑角度避免发生。
  • 上面可以统称非运行时异常。这些异常是必须进行处理的,不处理的话编译都不通过。
  • 错误一般是灾难性的error,jvm会强行关掉。Exception处理异常就好了。

异常处理机制

  • 异常分为:抛出异常和捕获异常
  • 异常处理五个关键字:try(尝试处理)、catch(捕获)、finally(无论执不执行都会走的)、throw(抛出异常)、throws(从方法中抛出异常)
  • 像1除以0会报错,我怎么捕获异常然后返回一些信息呢?try代码区可以监控区域,只要在这里的代码有了异常就能捕获。catch捕获异常你首先要知道异常的类型。在catch里面只要捕获到上面的错误就打印一句话。finally无论怎么样都会执行,一般是用来处理一些善后的工作的。
public class Test {
public class Test {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try{
            System.out.println(a/b);
        }catch (ArithmeticException e){
            System.out.println("程序出现异常,变量b不能为0");
        }finally{
            System.out.println("finally");
        }
    }
}

在这里插入图片描述

  • 红色的东西没有了,异常被捕获了。
  • try和catch是这里面必须要有的东西,finally可以不要。
  • 后面会学一些io流,假如资源要关闭,关闭的操作就放在scanner里面。
  • 其他异常,假如栈溢出,试下用Throwable能不能抓到他。
public class Test {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try{
            new Test().a();
        }catch (Throwable e){
            System.out.println("程序出现异常,栈溢出");
        }finally{
            System.out.println("finally");
        }
    }
    public void a(){
        b();
    }
    public void b(){
        a();
    }
}
  • 可以发现Throwable可以捕获栈溢出,因为最高就是Throwable,几乎所有东西都能够被捕获到。
    在这里插入图片描述
  • java里面可以捕获多个异常,就跟if else一样层层递进。你要把最大的异常放在最下面
public class Test {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try{
            System.out.println(a/b);
        }catch(Error e){
            System.out.println("error");
        }catch(Exception e){
            System.out.println("exception");
        }catch(Throwable t){
            System.out.println("Throwable");
        }finally{
            System.out.println("finally");
        }
    }
    public void a(){
        b();
    }
    public void b(){
        a();
    }
}

在这里插入图片描述

  • 但是假如将exception和throwable调换一下位置就会报错了
    在这里插入图片描述
  • 假设要捕获多个异常,就必须从小到大地捕获。
  • 有时候我们想对一行代码自动生成try catch 。选中当前代码,ctrl + alt + t (command + alt + t)
    在这里插入图片描述
public class Test2 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try {
            System.out.println(a/b);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
    }
}
  • 这里有句话 e.printStackTrace();打印栈信息,打印错误的栈信息。
    在这里插入图片描述
  • 也可以让程序自己结束
    在这里插入图片描述
  • 假设有代码可能错误,可以加个if语句,然后主动地抛出异常
        try{
            if (b==0){
                throw new ArithmeticException();
            }
            System.out.println(a/b);
  • 结果运行后,抛出异常这里什么都没有做,所以抛出异常一般会在方法里面用
    在这里插入图片描述
  • 写除数的方法
public class Test {
    public static void main(String[] args) {
        new Test().test(1,0);
    }
    public void test(int a ,int b ){
        if (b==0){
            throw new ArithmeticException();
        }
        System.out.println(a/b);
    }
}

在这里插入图片描述

  • 他抛出了异常,假设不要方法体,正常应该没有做除法,但是他主动抛出异常了。
  • 有时候我们明明知道方法有异常,但是我们可以主动往外抛,抛到更高级。
  • 主动抛出后程序不会中断,会正常往下执行,这就是好处
public class Test {
    public static void main(String[] args) {
        try {
            new Test().test(1,0);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
    }
    public void test(int a ,int b )throws ArithmeticException{
        if (b==0){
            throw new ArithmeticException();
        }
        System.out.println(a/b);
    }
}

自定义异常

  • java和其他开源框架已经有很多定义了的异常,所以自定义异常并不常见。你不去写开源框架或大型系统,很少会用到这个。
  • Java内置的异常类可以描述在变成时出现的大部分异常情况,自己写的异常类处理小问题也可以使用它。用户自定义异常类,只需继承Exception类即可。
  1. 创建自定义异常类
  2. 在方法中通过throw关键字爬出异常对象。
  • 写一个自己的异常类
    在这里插入图片描述
  • 他必须继承Exception类,一旦继承了他就是异常类了。
  • 查一下这个异常
    在这里插入图片描述
  • 数组下标越界继承了其他异常类
    在这里插入图片描述
  • 这个又继承了运行时异常
    在这里插入图片描述
  • 一直到这里才继承到Exception类
    在这里插入图片描述
  • 异常他是这样写的,他首先有个构造方法,里面是空参的
    在这里插入图片描述
  • 构造方法也可以接受下标
    在这里插入图片描述
  • 这里又调用了父类的方法
    在这里插入图片描述
  • 这里是一个message
    在这里插入图片描述
  • 说白了就是打印这个message
    在这里插入图片描述
  • 咱们写一个,传递数字,如果数字大于10就抛出异常。抛出异常需要给人提示信息。
public class MyException  extends Exception{
    //传递数字>10
    private int detail;

    public MyException(int a) {
        this.detail = a;
    }
    //toString:异常的打印信息

    @Override
    public String toString() {
        return "MyException{" +
                "detail=" + detail +
                '}';
    }
}
  • 再来写一个测试类
public class Test {
    // 可能会存在异常的方法
    static void test(int a) throws MyException {
        System.out.println("传递的参数为:"+a);
        if(a>10){
            throw new MyException(a); //抛出
        }
        System.out.println("OK");
    }

    public static void main(String[] args) {
        try {
            test(1);
        } catch (MyException e) {
            System.out.println("MyExcetpion=>"+e);;
        }
    }
}

在这里插入图片描述

  • 如果传递11
    在这里插入图片描述

总结

  • 处理运行异常时,才用逻辑去合理规避同时辅助try-catch处理
  • 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常。
  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  • 尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出
  • 具体如何处理异常,要根据不同的业务需求和异常类型取决定
  • 尽量添加finally语句块去释放占用的资源
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值