Java学习笔记——Java语言基础(十七)(异常、File文件类)

一、异常

在学习IO流之前,我们需要先了解异常和File文件类。File表示的是IO流将来要进行操作的文件,常见的操作是上传和下载,操作过程中可以会出现一些问题,需要处理问题,所以需要学习异常

1.1 异常的概述以及分类

异常:指的是程序在执行过程中,出现的非正常情况,最终会导致JVM的非正常停止
在Java这种面向对象的编程语言中,异常本身就是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式为终端处理

1.2 异常体系

异常机制其实是帮助我们找到程序中存在的问题,异常的根类是Throwable,下面有两个子类:Error和Exception。
Error:严重错误,无法处理的错误也不予处理,只能事先避免。
Exception:表示异常,异常产生后可以通过代码的方式纠正,使得程序继续运行。

1.3 JVM默认处理异常

main方式收到这个问题时,有两种处理方式
1.main方法自己处理该问题,然后继续运行
2.自己没有处理方式,交给调用main方法的JVM进行处理。JVM默认的处理将异常的名称、信息、出现的位置打印在了控制台,并且同时停止程序的运行。

1.4 Throwable的常用方法
public void printStackTrace() ://打印异常的详细信息。

包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。

public String getMessage() ://获取发生异常的原因。

提示给用户的时候,就提示错误原因。

public String toString() ://获取异常的类型和异常描述信息(不用)
1.5 异常的分类
  • 编译时期异常:checked异常。在编译时期,就会检查。如果没有处理异常,则编译失败(日期格式化异常)
  • 运行时期异常:runtime异常。在运行时期,检查异常。在编译时期,运行异常不会编译器检测(不报错)(数学异常)
public class Test01 {
    public static void main(String[] args) throws ParseException {
        //编译器异常:日期格式化异常
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        //编译器异常,必须处理,抛出异常 处理:main方法抛出ParseException
        Date parse = simpleDateFormat.parse("2012-12-22");
        System.out.println(parse);
        //运行期异常         数学异常 打印ArithmeticException: / by zero 除数为0异常
        int a=1;
        int b=0;
        System.out.println(a/b);
    }
}
public class Test02 {
    public static void main(String[] args) {
        int[] arr={10,20,30};
        int element = getElement(arr, 4);
        System.out.println(element);
    }

    private static int getElement(int[] arr,int index) {
        return arr[index];
    }
}

对Test02程序的执行过程进行分析
在getElement方法中,由于没有找到参数的索引,导致程序运行时发生了异常,这个异常JVM认识。Java中对于这种异常有具体的描述,其内容包括:异常的名称、内容以及产生的位置。Java将这些信息直接封装到ArrayIndexOutOfBoundsException异常的一个对象中。
JVM将异常抛出给方法的调用者main方法中。main方法接受这个异常对象,由于main方法没有处理这个异常,main方法就会将这个异常抛出给调用者JVM,当JVM收到异常是,就会将异常的内容打印在控制台,同时停止程序的运行。

1.6 异常的处理

如果异常出现的话,会终止程序的运行,所以必须处理异常

1.6.1 捕获异常

捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理

(1) try…catch

try…catch的方式就是捕获异常。
try{
编写可能会出现异常的代码
}catch(异常类型 e){
处理异常的代码
}
注意:

  • try和catch都不能单独使用,必须一起使用
  • try中的代码越少越好
  • catch中要做处理,哪怕是一条输出语句也可以.(不能将异常信息隐藏)
    使用演示:
public class Test03 {
    public static void main(String[] args) {
        int a=1;
        int b=0;
        try {
            //可能出现问题的代码
            System.out.println(a/b);
        }catch (ArithmeticException e ){//异常名和对象
            //处理语句
            System.out.println("除数为0");
        }
    }
}

这样捕获到异常之后,程序会执行catch中的代码,不会在控制台打印异常信息

(2) finally代码块

finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为有些异常会引发程序发生跳转,导致有一些语句不能被执行到。而finally就是解决这个问题,finally中存放的代码都是一定会执行的。一般用于释放资源
注意:在执行finally之前,如果JVM退出则finally语句执行不到(System.exit(0))

public class FinallyDemo {
    public static void main(String[] args) {
        List<Integer> list=new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        try {
            Integer integer = list.get(3);
            System.out.println(integer);
        }catch (IndexOutOfBoundsException e){
            System.out.println("出现异常情况");
        }finally {
            System.out.println("finally代码执行了");
        }
        //finally代码不执行
        try {
            int[] arr={1,2,3};
            System.out.println(arr[3]);
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("出现异常情况2");
            //停止JVM finally代码执行不能够执行
            System.exit(0);
        }finally {
            System.out.println("finally代码执行了");
        }
    }
}

