Day19 --异常 File类

来源:互联网 发布:陕西广电网络是国企嘛 编辑:程序博客网 时间:2024/06/05 08:55
 a.
    异常
        概述
            * 异常就是程序运行过程中可能出现的错误
            * 通过API查看Throwable可知,异常处于lang包下,直接子类是Error和Exception
            * 其实异常就是java通过面向对象的思想将问题封装成对象,用异常类对其进行描述,不同的问题有不同类进行具体的描述,如:角标越界异常,空指针异常等。问题多,意味着描述的类也就越多,所以将其共性不断的向上抽取,进而形成了异常体系结构。
        分类
            * throwable无论error还是异常问题。问题发生就应该抛出,让调用者处理,该体系结构的特点在于:Throwable及其所有的子类对象都具有可抛性。
                * 可抛性?
                    * 通过两个关键字 throw 和 throws 来说实现。 凡是可以通过这两个关键字所操作的类和对象都具有可抛性。
                    
            * Exception --可解决的异常问题
                * ClassCastException 类型转换异常
                * NullPointerException 空指针异常  
                * ConcurrentModificationException 并发修改异常
                * IndexOutOfBoundsException 角标(索引)越界异常
                * ParseException  解析异常
                * UnsupportedOperationException 当不支持请求的操作时,抛出该异常
                * NumberFormatException 数字格式异常
                * 。。。
            * Error    --无法避免的错误
                * 服务器宕机,数据库崩溃等,由jvm抛出的严重性问题。
                
        异常的继承体系  --都是java.lang包下的。
            * Object
                * Throwable  --是异常最顶层
                    * Error
                    * Exception --分 运行时异常 和 编译时异常
                        * RunTimeException --运行时异常,通常都是程序员自己犯的错误,只能通过运行程序后才能发现。可解决。
                               * NullPointerException
                               * IndexOutOfBoundsException
                               * ClassCastException
                               * NoSuchElementException
                               * ...
                        * 编译时异常,写程序过程中出现的直接错误。


b.
    JVM默认是如何处理异常的
         过程
            * 当主函数main收到这个问题时,有两种处理方案:
                * a.直接将问题处理,然后继续运行 --try...catch
                * b.直接没有针对的处理方式,只有交给调用main的jvm来处理 --抛
            * jvm有一个默认的异常处理机制,就将该异常进行处理
            * 并将该异常的名称,异常信息,异常出现的位置行数打印在控制台上,同时将出现停止运行。
代码【必看,了解异常的产生过程】
            public class Demo02_JVM默认是如何处理异常的 {
                public static void main(String[] args) {
                    Demo d = new Demo();
                    int div = d.div(10,0); 
                    System.out.println(div); // java.lang.ArithmeticException --属于RuntimeException 运行时异常。
                }
                
            }

            class Demo{
                public int div(int a, int b){  // a = 10  b = 0
                    return a / b; // 10是被除数,0是除数,当10 / 0的时候违背了算术运算法则,所以就在底层new出了这个
                                     异常对象。(抛出了异常对象) 返回的就是这个对象,将这个异常对象给 int div, div自然就接不住,所以jvm就调用了自己处理异常的方式(将该异常的名称,异常信息,异常出现的位置行数打印在控制台上,同时将出现停止运行。)。
                                     new ArithmeticException("/ by zero");   控制台的第一行 by zero 是该异常的参数。
                }
            }
    异常处理原理
        * 方法内容如果有异常隐患的存在,要么在方法上声明(throws),那么在方法内部使用try/catch捕捉到异常,否则编译不通过。
        * 如果调用了声明异常的方法,那么调用者try/catch,要么throws抛异常。
        * 当功能内容可以解决,就用try/catch
        * 解决不了,就用throws告诉调用者,由调用者来解决。
        * 一个功能如果抛出多个异常,那么在调用的时候,必须要对这些catch进行针对性处理,内部有几个需要检测的异常,就抛出几个异常。抛出几个,就catch几个。
c.
     异常处理1 --try catch finally
        异常处理的方式
        概述
            * 异常处理有两种方式
                * try...catch...finally --自己处理
                    * try  catch
                    * try  catch(单个或多个)  finally --基本格式
                    * try  finally --常常用于流异常代码的处理
                * throws --抛
        含义
            * try   用来检测异常(存放可能出异常的代码)
            * catch 用来捕获异常(对异常代码的处理方案)
            * finally 释放异常 (用于释放[关闭]一些资源,比如水龙头,用完就得关,不然浪费资源)
        注意:当try catch将问题处理了,程序会继续往后执行。 
    
