Java基础学习生疏知识点总结(16)——异常处理,文件和日期常用方法

本文总结了Java中的异常处理机制,包括异常与错误的区别、Throwable子类、异常处理原则及JVM异常处理。同时,详细介绍了File类的使用,如获取路径、文件操作、判断和获取功能等,并提及日期类的常用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、异常

1.1 异常与错误

异常: 程序运行时期出现了问题,出现了不正常的情况,称之为异常,并导致程序终止
编译出错: 在程序的编译时期不能通过编译器的语法检查,所以报错

1.2 Throwable的子类:

① Error: StackOverflowError是常见的Error,它表示栈空间已经不够用了,溢出了

  •  递归很危险,尽量不要使用
    
  •  对于Error而言,这个错误不应该由程序员自己去抛出,而是应该让jvm抛出
    

② Exception: 描述的程序运行期间的一般问题
       RuntimeException: 这种问题无法在编译时检查和预料,只有到程序运行后才能显现问题

  •  ArithmeticException: / by zero: 数学异常 算术异常 该异常是0作为了除数
    
  •  这个异常是最容易能够直接制造的运行时异常,这个异常会经常用于测试,测试代码的抗异常性能
    
  •  测试代码的健壮性
    

       非RuntimeException: 指的是在编译时期,就需要显式的检查并处理的异常,称之为编译时异常

  • Exception子类当中,除了RuntimeException和它的子类都属于编译时异常
    
  • 比如CloneNotSupportedException就是典型的编译时异常,需要在编译时期就处理这个异常,否者编译不通过
    

1.3 Java设计异常体系的原则

  • 尽量把一切错误,摒弃在程序运行之前,最好在编译时期就发现程序潜在的问题(通过编译器)
  • 确实,Java把相当一部分异常定义为编译时异常,让程序员在编译时期就显式的处理它们
  • 但仍然有很多问题,必须要Java程序运行起来,才可能产生,被发现,是编译器检查不到的
  • 这就是运行时异常
public class Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
       /* Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个整数: ");
        int i = sc.nextInt();
        System.out.println(10 / i);*/
        //System.out.println(0/0);

        Demo d = new Demo();
        //Unhandled exception: java.lang.CloneNotSupportedException
        d.clone();
    }
   /*
   没有递归出口的递归,会产生栈溢出错误
   public  static void test(){
        test();
    }*/
}

1.4 JVM异常处理机制

(1) java的代码产生异常,总是在一个方法当中产生异常,方法可以自己处理异常,也可以抛出异常给方法的调用者,最终异常会给到main方法程序的入口,如果main()方法还不解决,就只能抛给jvm,jvm只能自己解决。

(2)JVM是怎么解决异常的呢?
1,程序产生异常之前的代码 仍然正常执行
2,程序产生异常的代码会由jvm抛出一个异常,然后立刻从该行终止程序,后面的代码就不会执行了

  • 如果我们在程序中,不写任何和异常处理相关的代码,Java程序仍然能够对异常进行处理
    

(3) 如果错误产生在main方法中

  • 当我们的代码执行到错误行数之前,代码是正常执行的
    
  • 当我们的代码执行到错误行数时,JVM会终止程序的执行,抛出一个该异常信息封装成的对象
    

(4)将该对象中的异常信息,打印到控制台上,告诉程序员发生了什么问题
   这个异常的信息包括:

  •  异常对象的全限定类名,异常产生的原因,最重要的是发生异常的行数
    
  •  发生错误之后的语句,都不执行了
    
  • 如果错误产生在main方法当中的另一个方法中
    
  • 当程序执行到该方法的错误行数时,JVM会终止程序的执行
    
  • 向上给方法的调用者抛出一个该异常信息封装成的对象
    
  • 一直向上抛出,直到抛给main方法,main方法最终抛给JVM
    
  • 发生异常之前的语句正常执行,但是之后的语句都不执行了
    

(5) 总结:
java默认异常处理(不写任何有关异常处理的代码),会自动的往上抛出运行时异常(编译时异常由程序员手动处理决定怎么办), 直到抛给main方法,抛给jvm,然后jvm立刻终止程序执行,在控制台打印异常信息, 这种默认的异常处理会导致程序终止,往往不是我们希望的,所以我们还要手动去处理异常。

1.5 处理异常语法

  •  try...catch...finally
    
  •  try...catch...
    
  •  try...catch...catch...
    
  •  try...catch...catch...finally
    
  •  try...finally
    

1.6 自定义异常