运行结果
在这里插入图片描述

1.6.2 抛出异常throw

在编写程序时,必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方
法使用接受到的参数时,需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的
数据进来。这时需要使用抛出异常的方式来告诉调用者。
Java中就提供了throw关键字,用来抛出一个指定的异常对象,封装一些提示信息
使用格式:throw new 异常类名(参数);
代码演示:

public class ThrowDemo {
    public static void main(String[] args) {
       /* int[] arr2={1,2,3,4,5};
        int element1 = getElement(arr2, 10);
        //Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 传递的索引越界
        System.out.println(element1);*/
        int[] arr=null;
        int element = getElement(arr, 2);
        //Exception in thread "main" java.lang.NullPointerException: 传递的数组为空数组
        System.out.println(element);
    }
    public static int getElement (int[] arr,int index){
        //运行期异常
        if (arr==null){
            throw new NullPointerException("传递的数组为空数组");
        }
        if (index<0||index>arr.length-1){
        //判断条件如果满足,当执行完throw抛出异常对象后,方法已经无法继续进行,就会结束当前方法,将异常告知调用者。
            throw new ArrayIndexOutOfBoundsException("传递的索引越界");
        }
        int i = arr[index];
        return i;
    }
}

对于调用者来说处理异常有两种方式,一种是进行捕获处理,另一种就是继续讲异常声明处理,使用throws声明处理

1.6.3 声明异常throws

声明异常:将问题标识出来,告知调用者,如果方法内通过throw抛出了编译时异常,而没有进行捕获处理,那么必须通过throws进行声明,让调用者进行处理
关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).
格式:修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ }
代码:

public class ThrowDemo {
    public static void main(String[] args)throws NullPointerException,ArrayIndexOutOfBoundsException {
       /* int[] arr2={1,2,3,4,5};
        int element1 = getElement(arr2, 10);
        //Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 传递的索引越界
        System.out.println(element1);*/
        int[] arr=null;
        int element = getElement(arr, 2);
        //Exception in thread "main" java.lang.NullPointerException: 传递的数组为空数组
        System.out.println(element);
    }
    public static int getElement (int[] arr,int index)throws NullPointerException{
        //运行期异常
        if (arr==null){
            throw new NullPointerException("传递的数组为空数组");
        }
        if (index<0||index>arr.length-1){
            throw new ArrayIndexOutOfBoundsException("传递的索引越界");
        }
        int i = arr[index];
        return i;
    }
}

main声明的异常由于没有进行处理,将异常抛给调用者JVM,JVM使用默认的处理异常方式进行处理
throws用于进行异常类的声明,若方法可能会 出现多个异常,那么throws后面可以写多个异常类,用,隔开

1.6.4 抛出异常throw与声明异常throws的区别
throw:用在方法体内,跟的是异常类的一个对象(只能抛出一个对象名)
			异常可以为编译期,也可以为运行期
			表示抛出异常,由方法体内的语句处理
			throw是抛出了异常,执行throw则一定抛出了某种异常
throws:用在方法声明的后面,跟的是异常类名
			  可以跟多个异常类名,中间使用逗号隔开
			  表示声明异常,有方法的调用者来处理
			  throws表示出现异常的可能性,并不一定会发生该异常
1.7 自定义异常

在开发过程中根据自己的需求来定义一个异常类,可以定义编译期异常,也可以是运行期异常。
自定义编译期异常,继承Exception。
自定义运行期异常,继承RuntimeException
自定义一个异常类RegisterException,用来进行用户的注册
RegisterException类:

public class RegisterException extends Exception {
    public RegisterException(){
        super();
    }
    //添加一个带异常信息的构造方法
    public RegisterException(String s){
        super(s);
    }
}

测试类,用来测试用户名是否被注册

public class RegisterExceptionDemo2 {
    static String[] usernames={"张三","李四","王五"};

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入注册的用户名信息:");
        String username = scanner.nextLine();
        cheakUserName(username);

    }
    public static void cheakUserName(String username)  {
        for (String name : usernames) {
            if (name.equals(username)){
                try {
                //throw抛出一个自定义异常
                    throw new RegisterException("该用户已经被注册");
                } catch (RegisterException e) {
                    e.printStackTrace();
                    return;//结束方法
                }
            }
        }
        System.out.println("恭喜注册成功");
    }
}