-------
     异常处理2 --抛异常    
        概述
            * throws处理异常的过程
                * 定义功能方法时,需要把出现的代码问题暴露出来让调用者去处理
                * 那么就需要通过throws在方法上进行声明标识
        编译时异常的抛出
            * 必须对其立即处理。 
        运行时异常的抛出
            * 不用立即处理,也可以立即处理。
    
    
    throw和throws的区别    
        定义的位置不同,后面跟的内容不同,异常交给谁出来不同。
        throw概述
            * 在功能方法内部,程序出现的某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。
        throw 
            * 方法体内部,后面跟的是 new 异常对象,只能抛出一个异常对象,    
            * 表示抛出异常,在方法体内部进行处理
                *  --throw new Exception("异常描述");

        throws 
            * 方法声明上,后面跟的是throws 异常类型,可以有多个,用逗号隔开。 
            * 表示抛出异常,由该方法的调用者来处理。
                * --public static void main(String[] args) throws Exception  这里的main就表示 方法的调用者


    finally关键字的特点及作用
        概述
            * 被finally控制的语句体一定会被执行
            * 特殊情况:在执行到finally之前jvm语句退出了(如:system.exit(0))的时候,finally就不能够被执行
        作用
            * 用于释放(关闭)资源对象,如流对象,数据库DB对象,避免浪费资源。
        代码
            try {
                 System.out.println(4/0);
            } catch (Exception e) {
                System.out.println("程序错误");
                return; //return是用于关闭方法,但是在try catch中有finally的存在,所以在关闭方法之前,会将finally执行完后再关闭方法。 相当于return是将死之人,finally相当于遗言。在死之前会看看try catch中是否有finally的存在,如果有,就说完遗言后,再死(即将方法返回[关闭方法])。
            }finally{
                System.out.println("我执行了吗?");  // finally一定会被执行的,除非jvm提前退出。
            }
        
        【切记】
            finally里面 只是做释放资源用的,不能写其他代码。更不能有return,break,continue语句的出现。    

finally关键字的面试题
final,finally和finalize的区别
    final 
        * 是关键字,表示:“最终”,用于修饰类,变量 和 方法、
            * 当修饰类时,该类不能被继承,但能继承其他类。
            * 当修饰方法时,该方法不能被重写。
            * 当修饰变量时,变量变常量,必须初始化且只能被赋值一次。一般配合 public static final 一起使用。
    
    finally    
        * 是 try..catch 语句中的一个语句体,不能单独存在。用于释放资源。在try...catch中可有,也可没有。
        * 存在时一定会被执行,除非jvm提前退出。即:System.exit(0);
    
    finalize
        * 它是Object中的一个方法,用于执行垃圾回收。
        * 当垃圾回收器确定不存在对该对象更多的引用时,会由对象的垃圾回收器去调用该方法执行垃圾回收。
        * 当对象变成垃圾的时候,会由GC调用该对象的finalize()方法来进行垃圾回收,从而释放资源。
         
    

    