1、怎么自定义异常?

  •  自定义编译时异常: 定义一个类,继承Exception,那么就是一个编译时异常
    
  •  自定义运行时异常: 定义一个类,继承RuntimeException,就是一个运行时异常
    

2、 怎么写自定义异常类的构造方法呢?

  •  直接去调用父类构造器就可以 super(参数)
    

3、自定义异常有啥用?

  • 在我们这个案例中,如果直接使用jdk已有的异常,比如IllegalArgumentException这个异常,看起来是可以实现效果的
  • 但是如果try当中的代码,本身也会产生这个异常IllegalArgumentException,那么就不能区分对待,不能分别处理了
  • 所以自定义异常可以区分自己写的代码的错误,不使用源码中已有的异常,避免混淆
  • 自定义异常其实比较少见,我们对异常的处理多数情况下还是以jdk中已有的为准
  • 一般公司中都有自己自定义的异常
  • 工具类
  • 异常
public class Demo {
    public static void main(String[] args) {
        try {
            judgeObjectNumRun(-1);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            System.out.println("对象数量应该是0和1");
        }
        try {
            judgeObjectNum(3);
        } catch (ObjectNumException e) {
            e.printStackTrace();
            System.out.println("对象数量应该是0和1");
        }
    }
        //这个方法用来判断数量,如果数量不是0和1,那就有问题,有问题就要抛出异常
    public static void judgeObjectNumRun(int num) {
        if (num > 1) {
            throw new IllegalArgumentException("你是海王");
        }
        else if (num < 0 ){
            throw  new IllegalArgumentException("不能小于0");
        }else {
            System.out.println("你是个正常人!");
        }
    }

    public static void judgeObjectNum(int num) throws ObjectNumException {
        if (num > 1) {
            throw new ObjectNumException("你是海王");
        }
        else if (num < 0 ){
            throw  new ObjectNumException("不能小于0");
        }else {
            System.out.println("你是个正常人!");
        }
    }

}

class ObjectNumException extends Exception { //编译时异常
    public ObjectNumException() {
        super();
    }

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

class ObjectNumRuntimeException extends RuntimeException { //运行时时异常
    public ObjectNumRuntimeException() {
        super();
    }

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

2 File

2.1 System.getProperty(“user.dir”) 这个方法可以用来获取当前IDEA的相对路径

File类的构造方法:

/**
 * @description: File类的构造方法
 **/

public class Demo {
    public static void main(String[] args) {
        创建一个File对象,该方法一般使用绝对路径来创建对象,也可以使用相对路径
        //File (String pathname)
        //E:\\2\\a.txt
        //用绝对路径创建对象
        File f = new File("E:\\2\\a.txt");
        System.out.println(f.exists());
        //用相对路径创建对象
        System.out.println(System.getProperty("user.dir"));
        File f1 = new File("2.txt");
        System.out.println(f1.exists());

        和第一种方式类似,只不过把一个路径劈成了两半
        普遍来说,parent路径表示一个绝对路径。child路径跟一个相对路径
        //File (String parent, Sting child)
        //E:\idea_space\31th\12_file\1.txt
        File f3 = new File("E:\\idea_space\\31th\\12_file\\", "1.txt");
        System.out.println(f3.exists());

        //和第二种方式一样,只不过,子路径用一个File对象表示
        //File (File parent, String child)
        File tempFile = new File("E:\\idea_space\\31th\\12_file\\");
        File f4 = new File(tempFile, "1.txt");
        System.out.println(f4.exists());
    }
}

2.2 常用API

2.2.1分隔符

/**
 * //与系统有关的多个路径名的分隔符 “;”
 * static String pathSeparator
 * //与系统有关的单个路径层级的分隔符 “\”
 * static String separator
 *
 */
public class Demo {
    public static void main(String[] args) {
        System.out.println(File.pathSeparator);
        System.out.println(File.separator);
    }
}

2.2.2 文件创建

/**
 * 总结:
 *  不能通过是否有后缀名判断是否是文件或者文件夹
 *  具体怎么判断,后面学习
 *
 */
public class Demo {
    public static void main(String[] args){
        只负责创建文件,目录路径如果不存在,会报错而不是帮你创建
        //这个方法如果创建成功就返回true,如果文件已存在返回false
        //如果创建的文件的目录不存在,该方法会抛出异常,警告你路径不存在,程序终止
        //该方法不能帮你创建目录,必须要求创建文件的目录是存在的

        //如果这个方法创建的文件没有后缀名,那它会创建出文件夹吗?
        //那它仍然创建出文件,只不过这个文件没有后缀名
        //public boolean createNewFile()
       /* File f1 = new File("E:\\aaaaa");
        //Unhandled exception: java.io.IOException
        System.out.println(f1.createNewFile());*/


        //只负责创建目录,但只能创建单层目录,如果有多级目录不存在的话,创建失败
        //public boolean mkdir()
        //File f = new File("asdasdhasidhasd121321\\123123123\\adkjash");
        File f = new File("3.txt");
        //System.out.println(f.mkdir());

        //只负责创建目录,但可以创建多级目录,如果多级目录不存在,则帮你全部创建
        //和上一个方法一模一样 区别在于可以创建多级目录
        //以后开发中如果有创建文件夹的需求,不管创建的是什么目录,都用这个方法
        //public boolean mkdirs()
        System.out.println(f.mkdirs());
        //该方法只能创建文件夹,即便是写了后缀名,也仍然是一个文件夹
    }
}

2.2.3 删除文件

public class Demo {
    public static void main(String[] args) {
        //public boolean delete()
        //该方法是File当中的删除功能,该功能只能删除文件和一个空的文件夹
        //如果文件夹中有别的文件或者文件夹,是删除不成功的
        //这个删除文件是直接调用系统的API 不会删到回收站 而是直接干掉了
        //友好提示: 慎用
        File f = new File("1");
        System.out.println(f.delete());
    }
}

2.2.4 文件移动与重命名

public class Demo {
    public static void main(String[] args) {
        //public boolean renameTo(File dest)
        //把调用方法的File源文件,移到参数的dest文件对象那
        //- 当源文件和修改之后的目标文件,在同一目录的时候,效果只是重命名
        //- 当源文件和修改之后的目标文件,不在同一目录的时候,效果是移动且重命名
        //- 当源文件和修改之后的目标文件,同目录同名时,方法返回true,实际没有效果
        //- 真正操作文件,应该使用(IO流操作)
        File f = new File("E:\\test.jpg");
        File f2 = new File("E:\\test.jpg");
        System.out.println(f.renameTo(f2));
    }
}

2.2.5 File的判断功能

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

