不冷博客

异常处理和File类-11月16日讲课内容

异常

Throwable 类

Throwable 类是Java语言中所有错误和异常的顶级父类,直接子类为 Error 和 Exception

构造方法

// 无参构造:构造一个新的 throwable 对象,其详细信息为null
public Throwable()
    
// 有参构造:使用指定的详细信息(message)构造一个新的 throwable 对象
public Throwable(String message)

成员方法

// 返回此 throwable 对象的详细信息字符串
public String getMessage()

// 返回一个简要信息描述
public String toString()
    
// 打印此 throwable 对象及其详细信息字符串到标准错误流(控制台)
public void printStackTrace()

案例代码

public class Test {
    public static void main(String[] args) {
        Throwable throwable1 = new Throwable();
                
        System.out.println(throwable1.getMessage());
        System.out.println(throwable1.toString());
        throwable1.printStackTrace();
        
        Throwable throwable2 = new Throwable("错误信息!!!");
        
        System.out.println(throwable2.getMessage());
        System.out.println(throwable2.toString());
        throwable2.printStackTrace();
    }
}

Error

Error 类是 Throwable 的子类,它指出了一个合理的应用程序不应该试图捕捉的严重问题

【注意】Error 结尾的是严重问题,无法解决

Exception

Exception 类及其子类是一种 Throwable 的子类,指示了一个合理的应用程序可能想要捕获的条件。

【注意】Exception 结尾的是我们可以处理的,一般我们需要关注的是 RuntimeException

异常处理

异常处理分为两种:捕获和抛出

有能力处理就进行捕获,没有就抛出

捕获

格式:
    try {
        // 有可能出现问题的代码,存在一定隐患的代码
    } catch (异常类型 变量名) {
        // 对应当前异常类型的处理方式
    } finally {
        // 无论是否捕获,都会执行,常用于释放资源
    }

案例代码

public class Test {
    public static void main(String[] args) {
        int num1 = 0;
        int num2 = 20;

        int ret = 0;

        /*
         * 除数不能为0
         */
        try {
            ret = num2 / num1;
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }

        System.out.println(ret);
    }
}

结果

java.lang.ArithmeticException: / by zero
    at code.exception.Test.main(Test.java:11)
0

【注意】

1、代码中出现异常,JVM会终止代码运行,如果使用try catch捕获处理异常,JVM会认为当前代码中不存在异常,可以继续运行。

2、try - catch代码块中声明的都是局部变量,需要提前声明

3、try - catch捕获处理异常,可以处理多种异常情况

4、代码中存在多种隐患,存在多个异常情况,try - catch捕获有且只能处理第一个出现异常的代码,因为JVM从异常代码开始直接进入异常捕获阶段

5、Exception作为Java中所有异常的超类,在捕获异常处理时如果直接使用Exception进行捕获处理,无法具体到对某一个异常来处理

6、Exception可以作为try - catch 最后一个,用于处理其他异常捕获之后没有对症方式遗留问题

抛出

关键字:
    throw
        在方法内特定条件下抛出指定异常,后面跟异常类型的对象
        
    throws
        在【方法声明】位置,告知调用者,当前方法有哪些异常抛出,后面跟异常的类型

    用于处理非当前方法操作问题,导致出现的异常,一般情况下是用于处理方法运行过程中因为参数传入,参数处理,运算结果导致的问题,抛出异常。
    
    throw是一个稍微高级的参数合法性判断

案例代码

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

        try {
            test(1, 0);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试方法,打印两个数的差
     * 
     * @param num1 第一个参数,被除数
     * @param num2 第二个参数,除数
     * @throws ArithmeticException 如果除数为0,抛出异常
     */
    public static void test(int num1, int num2) throws ArithmeticException {

        if (0 == num2) {
            throw new ArithmeticException("除数不能为0");
        }

        System.out.println(num1 / num2);
    }
}

结果

java.lang.ArithmeticException: 除数不能为0
    at code.exception.TestThrows.test(TestThrows.java:23)
    at code.exception.TestThrows.main(TestThrows.java:7)

【注意】

1、throw 和 throws 必须同时出现,并且体现在注释上

2、代码如果运行到throw抛出异常,之后的代码不再运行,之后的代码是成为无法抵达的代码

3、代码中存在多种隐患,按照隐含的情况,分门别类处理,不能在同一个条件内抛出两个异常。并且在方法的声明位置,throws之后,不同的异常,使用逗号隔开

4、当调用带有异常抛出的方法时,对于方法抛出的异常,有两种处理方式,可以捕获处理,也可以抛出处理。

异常分类

运行时异常

RuntimeException:代码运行过程中出现的异常,没有强制处理的必要性,因为JVM会处理RuntimeException异常,即报错

其他异常

强制要求处理,不管是捕获处理还是抛出处理,都需要进行操作,如果未处理就会报错

自定义异常