测试结果
(1)用户已被注册
在这里插入图片描述
(2)用户注册成功
在这里插入图片描述

1.8 异常的注意事项
	a:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类,或者子类不抛出异常也是可以的。
	b:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常,或者子类不抛出异常也是可以的。
	c:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws
class Fu{
    public static void show01()throws NullPointerException,ClassCastException{};
    public static void show02()throws IndexOutOfBoundsException{};
    public static void show03()throws NullPointerException,ClassCastException{};
    public static void show04(){};
}
class Zi extends Fu{
    //子类重写父类方法。抛出父类相同的异常
    public static void show01()throws NullPointerException,ClassCastException{};
    //子类重写父类方法,抛出父类异常的子类
    public static void show02()throws ArrayIndexOutOfBoundsException{};
    //子类重写父类方法,不抛出异常
    public static void show03(){};
    //父类不抛出异常,子类重写也不抛出异常
    //有异常发生,只能try,不能throws
    public static void show04(){
        try {
            throw new Exception("子类异常");
        } catch (Exception e) {
            e.printStackTrace();
        }
    };

}

二、File文件类

Java把电脑中的文件和文件夹(目录)封装为一个File类,使用File类对于文件和文件夹进行操作(创建 删除 获取 判断 遍历文件夹 文件的大小)File类是文件和目录路径名的抽象表示,主要用于文件和目录的创建

2.1 构造方法

public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File实例。
public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File实例。

public class FileMethod01 {
    public static void main(String[] args) {
        // public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
        File file = new File("a.txt");
        System.out.println(file);//a.txt
        /*public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File实例。
        路径分为父路径和子路径*/
        String parent="D:\\IDEAlei\\File";
        String child="c.txt";
        File file1 = new File(parent, child);
        System.out.println(file1);//D:\IDEAlei\File\c.txt
        /*public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File实例。
        File:父路径 String:子路径*/
        File file3=new File("C:\\IDEAlei\\File");
        File file4=new File(file3,"d.txt");//File:父路径 String:子路径
        System.out.println(file4);//
    }
}
2.2 常用方法
2.2.1 获取功能的方法

public String getAbsolutePath() :返回此File的绝对路径名字符串。
public String getPath() :将此File转换为路径名字符串。
public String getName() :返回由此File表示的文件或目录的名称。
public long length() :返回由此File表示的文件的长度。

public class Method01 {
    public static void main(String[] args) {
        File file1=new File("D:\\IDEAlei\\File\\a.txt");
        System.out.println("绝对路径"+file1.getAbsolutePath());//绝对路径D:\IDEAlei\File\a.txt
        System.out.println("相对路径"+file1.getPath());//相对路径D:\IDEAlei\File\a.txt
        System.out.println("文件名称"+file1.getName());//文件名称a.txt
        System.out.println("文件长度:"+file1.length()+"字节");//文件长度:0字节//File表示的文件的长度。
        //toString()相当于getPath()
        System.out.println(file1.toString());//D:\IDEAlei\File\a.txt
        File file2=new File("b.txt");
        System.out.println("绝对路径"+file2.getAbsolutePath());//绝对路径C:\Users\asus\IdeaProjects\MyTest\b.txt
        System.out.println("相对路径"+file2.getPath());//相对路径b.txt
        System.out.println("文件名称"+file2.getName());//文件名称b.txt
        System.out.println("文件长度:"+file2.length()+"字节");//文件长度:3字节

        File file=new File("D:\\james\\james.png");
        System.out.println(file.length());//292098
        File file3=new File("D:\\james");
        //文件夹是没有大小的,当文件不存在时也同样返回0
        System.out.println(file3.length());//0
        File file4=new File("D:\\sdes");
        System.out.println(file4.length());//0
    }
}

绝对路径:从盘符开始的路径,是一个完整的路径、比如:D:\james\james.png
相对路径:相对于项目目录的路径,这是一个便捷的路径
**注意:**在创建文件或者文件夹时忘记写盘符路径,那么默认路径为项目目录的路径

2.2.2 判断功能的方法

public boolean exists() :此File表示的文件或目录是否实际存在。
public boolean isDirectory() :此File表示的是否为目录。
public boolean isFile() :此File表示的是否为文件。