       /* //这两个判断是否是文件和文件夹的方法,如果目录或文件不存在,返回false
        判断File对象是否表示的是一个文件
        //public boolean isFile()
        File f = new File("E:\\2\\aaa");
        System.out.println(f.isFile());
        判断File对象是否表示的是一个目录
        //public boolean isDirectory()
        File f2 = new File("E:\\2\\1.txt");
        System.out.println(f2.isDirectory());*/


        判断File对象表示的文件或目录,是否真实存在
        //public boolean exists()
        File f = new File("E:\\2\\aaa");
        System.out.println(f.exists());

        //以下三个方法,在Windows操作系统下,意义不大,PC往往都拥有很大的权限,一般都没有权限问题
        //这些方法往往放在服务器中去使用
        //服务器是分权限分用户使用的
        //teacher/student最高的root权限
        //测试/开发 运维

        //判断File对象表示的文件,是否可读
        //public boolean canRead()
        判断File对象表示的文件,是否可写
        //public boolean canWrite()
        判断File对象表示的文件是否是隐藏文件
        //public boolean isHidden()
    }
}

2.2.6 File的获取功能

public class Demo {
    public static void main(String[] args) {
        //获取File对象表示的抽象文件的绝对路径
        //public String getAbsolutePath()
        File f = new File("1");
        String absolutePath = f.getAbsolutePath();
        System.out.println(absolutePath);
        //public File getAbsoluteFile() 获取该file的抽象路径的绝对路径表示的对象
        File absoluteFile = f.getAbsoluteFile();
        System.out.println(absoluteFile);

        //File的toString()方法已经重写了
        // public String toString() {
        //     return getPath();
        // }


        获取File对象表示的抽象路径名的字符串,简单来说,创建的时候给的是什么就输出什么
        //public String getPath()
        System.out.println(f.getPath());
        System.out.println(f);

        //获取File对象表示的文件或者目录的文件名
        //public String getName()
        System.out.println(f.getName());
        File f2 = new File("E:\\111");
        System.out.println(f2.getName());


        返回由此抽象路径名表示的文件的所占硬盘空间大小,以字节为单位
        但是需要注意的是,这个方法只能获取文件的大小,不能获取目录大小
        //public long length()
        File f3 = new File("E:\\2\\学习资料.mp4");
        System.out.println(f3.length());
        File f4 = new File("E:\\2"); //4096的整数倍
        System.out.println(f4.length());

        返回此File对象表示的文件的最后一次修改的时间
        //public long lastModified()
        //1606289729000 时间戳 指的是从格林威治时间1970 /1/1 0点0时0分开始到现在时间的毫秒数
        System.out.println(f3.lastModified());

    }
}