继承自 Exception 或者 RuntimeException,只需要提供无参构造和一个带参构造即可

【注意】如果继承自Exception,调用抛出了此异常的方法需要手动对其捕获或者抛出

自定义异常类

public class MyException extends Exception {
    public MyException() {}
    
    public MyException(String message) {
        super(message);
    }
}

测试

public class Test {
    public static void main(String[] args) {
        try {
            buy(false);
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 买方法,当没有女朋友的时候,抛出异常
     * @param hasGirlFriend boolean类型,是否有女朋友
     * @throws MyException 自定义单身狗异常
     */
    public static void buy(boolean hasGirlFriend) throws MyException {
        if (false == hasGirlFriend) {
            throw new MyException("你还没有女朋友");
        }
        
        System.out.println("买一送一");
    }
}

结果

code.myexception.MyException: 你还没有女朋友
    at code.myexception.Test.buy(Test.java:19)
    at code.myexception.Test.main(Test.java:6)

注意

1、父类的方法有异常抛出,子类的重写方法在抛出异常的时候必须要小于等于父的异常

2、父类的方法没有异常抛出,子类的重写方法不能有异常抛出

3、父类的方法抛出多个异常,子类的重写方法必须比父少或者小

总结

1、异常的存在是非常有必要的,可以帮助我们定位和解决问题

2、异常的处理方式:捕获和抛出

3、自定义异常一定要有无参构造和有参构造

4、后期会遇到大量的异常,一般使用快捷键就能搞定

​ Eclipse:Ctrl + 1

​ Idea:Alt + Enter

File 类

文件和目录路径名的抽象表示形式,提供了对文件和文件夹的增删改查的方法

构造方法

File(String pathName);
    根据指定的文件路径,或者文件夹路径,创建对应的File类对象。路径可以是相对路径,可以是绝对路径
        
File(String parent, String childName);
    根据指定的父目录文件夹路径,和子文件或者子文件夹的名字,创建对应的File类对象
        
File(File parent, String childName);
    根据指定的父目录File类对象,和子文件或者子文件夹的名字,创建对应的File类对象

【注意】如果是文件必须要有后缀名,否则就是文件夹

案例代码

public class Test {
    public static void main(String[] args) {
        File file1 = new File("D:/aaa");
        File file2 = new File("D:/aaa", "1.txt");
        File file3 = new File(file1, "1.txt");
        
        System.out.println(file1);    // D:\aaa
        System.out.println(file2);    // D:\aaa\1.txt
        System.out.println(file3);    // D:\aaa\1.txt
    }
}

创建方法

boolean createNewFile();
    通过File类对象调用,创建File类对象中对应地址的普通文件,创建成功返回true,创建失败返回false;
    失败原因:
        1. 路径不合法,路径不存在,路径错误。
        2. 对应文件夹没有写入权限。
        3. 对应文件已存在。
        4. 磁盘坏道,电脑蓝屏。
       
boolean mkdir();
    通过File类对象创建,创建File类对象中对应的文件夹,创建成功返回true,失败返回false
    失败原因:
        1. 路径不合法,路径不存在,路径错误。
        2. 对应文件夹没有写入权限。
        3. 对应文件夹已存在。
        4. 磁盘坏道,电脑蓝屏。

boolean mkdirs();
    创建文件夹过程中可以完成中间路径

boolean renameTo(File dest);
    通过File类对象调用,转为目标dest指定File类对象,可以操作普通文件,可以操作文件夹。移动或者重命名

案例代码

public class Test {
    public static void main(String[] args) throws IOException {
        File file1 = new File("C:/Users/CJF/Desktop/啥啥啥.txt");

        boolean createNewFile = file1.createNewFile();
        System.out.println(createNewFile);

        File file2 = new File("C:/Users/CJF/Desktop/啥啥啥");
        boolean mkdir = file2.mkdir();
        System.out.println(mkdir);

        File file3 = new File("C:/Users/CJF/Desktop/啥啥啥/afaf/aggr/htedfgb/er");
        boolean mkdirs = file3.mkdirs();
        System.out.println(mkdirs);

        File file4 = new File("C:/Users/CJF/Desktop/什么鬼.txt");

        boolean renameTo = file1.renameTo(file4);
        System.out.println(renameTo);
    }
}

删除方法

boolean delete();
    通过File类对象调用,删除File类对象对应的文件或者文件夹。
    注意事项:
        1. 从磁盘中直接抹掉数据,不经过回收站,慎用
        2. 删除操作只针对于空文件夹操作,不能删除非空文件夹
    
void deleteOnExit();
    程序退出之后,删除调用该方法File类对象,对应的普通文件或者文件夹。
    用于缓冲文件,缓存问题,日志文件

案例代码

public class Test {
    public static void main(String[] args) throws IOException {
        File file = new File("C:/Users/CJF/Desktop/Test.txt");
        
        System.out.println(file.createNewFile());    // true
        
        System.out.println(file.delete());    // true
        
        file.deleteOnExit();
    }
}

获取方法

前三个方法和文件或者文件夹是否存在无关。
    
String getPath();
    获取File类对象中保存的路径
        
String getName();
    获取File类对象操作对应的文件名或者文件夹名

String getParent();
    获取File类对象操作文件或者文件夹的上级目录

String getAbsolutePath();
    获取当前File类对象对应路径的绝对路径

long length();
    获取当前【文件】的占用磁盘空间字节数
    根据不同的系统环境,文件夹调用length方法 0L 或者 4096L
long lastModified();
    获取当前文件夹上一次修改时间的【时间戳】
    是从计算机元年1970-01-01 00:00:00 到修改时间的秒数

案例代码

public class Test {
    public static void main(String[] args) {
        File file = new File("D:/aaa/bbb/ccc/1.txt");
        
        System.out.println(file.getPath());    // D:\aaa\bbb\ccc\1.txt
        System.out.println(file.getParent());    // D:\aaa\bbb\ccc
        System.out.println(file.getName());    // 1.txt

        System.out.println(file.length());    // 0
        
        System.out.println(file.lastModified());// 0
        
        System.out.println(new File(".").getAbsolutePath());    // D:\Qfeng\day27\.
    }
}

判断方法

boolean isFile();
    判断当前File类对象对应的是不是普通文件。
        
boolean isDirectory();
    判断当前File类对象对应的是不是文件夹。
        
boolean exists();
    判断当前File类对象对应的内容是否存在。
        
boolean isAbsolute();
    判断当前File类对象保存的路径是不是绝对路径。
        
boolean isHidden();
    判断当前File类对象对应的文件是不是一个隐藏文件。

案例代码

public class TestFileDecide {
    public static void main(String[] args) {
        File file = new File("D:/Adobe");
        
        System.out.println(file.exists());    // true
        System.out.println(file.isFile());    // false
        System.out.println(file.isDirectory());    // true
        System.out.println(file.isAbsolute());    // true
        System.out.println(file.isHidden());    // false
    }
}

列表方法

static File[] listRoots();    
    获取Windows操作系统下的所有盘符
    Linux中没有什么作用。

String[] list();
    获取File类对象对应文件夹中所有子文件或者子文件夹名字,String类型数组
    
File[]    listFiles();
    获取File类对象对应文件夹中所有子文件或者子文件夹的File类对象数组

案例代码

public class Test {
    public static void main(String[] args) {
        File file = new File("C:/Users/CJF/Desktop");

        String[] list = file.list();
        for (String fileName : list) {
            System.out.println(fileName);
        }

        File[] listFiles = file.listFiles();
        for (File file2 : listFiles) {
            System.out.println(file2);
        }

        File[] listRoots = File.listRoots();
        for (File file2 : listRoots) {
            System.out.print(file2 + "\t"); // C:\ D:\ E:\
        }
    }
}

FilenameFilter 文件名过滤器接口

实现此接口的类实例可用于过滤文件名。

boolean accept(File dir, String name);
    dir是当前操作获取文件列表的文件夹File类对象
    name是当前文件夹下的文件名或者文件夹名

案例代码

public class Test {
    public static void main(String[] args) {
        File file = new File("D:/EclipseWorkSpace/rx1901/src/com/fc/za/file");

        String[] fileNameArray = file.list(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
                return new File(dir, name).isFile() && name.endsWith(".java");
            }
        });

        for (String fileName : fileNameArray) {
            System.out.println(fileName);
        }
    }
}