public class FileMethod02 {
    public static void main(String[] args) {
         /*
         public boolean exists() :此File表示的文件或目录是否实际存在。
         public boolean isDirectory() :此File表示的是否为目录。
        public boolean isFile() :此File表示的是否为文件。
        电脑中只存在文件夹(目录)和文件
         两个方法的前提是路径存在,如果不存在,返回false
         */
        //存在的一个目录
        File file=new File("D:\\IDEAlei\\File");
        System.out.println(file.exists());//true
        System.out.println(file.isDirectory());//true
        System.out.println(file.isFile());//false
        //不存在的一个目录
        File file1=new File("C:\\IDEAlei\\File");
        System.out.println(file1.exists());//false
        System.out.println(file1.isDirectory());//false
        System.out.println(file1.isFile());//false
        //存在的一个文件
        File file4=new File("D:\\IDEAlei\\File\\a.txt");
        System.out.println(file4.isDirectory());//false
        System.out.println(file4.isFile());//true
    }
}
2.2.3 删除功能的方法

public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
public boolean delete() :删除由此File表示的文件或目录。
public boolean mkdir() :创建由此File表示的目录。
public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。

public class FileMethod03 {
    public static void main(String[] args) throws IOException {
        /*
        public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
        文件存在,返回false 文件不存在:返回true 创建一个空的文件
        只能创建文件,不能创建文件夹
        创建文件时路径必须存在,否则抛出异常
        createNewFile()抛出IOException throws或者try...catch
         */
        File file=new File("D:\\IDEAlei\\File\\c.txt");
        boolean newFile = file.createNewFile();
        System.out.println(newFile);
        /*
        public boolean mkdir() :创建由此File表示的目录。   创建单级文件夹
        public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。 创建单级文件夹 多级文件夹同文件
        */
        File file2=new File("D:\\IDEAlei\\File\\aaa");
        boolean mkdir = file2.mkdir();//单级文件夹
        System.out.println(mkdir);
        File file3=new File("D:\\IDEAlei\\File\\111\\222\\333");
        boolean mkdirs = file3.mkdirs();多级文件夹
        System.out.println(mkdirs);
        File file4=new File("D:\\IDEAlei\\File\\abc.txt");//创建的是一个名称为abc.txt的文件夹
        boolean mkdir1 = file4.mkdir();
        System.out.println(mkdir1);
        /*
        public boolean delete() :删除由此File表示的文件或目录。
        true :删除成功 false:文件夹内有内容,不会删除返回false 或者构造方法中的路径不存在
        注意: delete方法直接在硬盘中删除文件或者文件夹  不走回收站
         */
        boolean b = file2.delete();
        System.out.println(b);
        boolean b1 = file4.delete();
        System.out.println(b1);
    }
}
2.2.4 重命名的方法

public boolean renameTo(File dest):把文件重命名为指定的文件路径

public class FileDemo02 {
    public static void main(String[] args) {
        File file = new File("aaa.txt");
        File file1 = new File("bbb.txt");
        boolean b = file.renameTo(file1);
        if (b) {
            System.out.println("重命名成功");
        }else {
            System.out.println("重命名失败");
        }
    }
}

注意:当调用方法的文件路径和传入的参数的文件的路径名相同,则为重命名。否则为剪切+重命名

2.2.5 目录的遍历

public String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录。
public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录。

练习:删除多级文件夹

public class MyTest0101 {
    public static void main(String[] args) {
        File file = new File("C:\\Users\\asus\\Desktop\\aaa");
        file.mkdirs();
        deleteFile1(file);
    }

    private static void deleteFile1(File file) {
        //遍历得到文件目录下的所有文件 listFiles() 方法
        File[] files = file.listFiles();
        for (File file1 : files) {
            //判断是否是目录,如果是,则递归
            if (file1.isDirectory()){
                deleteFile1(file1);
            }else {
                file1.delete();
            }
        }
        file.delete();
    }
}

练习:修改多级文件夹的后缀名

public class Test02 {
    public static void main(String[] args) {
        /*
        练习:将文件名后缀修改为.PNG
         */
        //绑定一个文件夹
        File file = new File("C:\\Users\\asus\\Desktop\\music");
        //构造一个修改的方法updataFileName
        updataFileName(file);
    }

    private static void updataFileName(File file) {
        //遍历得到文件目录下的所有文件
        File[] files = file.listFiles();
        for (File file1 : files) {
            //对遍历的文件进行判断,是文件则进行修改操作
            if (file1.isFile()){
                //获取文件的绝对路径
                String name = file1.getAbsolutePath();
                //修改文件的绝对路径名
                String newName=name.substring(0,name.lastIndexOf("."))+".PNG";
                //使用新的文件名构造一个文件
                File endFile = new File(newName);
                //对文件进行重命名
                file1.renameTo(endFile);
            }else {
                //是文件夹的话,对文件夹调用updataFileName
                updataFileName(file1);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值