2.2.7 File的高级获取功能

/**
 * //返回一个字符串数组,这些字符串包括,此抽象的路径名表示的目录中的所有文件和文件夹的名字
 * //如果File对象表示的是一个文件,则返回null
 * //只能获取当前目录的下一层,并不是获取所有层级
 * //如果是一个空目录,返回一个长度为0的数组,而不是null
 * public String[] list()
 *
 * 这个方法实际上获取的是目录下的文件名,但实际上来说,要文件名不如直接要一个对象
 * 所以Java也提供了这个方法listFiles() 该方法的返回值是一个File对象数组
 *
 */
public class Demo2 {
    public static void main(String[] args) {
        //1,如果该File对象是一个目录并且不是一个空目录 会得到一个String数组 该数组里放的是文件/文件夹的名字
        File f = new File("E:\\2");
        String[] list = f.list();
        for (String s : list) {
            System.out.println(s);
        }
        //2,如果File对象是一个空目录,那么仍然也会得到一个String数组,但是是一个长度为0的数组 空的数组
        File f2 = new File("E:\\2\\a");
        String[] list1 = f2.list();
       /* for (String s : list1) {
            System.out.println(s);
        }*/
        System.out.println(Arrays.toString(list1));

        //3,如果该File对象表示的文件是一个文件 那么会得到null
        //根据这一特点,这个方法勉强也能用来区分文件和文件夹
        File f3 = new File("E:\\2\\aaa");
        String[] list2 = f3.list();
        System.out.println(list2);

        //4,如果没有File对象表示的文件
        File f4 = new File("E:\\2\\aasdasdaa");
        String[] list3 = f4.list();
        System.out.println(list3);
        //这个方法不会抛出异常
    }
}

2.2.8 listFiles()获取目录下所有的文件的对象

/**
 * //返回指定File目录下的文件和文件夹的绝对路径形式的File对象数组
 * //如果File对象表示的是一个文件,则返回null
 * //只能获取当前目录的下一层,并不是获取所有层级
 * //如果是一个空目录,返回一个长度为0的数组,而不是null
 * public File[] listFiles()
 * 该方法是在list()方法的基础上得到的一个方法
 * 它的一些基本特点和list()方法一样,不过这个方法得到的是File对象
 */
public class Demo3 {
    public static void main(String[] args) {
        File f = new File("E:\\2");
        File[] files = f.listFiles();
        //for (File file : files) {
        //    //listFiles方法得到的是File的绝对路径形式的表示
        //    System.out.println(file);
        //}
        //遍历这个File数组
        for (int i = 0; i < files.length; i++) {
            System.out.println(files[i].getPath());
        }
    }
}

2.2.9 带筛选功能的获取File文件的listFiles()方法

/**
 * 带筛选功能的获取File文件的listFiles()方法
 * public File[] listFiles(FileFilter filter)
 * 该方法需要传入FileFilter接口的实现类对象,可以类比带比较规则的自然排序sort(数组,Comparator)方法
 * FileFilter是一个接口,它是一个功能接口,它里面只有一个需要实现的抽象方法:
 *      boolean accept(File pathname)
 *
 */
public class Demo4 {
    public static void main(String[] args) {
        /*File f = new File("E:\\2");
        //FileFilter filter = null;
        MyFileFilter filter = new MyFileFilter();
        File[] files = f.listFiles(filter);
        *//*for (File file : files) {
            System.out.println(file);
        }*//*
        System.out.println(Arrays.toString(files));*/

        //使用实现类对象去实现这个筛选器
        /*File f = new File("E:\\2");
        File[] files = f.listFiles(new MyFileFilter());
        System.out.println(Arrays.toString(files));*/

        //使用匿名内部类
        /*File f = new File("E:\\2");
        File[] files = f.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                String fileName = pathname.getName();
                return pathname.isFile() && fileName.endsWith(".mp4");
            }
        });
        System.out.println(Arrays.toString(files));*/

        //使用lambda表达式
        File f = new File("E:\\2");
        //规则: 想听歌-听beyond的歌
        File[] files = f.listFiles(Demo4::beyondSong);
        System.out.println(Arrays.toString(files));

        f.listFiles(file2 -> {
           String fileName =  file2.getName();
           return true;
        });

        //规则: 只看文件
        File[] files1 = f.listFiles(File::isFile);
        System.out.println(Arrays.toString(files1));
    }

    private static boolean beyondSong(File file) {
        String fileName = file.getName();
        boolean beyond = fileName.startsWith("Beyond");
        boolean file1 = file.isFile();
        return file1 && beyond;
    }
}
//1,手写一个实现类 实现该接口FileFilter
class MyFileFilter implements FileFilter{
    @Override
    public boolean accept(File pathname) {
        //规则: 我希望能够看学习资料
        //1,文件对象表示的必须是一个文件
        //2,文件名的后缀是.mp4
        //return false;
        boolean file = pathname.isFile();
        //获取文件的名字
        String fileName = pathname.getName();
        boolean b = fileName.endsWith(".mp4");
        return file && b;
    }
}

3、日期类

3.1 常用方法(1)

/**
 * @Deprecated:不推荐使用的 已过时的方法
 * 这些方法往往都已经被新的方法替代了 但是这些方法没有被删除
 * Date类表示一个特定的瞬间时间,精确到毫秒
 * Date的构造方法,现在还没有过时的,只有两个了
 * //该构造函数使用当前日期和时间来初始化对象
 * Date()
 * //第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数
 * Date(long millisec)
 *
 * System.currentTimeMillis(): 该方法是一个本地方法,它是根据操作系统的API去获取当前时间的时间戳
 * 时间戳:是从1970年01/01 0点0时0分格林威治时间到现在的时间的毫秒数
 * 格林威治: 英国的小镇 它是经线的起始点 还是世界时的起始点 本初子午线 0时区 东八区
 *
 *
 *
 *
 */
public class Demo {
    public static void main(String[] args) {
        Date d = new Date();
        //Thu Apr 15 16:19:31 CST 2021 星期四,四月,15, CST China Standard Time 中国标准时间 北京时间
        System.out.println(d);
        //介绍两个成员方法
        //用自1970年1月1日00:00:00 GMT以后time毫秒数设置时间和日期。
        //void setTime(long time)
        返回自1970年1月1日00:00:00 GMT以来此Date对象表示的毫秒数。
        //long getTime( )
        System.out.println(d.getTime());
        d.setTime(3742762088000L);
        System.out.println(d);

        Date d2 = new Date(3742762088000L);
        System.out.println(d2);

        //1,算现在到1970年多少年了
        Date d3 = new Date();
        long time = d3.getTime();
        //Numeric overflow in expression
        System.out.println(time / (1000L * 3600 * 24 * 365));

        //2,如果setTime(0)
        d3.setTime(0);
        System.out.println(d3);


    }
}

3.2 常用方法(2)

/**
 * 首先日期的格式类只是表示日期的格式 它不是真正的表示时间
 * 2020/01/01 00:00:00
 * 真正的表示时间还是要靠Date类
 *
 * DateFormat是一个抽象类,我们真正去使用的是SimpleDateFormat这个类
 * 首先要创建日期的格式,给出一套匹配的格式
 * //以传入的字符串格式进行解析或者格式化日期
 * public SimpleDateFormat(String pattern)
 * 匹配的模式怎么写:
 * - y:表示年,例如yyyy,表示千年年份
 * - M:表示月份,例如MM,表示月份(最多12,两位数)
 * - d:表示月份中的天数,例如dd,表示天数(最多31,两位数)
 * - H:表示一天中的小时数,例如HH,表示小时数(最多24,两位数)
 * - m:表示小时中的分钟数,例如mm,表示分钟数(最大59,两位数)
 * - s:表示分钟里的秒数,例如ss,表示秒数(最大59,两位数)
 *
 * 这个类的对象是用来
 *      1,Date对象表示成匹配模式的时间字符串 专有名词叫格式化 format()
 *      2,直接用匹配成功的字符串转换成Date对象 专有名词叫解析 parse()
 *
 *
 *
 */
public class Demo2 {
    public static void main(String[] args) throws ParseException {
        //我希望的匹配模式: 2020/01/01 00:00:00
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        //1,格式化
        Date d = new Date(3742762088000L);
        String timeStr = sdf.format(d);
        System.out.println(timeStr);

        //2,解析
        String time = "2077/07/07 07:07:07";
        //Unhandled exception: java.text.ParseException
        //ParseException是一个编译时异常,当你写的字符串和给的匹配模式 不匹配时,就会报这个错误
        Date parse = sdf.parse(time);
        System.out.println(parse.getTime());

    }
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值