扩展:匿名内部类格式

匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。它与内部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,那么你就可以使用匿名内部类

不使用匿名内部类

public class Demo7 {
    public static void main(String[] args) {
        File file = new File("D:/EclipseWorkSpace/rx1901/src/com/fc/za/file");

        // 传入一个接口的实现类
        String[] list = file.list(new JavaFilter());
        
        // 对结果进行增强for循环
        for (String string : list) {
            System.out.println(string);
        }
    }
}

// 此接口用于过滤指定的文件名,需要重写accept方法
class JavaFilter implements FilenameFilter {
    // 过滤以 .java 结尾的文件
    @Override
    public boolean accept(File dir, String name) {
        return new File(dir, name).isFile() && name.endsWith(".java");
    }
}

使用匿名内部类

public class Demo7 {
    public static void main(String[] args) {
        File file = new File("D:/EclipseWorkSpace/rx1901/src/com/fc/za/file");
        
        /*
         * 匿名内部类,常用于我们的参数传递,
         * 用来创建一个没有名字的类的对象
         * 
         * 写法:new 类名或者接口名() {}
         * 
         * 如果是接口,直接在{}里面实现方法的重写
         */
        String[] list2 = file.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return new File(dir, name).isFile() && name.endsWith(".java");
            }
        });
        
        for (String string : list2) {
            System.out.println(string);
        }
    }
}

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »