菜鸟之路Day14一一异常与File

简介: 此篇博客详细介绍了Java中的异常处理机制和File类的常用操作。

菜鸟之路Day14一一异常与File

作者:blue

时间:2025.2.2

1.异常

1.1异常体系

image-20250202111339143.png

Error:代表的系统级别错误(属于严重问题)系统一旦出现问题,sun公司会把这些错误封装成Error对象。Error是给sun公司自己用的,不是给我们程序员用的。因此我们开发人员不用管它。

Exception:叫做异常,代表程序可能出现的问题。我们通常会用Exception以及它的子类来封装程序出现的问题

运行时异常:RuntimeException及其子类,编译阶段不会出现异常提醒。运行时出现的异常(如:数组索引越界异常)

编译时异常:直接继承于Excpetion,编译阶段就会出现异常提醒。(如:日期解析异常)

1.2异常的作用

作用一:异常时用来查询bug的关键参考信息

作用二:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况

1.3异常的处理方式

①JVM默认的处理方式

​ 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台

​ 程序停止执行,下面的代码不会再执行了

②自己处理(捕获异常)

try {
    可能出现异常的代码;
} catch(异常类名 变量名) {
    异常的处理代码;
}

目的:当代码出现异常的时候,可以让程序继续往下执行

public class Demo1 {
   
    public static void main(String[] args) {
   

        int[] arr = {
   1,2,3,4,5,6};
        try{
   
            //可能出现异常的代码
            System.out.println(arr[10]);//此处出现了异常,程序就会创建ArrayIndexOutOfBoundsException对象
                                        //new ArrayIndexOutOfBoundsException();
                                        //拿着这个对象到catch的小括号中对比,看括号中的变量是否可以接受对象
                                        //如果能被接受,就表示该异常被捕获(抓住),执行catch里面对应的代码
                                        //当catch里面的代码执行完毕,继续执行try...catch体系下面其他代码
        }catch(ArrayIndexOutOfBoundsException e){
   
            //如果出现了ArrayIndexOutOfBoundsException异常,我该如何处理
            System.out.println("索引越界了");
        }

        System.out.println("看看我执行了吗?");
    }
}

有关捕获异常的四个问题

一.如果try中没有遇到问题,怎么执行?

public class Demo1 {
   
    public static void main(String[] args) {
   

        int[] arr = {
   1,2,3,4,5,6};
        try{
   
            //正常的代码
            System.out.println(arr[0]);
        }catch(ArrayIndexOutOfBoundsException e){
   
            //如果出现了ArrayIndexOutOfBoundsException异常,我该如何处理
            System.out.println("索引越界了");
        }
        System.out.println("看看我执行了吗?");
    }
}

答:会把try里面的所有代码全部执行完毕,不会执行catch里面的代码,只有当出现了异常才会执行catch里面的代码

二.如果try中可能遇到多个问题,怎么执行?

public class Demo2 {
   
    public static void main(String[] args) {
   
        int[] arr = {
   1,2,3,4,5,6};
        try{
   
            System.out.println(arr[10]);
            System.out.println(2/0);
        }catch(ArrayIndexOutOfBoundsException e){
   
            //如果出现了ArrayIndexOutOfBoundsException异常,我该如何处理
            System.out.println("索引越界了");
        }catch (ArithmeticException e){
   
            System.out.println("不能做除0操作");
        }
        System.out.println("看看我执行了吗?");
    }
}

答:我们会写多个catch与之对应,如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面,在JDK7之后,我们可以在catch中同时捕获多个异常,中间用|进行隔开,表示如果出现了A异常或者B异常,采取同一种处理方案。

三.如果try中遇到问题没有被捕获,怎么执行?

答:相当于try....catch的代码白写了,

四.如果try中遇到了问题,那么try下面的其他代码还会执行吗?

答:下面的代码不会执行了,直接跳转到对应的catch当中,执行catch里面的语句体,但是如果没有对应catch与之匹配,那么还是会交给虚拟机进行处理

③抛出异常

1.关于抛出异常的一些常用方法(Throwable的成员方法)

public class Demo3 {
   
    public static void main(String[] args) {
   
        /*
        *   public String getMessage()  返回此throwable的详细消息字符串
        *   public String toString()    返回此可抛出的简短描述
        *   public void printStackTrace() 把异常的错误信息输出在控制台
        *                               细节:仅仅是打印信息,不会停止程序运行
        * */

        int[] arr = {
   1,2,3,4,5,6};
        try {
   
            System.out.println(arr[10]);
        } catch (ArrayIndexOutOfBoundsException e){
   
            /*String message = e.getMessage();
            System.out.println(message); Index 10 out of bounds for length 6 */

            /*String str = e.toString();
            System.out.println(str); java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 6*/

            e.printStackTrace();
        }
        System.out.println("看看我执行了吗?");
    }
}

2.抛出处理

①throws:写在方法定义处,表明声明一个异常,告诉调用者,使用本方法可能会有哪些异常

编译时异常:必须要写

运行时异常:可以不写

public void 方法()throws 异常类名1,异常类名2...{
   
    ...
}

②throw:写在方法内,结束方法

手动抛出异常对象,交给调用者

方法中下面的代码不再执行了

public void 方法(){
   
    throw new NullPointerException();
}

实例:

public class Demo4 {
   
    public static void main(String[] args) {
   
        int[] arr = null;
        int max = 0;
        try {
   
            max = getMax(arr);
        } catch (NullPointerException e) {
   
            System.out.println("空指针异常");
        } catch (ArrayIndexOutOfBoundsException e) {
   
            System.out.println("索引越界异常");
        }

        System.out.println(max);
    }
    public static int getMax(int[] arr){
   
        if(arr==null){
   
            //手动创建一个异常对象,并把这个异常交给方法调用者来处理
            //此时方法就会结束,下面的代码不会执行了
            throw new NullPointerException();
        }
        if(arr.length == 0){
   
            throw new ArrayIndexOutOfBoundsException();
        }
        int max = arr[0];
        for(int i=1;i<arr.length;i++){
   
            if(arr[i]>max) max = arr[i];
        }
        return max;
    }
}

练习:

需求:
键盘录入自己心仪的女朋友姓名和年龄。
姓名的长度在3~10之间
年龄的范围为18-40岁
超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
提示
需要考虑用户在键盘录入时的所有情况。
比如:录入年龄时超出范围,录入年龄时录入了abc等情况

public class Demo5 {
   
    public static void main(String[] args) {
   
        GirlFriend gf = new GirlFriend();
        Scanner sc = new Scanner(System.in);
        while (true) {
   
            try {
   
                System.out.println("请输入你心仪女朋友的姓名");
                String name = sc.nextLine();
                gf.setName(name);//有可能出现错误
                System.out.println("请输入女朋友的年龄");
                String age = sc.nextLine();
                int Age = Integer.parseInt(age);//有可能出现错误
                gf.setAge(Age);//有可能出现错误
                break;
            } catch (NumberFormatException e) {
   
                System.out.println("年龄的格式有误,请输入数字");
            } catch (RuntimeException e) {
   
                System.out.println("姓名或年龄超出范围");
            }
        }
        System.out.println(gf);
    }
}

在GirlFriend类中,对set方法的数据做限定,如果不是正确数据,就抛出一个RuntimeException对象

public class GirlFriend {
   
    private String name;
    private int age;

    public GirlFriend() {
   
    }

    public GirlFriend(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        if(name.length()<3||name.length()>10){
   
            throw new RuntimeException();
        }
        this.name = name;
    }

    public int getAge() {
   
        return age;
    }

    public void setAge(int age) {
   
        if(age<18||age>40){
   
            throw new RuntimeException();
        }
        this.age = age;
    }

    @Override
    public String toString() {
   
        return "GirlFriend{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

1.4自定义异常

在刚刚的练习代码中,我们针对名字和年龄的异常都是抛出一个RuntimeException,但不够具体,不够见名知意,这时我们就可以自定义异常。

①定义异常类

②写继承关系

③空参构造

④带参构造

意义:让控制台的报错信息更加见名知意

现在的idea建类的时候都有Exception选项

public class NameFormatException extends RuntimeException {
   
  public NameFormatException() {
   
  }

  public NameFormatException(String message) {
   
        super(message);
    }
}

然后我们修改对应的抛出错误的方法

public void setName(String name) {
   
     if(name.length()<3||name.length()>10){
   
           throw new NameFormatException(name+"姓名的长度在3~10之间");
     }
     this.name = name;
}

然后我们修改对应的catch异常的对象,调用方法把异常的错误信息输出在控制台即可

catch (NameFormatException e) {
   
       e.printStackTrace();
}

2.File

2.1构造方法

File对象就表示一个路径,可以是文件的路径,也可以是文件夹的路径

这个路径可以是存在的,也允许是不存在的

构造方法演示:

public class Demo1 {
   
    public static void main(String[] args) {
   
        /*
        * public File(String pathname)  把字符串表示的路径变成File对象
        * public File(String parent,String child) 把父级路径和子级路径进行拼接
        * public File(File parent,String child) 把父级路径和子级路径进行拼接
        * windows: "\"
        * java:"\"->转义字符,所以得有两个\\
        * Linux:"/"
        * */


        String str = "C:\\Users\\zhangtenlan\\Desktop\\test.txt";

        //1.public File(String pathname)  把字符串表示的路径变成File对象
        File f1 = new File(str);
        System.out.println(f1);//C:\Users\zhangtenlan\Desktop\test.txt


        //2.public File(String parent,String child) 把父级路径和子级路径进行拼接
        //父级路径:C:\Users\zhangtenlan\Desktop
        //子级路径:test.txt
        String parent = "C:\\Users\\zhangtenlan\\Desktop";
        String child = "test.txt";
        File f2 = new File(parent,child);
        System.out.println(f2);//C:\Users\zhangtenlan\Desktop\test.txt


        //3.public File(File parent,String child) 把父级路径和子级路径进行拼接
        File fparent = new File(parent);
        File f3 = new File(fparent,child);
        System.out.println(f3);//C:\Users\zhangtenlan\Desktop\test.txt
    }
}

2.2File的成员方法(判断,获取)

判断方法演示:

public class Demo2 {
   
    public static void main(String[] args) {
   
        //public boolean isDirectory()  判断此路径名表示的File是否为文件夹
        //public boolean isFile()       判断此路径名表示的File是否为文件
        //public boolean exists()       判断此路径名表示的File是否存在

        //1.对一个存在的文件做判断
        File f1 = new File("C:\\Users\\zhangtenlan\\Desktop\\test.txt");
        System.out.println(f1.isDirectory());//false
        System.out.println(f1.isFile());//true
        System.out.println(f1.exists());//true
        System.out.println("----------------------------------------------------");

        //2.对一个存在的文件夹做判断
        File f2 = new File("C:\\Users\\zhangtenlan\\Desktop\\TEST");
        System.out.println(f2.isDirectory());//true
        System.out.println(f2.isFile());//false
        System.out.println(f2.exists());//true
        System.out.println("----------------------------------------------------");

        //3.对一个不存在的文件做判断
        File f3 = new File("C:\\Users\\zhangtenlan\\Desktop\\aaa");
        System.out.println(f3.isDirectory());//false
        System.out.println(f3.isFile());//false
        System.out.println(f3.exists());//false
    }
}

获取方法演示:

public class Demo3 {
   
    public static void main(String[] args) {
   
        //1.public long length()  返回文件的大小(字节数量Byte)
        File f1 = new File("C:\\Users\\zhangtenlan\\Desktop\\test.txt");
        System.out.println(f1.length());//注意只能获取文件的大小,文件夹却不行

        System.out.println("=================================================");

        //2.public String getAbsolutePath() 返回文件的绝对路径
        File f2 = new File("src/File");//用相对路径创建一个File对象
        System.out.println(f2.getAbsoluteFile());//D:\some_test_project_of_my_own\Day14\src\File

        System.out.println("=================================================");

        //3.public String getPath()   返回定义文件时使用的路径
        System.out.println(f2.getPath());//src\File

        System.out.println("=================================================");

        //4.public String getName()   返回文件名称,带后缀
        System.out.println(f1.getName());//test.txt

        System.out.println("=================================================");

        //5.public long lastModified() 返回文件的最后修改时间(时间毫秒值)
        System.out.println(f1.lastModified());//1738810278724
    }
}

2.3File的成员方法(创建,删除)

public class Demo4 {
   
    public static void main(String[] args) throws IOException {
   
        //1.public boolean createNewFile() 创建一个新的空的文件
        //如果当前路径表示的文件是不存在的,则创建成功,方法返回true
        //如果当前路径表示的文件是存在的,则创建失败,方法返回false
        //如果父级路径是不存在的,那么方法会有异常IOException
        //该方法创建的一定是文件,如果路径中不包含后缀名,则创建一个没有后缀的文件

        File f1 = new File("C:\\Users\\zhangtenlan\\Desktop\\test.txt");
        System.out.println(f1.createNewFile());

        //2.public boolean mkdir() 创建单级文件夹,没什么用,因为它mkdirs既能创建多级又能创建单级


        //3.public boolean mkdirs() 创建多级文件夹
        File f2 = new File("C:\\Users\\zhangtenlan\\Desktop\\aaa\\bbb\\ccc");
        System.out.println(f2.mkdirs());

        //4.public boolean delete() 删除文件,空文件夹
        //如果删除的是文件,则直接删除,不走回收站
        //如果删除的是空文件夹,则直接删除,不走回收站
        //如果删除的是有内容的文件夹,则删除失败
        System.out.println(f1.delete());

    }
}

2.4File的成员方法(获取并遍历)

public class Demo5 {
   
    public static void main(String[] args) {
   
        /*
        * public File[] listFiles() 获取当前该路径下所有内容
        * 当调用者File表示的路径不存在时,返回null
        * 当调用者File表示的路径是文件时,返回null
        * 当调用者File表示的路径是一个空文件夹时,返回一个长度为0的数组
        * 当调用者File表示的路径是一个有内容的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回
        * 当调用者File表示的路径是一个有隐藏文件的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件
        * 当调用者File表示的路径是需要权限才能访问的文件夹时,返回null
        * */
        File f1 = new File("C:\\Users\\zhangtenlan\\Desktop\\aaa");
        File[] arr = f1.listFiles();
        for(File f : arr){
   
            System.out.println(f);
        }

    }
}

内容学习至黑马程序员BV1yW4y1Y7Ms

目录
相关文章
|
人工智能 弹性计算 算法
一文解读:阿里云AI基础设施的演进与挑战
对于如何更好地释放云上性能助力AIGC应用创新?“阿里云弹性计算为云上客户提供了ECS GPU DeepGPU增强工具包,帮助用户在云上高效地构建AI训练和AI推理基础设施,从而提高算力利用效率。”李鹏介绍到。目前,阿里云ECS DeepGPU已经帮助众多客户实现性能的大幅提升。其中,LLM微调训练场景下性能最高可提升80%,Stable Difussion推理场景下性能最高可提升60%。
127642 268
|
Java API Spring
Java SpringBoot 公众号集成模板推送消息
Java SpringBoot 公众号集成模板推送消息
|
Java 编译器 Apache
Doris FE源码解读系列之源码编译踩坑!!!(下)
Doris FE源码解读系列之源码编译踩坑!!!
1108 1
Doris FE源码解读系列之源码编译踩坑!!!(下)
|
机器学习/深度学习 算法 数据可视化
利用SVM(支持向量机)分类算法对鸢尾花数据集进行分类
本文介绍了如何使用支持向量机(SVM)算法对鸢尾花数据集进行分类。作者通过Python的sklearn库加载数据,并利用pandas、matplotlib等工具进行数据分析和可视化。
1176 70
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
529 23
|
SQL 数据安全/隐私保护 索引
SQL语句速成
《SQL语句速成》由blue编写,涵盖建表、插入、查询、更新、删除、视图创建、权限管理及索引操作等核心内容。通过具体示例介绍SQL基本语法和常用聚合函数,帮助读者快速掌握SQL编程技巧。发布于2024年7月19日。
268 7
|
人工智能 开发者
3步,0代码!一键部署DeepSeek-V3、DeepSeek-R1
3步,0代码!一键部署DeepSeek-V3、DeepSeek-R1
454 3
|
Java 程序员
菜鸟之路Day22一一反射与动态代理
本文介绍了Java反射机制和动态代理的基本概念及应用。反射允许编程访问类的成员变量、构造方法和成员方法,通过三种方式获取Class对象,并演示了如何使用反射创建对象、调用方法和修改字段值。动态代理则通过接口实现无侵入式功能增强,展示了如何利用`Proxy`类和`InvocationHandler`接口生成代理对象并拦截方法调用。结合实例代码,详细讲解了反射在实际开发中的应用场景,如保存对象信息到文件和根据配置文件动态创建对象。 反射的主要作用包括: 1. 获取类的所有信息。 2. 结合配置文件动态创建对象。 动态代理的核心优势在于能够在不修改原有代码的情况下,为对象添加额外功能。
217 0
|
机器学习/深度学习 搜索推荐 算法框架/工具
使用Python实现深度学习模型:智能运动表现分析
使用Python实现深度学习模型:智能运动表现分析
750 1

热门文章

最新文章