如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问是在return前还是return后。
        * 文字说明
            * 会执行。在return前执行,将return比喻是一个将死之人,finally是最后的遗言,只有说完该遗言后,才能死去,所以在return之前会执行finally方法。
            
        * 代码说明
            * public static void main(String[] args) {
                Demo3 d = new Demo3();
                int i = d.me(); //30 因为finally会在return之前执行,而return会最后执行。所以执行流程是:先执行finally的40,再执行catch中的30
                System.out.println(i);
            }
        }
        class Demo3{
            public int me(){
                int a = 10;
                try {
                    a = 20;
                    System.out.println(3/0);
                    return a;
                } catch (Exception e) {
                    a = 30;
                    return a; //会建立一个返回路径,将catch中的 a = 30 先给记录住,当finally语句执行完后,再将 返回路径中的30给取出,最后输出。
                }finally{
                    a = 40;
                }
            }

        * 上述代码说明 --Teacher说明
            * 当 3/0 后,会跳入到catch中,此时的return a执行了,它建立了一个返回路径,将a=30装入的一个箱子里,比如是一个临时变量,先记录这个值。再看是否有finally语句,如果有就执行finally中的a = 40,但返回路径的a = 30并没有改变,最后还是执行的是catch中返回路径记录的30。
        
    如果没有finally,后面的代码也会执行,那么finally有和没有的区别是什么?(假设finally一定会执行的正常情况下)
        如果catch中有return
            * 如果写了finally,那么里面的代码肯定会被执行。
            * 如果没有写finally,那么后面的代码不会执行 

--------
    
    处理代码中存在的多个异常
            * 当一个程序出现多个异常,catch中可以直接给Exception来处理所有 运行时异常,因为是:Exception e = new ArithmeticException(); 父类引用指向子类对象        
        方向
             Android 客户端开发,如何处理异常? try{}...catch(Exception e){ }
            JavaEE  服务端开发,一般都是底层开发,从底层开始向上抛,一个个异常都向上抛,最后有个错误日志,来分析错误日志从而解决异常

        注意:如果try后面有多个catch,小的异常往前方,大的异常往后放。根据多态原理,如果大的在前,就会将所有的子类对象接收,后面的catch就没意义了,就会报错。
        
        JDK7以后处理多个异常的方式及注意事项
            * try{}...catch(ArithmeticException | IndexOutOfBoundsException e){ sop("程序出错了"); }
            * 采用一个catch,里面用 |(或) 来判断具体是哪个异常  --不建议使用


d.
    编译期异常 和 运行期异常的 区别?
        概述
            * Java中的异常分为两大类:编译期异常 和 运行期异常
            * 所有RunTimeException都属于 运行期异常,其他的异常都属于 编译期异常。
                * 编译期异常 --一般指语法问题
                    * Java程序必须显示(立刻)处理,否则程序就会一直报错,无法通过预编译
                        * 编译代码程序时,可以出现存在的隐患问题,如文件路径不对,文件名错误这样的异常,必须在编译期间就用处理,如果不处理,程序就编译不过去。所以采用try catch中将可能出错的问题给他提前解决(即未雨绸缪)。
                        
                * 运行期异常 --程序员的问题
                    * 无需显示(立刻)处理,但也可以采用和编译期异常一样处理的方式
                        * 程序员自己犯的错误,需要根据错误改动代码
    

e.
    Throwable中常见方法
        概述
            * Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。
        方法
            * getMessage(); 获取当前异常信息,返回字符串的表现形式。
            * toString(); 获取当前异常信息的简单表述,返回字符串的表现形式。即:异常类名 和 异常信息。
            * printStackTrace();  获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。 --jvm默认就是用这种方式处理异常
        
        


        
f.
    自定义异常 及 异常的注意事项
        概述
            * 自定义异常需要继承 Exception 或 RuntimeException
            * 继承 Exception时,必须要处理异常
            * 继承 RuntimeException时,可以不处理异常
            


异常注意事项
            * 子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或该异常的子类。-- 子类异常不能大于父类异常
            * 父类抛出多个异常,子类覆盖父类后,只能抛出相同的异常或异常的子集,子类不能抛出父类没有的异常。
            * 被重写的方法没有异常抛出,子类的方法绝对不可以抛出异常的,如果子类方法中有异常,那么子类只能try, 不能抛(父类没有抛出异常,子类覆盖后绝对也不能抛出,只能try/catch)
a:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
b:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
c:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws
            
如何使用异常处理
            * 原则:如果该功能内部可以将问题解决,用try,如果处理不了。交给调用者来处理。这就要使用到throws
            * 后续代码要运行,就用try
            * 后续代码不需要运行,就用throws
            * 原则:能try就try, 不能try就throws
                * 区别
                    * 后续代码程序需要继续运行,就用try
                    * 后续代码程序不需要运行,就是用throws
            * JD中K没有提供对应的异常,就需要自定义异常。
g.
    异常练习
        * 案例
            *  键盘录入一个int类型的整数,对其求二进制表现形式
                 * 如果录入的整数过大,给予提示,录入的整数过大请重新录入一个整数BigInteger
                 * 如果录入的是小数,给予提示,录入的是小数,请重新录入一个整数
                 * 如果录入的是其他字符,给予提示,录入的是非法字符,请重新录入一个整数
        考察的是try catch 的嵌套


h.
    File
        概述
            * 在java.io.包下,说明该类主要是一个读写文件(路径)的类
            * File更应该叫做 路径
                * 文件路径或文件夹路径
                * 路径分为:绝对路径 和 相对路径
                    * 绝对路径: 一个固定的路径。从磁盘盘符开始
                    * 相对路径: 相对于某个位置。是相对于当前项目的。 如:在eclipse下是指当前项目路径下
                        * 在dos下指的是当前路径:cmd打开后的,看到的路径就是当前路径
                    
            * 查看API指的是当前路径
            * File表示:文件和目录路径名的抽象表示形式
            * 注意:复制的磁盘路径或其他路径都是如以下形式的:
                * 如:D:\CSDN_Android_\Code\Day19_异常 File类\文件夹    这样系统就会将\当成转移符,报错。 
                * 有两种解决方案:
                    * 将该路径的 \ 都变成 \\,如:D:\\CSDN_Android_\\Code\\Day19_异常 File类\\文件夹 
                    * 或者将该路径的 \ 都改为 / 即可,如:D:/CSDN_Android_/Code/Day19_异常 File类/文件夹/带有盘符路径的文件.txt
        

        构造方法
            * File(String url); 根据一个路径得到File对象。 
                * String url = "D:\CSDN_Android_\Code"; File file = new File(url);
            * File(File parent, String child); 根据父File对象 和 一个子文件/目录得到的File对象
            * File(String parent, String child);  根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。


        File类的创建功能
            * public boolean createNewFile(); 创建文件,如果文件存在,就不创建了。
                * 第一次运行,如果该文件没有存在,就返回true,否则false。
                * 第二次运行,直接false。因为第一次运行如果没有就创建,第二次运行肯定是false     
                * 在创建的时候可以不加后缀名,但是建议加上,因为系统就知道用什么工具打开该文件
            
            * public boolean mkdir(); 创建文件夹,如果文件夹存在,就不创建了。 --创建单级目录(文件夹)
            
            * public boolean mkdirs(); (创建多级目录[文件夹]) 创建文件夹,如果父文件夹不存在。就帮你创建出来。
   注意:如果创建的文件夹或文件忘记写盘符路径,那么默认就在当前项目路径下。


        File类的重命名和删除功能
            * public boolean renameTo(File dest); 把文件重命名为指定的文件路径
            * public boolean delete(); 删除文件或文件夹
            
            * 重命名注意事项        
                * 如果路径相同,就改名
                * 如果路径不同,就改名并且剪切
                
            * 删除注意事项
                * Java中的删除操作是不走回收站的
                * 要删除一个文件夹,首先确定该文件夹下是否有东西(文件夹/文件等),如果有就删除不成功。 
                 如果想删除带有内容的文件夹该怎么办?
                     * 采用遍历删除,该怎么做?
                

        File类的判断功能
            * public boolean isDirectory(); 判断是否有该目录(路径/文件夹)
            * public boolean isFile(); 判断是否是文件
            * public boolean exists(); 判断是否存在
            * public boolean canRde(); 判断是否可读  --win系统认为所有的文件都是可读的,这也是win系统下开发后的软件可在别的系统上运行的条件之一(跨平台)
                * file.setReadable(true 或者 false); // win系统中使用setReadable方法来判断是否可读,及时设置为false系统也认为是可读的,因为win系统规定文件都是可读的。
                
            * public boolean canWrite(); 判断是否可写 --win系统可以设置不可写
                * file.setWritable(false); //设置该文件不可写
            * public boolean isHidden(); 判断是否隐藏
        注意:windows操作系统所有的文件都是可读的,但是可以设置是否可写。
        

        File类的获取功能
            * public String getAbsolutePath(); 获取绝对路径
            * public String getPath(); 获取路径 --其实是构造方法里的路径
            * public String getName(); 获取名字 --文件 和 文件夹名称     
            * public long length(); 获取长度。文件内容的字节数
            * public long lastModified(); 获取最后一次修改的时间,获取的是 毫秒值
            * public String[] list(); 获取指定目录下的所有文件或者文件夹的名称数组  --前提:File参数必须是绝对路径。获取到的是String字符串
                * 指定目录只能是 绝对路径         
                * 获取到的是String文件夹名称
            * public File[] listFiles(); 获取指定目录下的所有文件或者文件夹的File数组  --前提:File参数必须是绝对路径。获取到的是File对象
                * 指定目录是:绝对路径   
                * 获取到的是File对象的toString方法的表现形式,说明获取到的是File对象,可根据File对象进行操作,如判断该文件是文件夹还是文件,或者是否可读,可写,可隐藏等操作
            

        输出指定目录下指定后缀的文件名
            案例演示
                * 需求:判断指定磁盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称
                
            代码
                File dir2 = new File(pathName);//获取pathName路径下的所有文件和文件夹【对象】
                File[] listFiles = dir2.listFiles();
                for (File file : listFiles) {
                    if(file.isFile() && file.getName().endsWith(".jpg")){
                            System.out.println(file.getName());
                    }
                }


        文件名称过滤器的概述及使用
            概述
                * public String[] list(FilenameFilter filter);
                * public File] listFiles(FilenameFilter filter);
            
            使用
                * 需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称

原创粉丝点击