Java基础知识 异常&&File &&递归
1.异常
异常的概述:在Java运行过程不正常的情况,出现的错误,成为异常;
异常就是一个对象,描述了那些不符合正常的情况,包含了这些情况的异常的原因,类型、位置及描述;
异常也是一种处理异常的方式,可以跳转,捕获以及程序结束
异常的体系
1,顶层父类
Throwable 类是 Java 语言中所有错误或异常的超类。
其他异常的或者错误都是其子类,只有Throwable体系类型。才可以使用异常的处理机制;
2.直接子类 Error Exception
Error:错误,是Throwable的子类,用于描述那些无法捕获和处理的情况,属于非常严重的情况,如:StackFlowError,栈内存溢出错误;
Exception:异常,是Throwable的子类,用于描述那些可以捕获和处理的情况,属于不太严重的情况,如:ArrayIndexOutOfBoundsException;
RuntimeException:运行时异常,是Exception的特殊子类,在编译阶段不处理的异常;
3.体系图
Throwable
|--Error
|--Exception
|--RuntimeException
4.在虚拟机中默认的处理机制
1.在代码的某个位置,出现了不正常的情况,就将异常情况封装为一个异常对象;
2.将异常对象抛给调用该方法的方法(抛给调用者);
3.某个方法收到异常,无法解决,继续向上抛,最终抛给主方法,
当main()方法也无法处理,这是将异常对象抛给虚拟机;
4.虚拟机是我们手动调用的,只能将异常对象的信息通过错误流打印出来,展示给我们,然后结束虚拟机;
5.虚拟机默认的处理方式,就是一层一层向上抛,虚拟机接收之后,展示给使用者,然后结束自己;
5.手动处理异常
1.两大类解决异常的方式
1.异常的声明:某个方法有编译时异常,编译就无法通过,需要在异常所在的方法上进行声明,声明该方法出现的编译时异常;
2.异常的处理:出现异常之后,通过某些格式来捕获异常,可以让程序在出现异常之后继续运行,可以定义自己处理异常的方式;
3.三个格式
try...catch
try...catch...finally
try...finally
4.try...catch
格式:try{
可能发生异常的代码;
}catch(可能出现的异常的类型 标识符){
异常的处理方式;
}
运行机制:
1.运行try语句的代码;
2.如果没有发生异常,不会执行catch块内的内容;
3.如果发生了catch块声明的异常,就会捕获这个异常,执行catch的内容;
4.如果发生了catch块内的没有声明的异常,就会执行 默认的处理机制;
5.异常捕获的第一种格式的多种异常情况
格式:try{
可能出现异常的代码;
}catch(异常类型1 标识符1){
异常处理方式1;
}catch(异常类型2 标识符2){
异常处理方式2;
}
注意:1.一次只能捕获一个异常,逐个异常来解决,直到运行通过,或遇到没有解决的异常,按照默认的异常处理方式,结束虚拟机;
2.不能将父类Exception定义在第一个catch块中,因为在接下来的子类catch块没有执行的机会,产生错误;
3.在JDK1.7以后,允许在一个catch块中,进行异常“或运算”处理
如ArithmeticException | NullException an
6.异常捕获的第二种格式的多种异常情况
格式:try{
可能出现异常的代码;
}catch(异常类型1 标识符1){
异常处理方式1;
}finally{
一定会执行的代码;
如:关闭还在运行的线程,关闭资源,释放内存;
}
7.异常捕获的第三种格式的多种异常情况
格式:try{
可能出现异常的代码;
}finally{
一定会执行的代码;
如:关闭还在运行的线程,关闭资源,释放内存;
}
特点:1.无法捕获和处理异常,一旦发生异常进行默认的处理机制,交给虚拟机处理,然后执行finally里的代码;
2.把一定要执行的代码放在finally里,可视为一种保险做法;就算异常发生了,必须要执行的代码还是会执行到,不会受到影响;
2.编译时异常和运行时异常
1.编译时异常为Exception以及其子类(除RuntimeException),
2.运行时异常为RuntimeException及其子类;
3.编译时异常,在编译阶段对异常进行检测,一旦有这种编译时异常,在编译阶段不能通过,只有通过两种手段进行解决(1.异常声明,2.手动解决)
4.运行时异常不会在编译时检测,在编译时及时存在也不会报错,可以通过异常处理的手段解决,亦可以使用异常的避免方式(声明异常)
3.继承体系中的常用方法
Throwable() 构造一个将 null 作为其详细消息的新 throwable。
Throwable(String message) 构造带指定详细消息的新 throwable。
Throwable(String message, Throwable cause)
构造一个带指定详细消息和 cause 的新 throwable。
Throwable(Throwable cause) 构造一个带指定 cause 和 (cause==null ? null :cause.toString())(它通常包含类和 cause 的详细消息)的详细消息的新 throwable。
void printStackTrace()
将此 throwable 及其追踪输出至标准错误流。
StackTraceElement[] getStackTrace()
提供编程访问由 printStackTrace() 输出的堆栈跟踪信息。
void setStackTrace(StackTraceElement[] stackTrace)
设置将由 getStackTrace() 返回,并由 printStackTrace() 和相关方法输出的堆栈跟踪元素。
String toString() 返回此 throwable 的简短描述。
Throwable getCause() 返回此 throwable 的 cause;如果 cause 不存在或未知,则返回 null。
String getMessage() 返回此 throwable 的详细消息字符串。
4.throw关键字 主要用于抛出运行时异常,抛出的是异常对象
抛出,抛出一个异常对象,当程序运行到某种情况时,程序员认为这种情况与现实情况不符,这是就把当前情况封装为一个对象,进行抛出;
作用:
创建一个异常对象,抛给调用者;
如果抛出的是编译时异常,则该异常必须解决,否则编译无法通过;
如果抛出的是运行时异常,则相当于在编译时没有异常;
5.throws关键字 用于抛出异常类型,异常声明;主要用于编译时异常,作用在方法的声明上
当编译时异常没有给出解决方案,没有捕获这个异常,编译无法通过;
throws后面可以跟多个异常类型,即抛出多个异常;
方法中抛出运行时,可以不做处理,如果声明运行时异常,调用者也可以不处理;
如果方法中抛出的是编译时异常,调用者就必须做出处理;
如果方法上进行异常的声明,说明方法可能出现异常;
如果调用者调用声明异常的方法,需要进行异常处理
方法1:继续向上抛;
方法2:自己解决 try catch
注意:向上抛异常时,异常的范围要大于等于被调用方法的异常范围;
6.处理异常
两种方式:
异常的处理 try catch finally
异常的声明 throws
7.throw和throws的区别
throw 是对异常对象的抛出;一次只能抛出一个异常;
throws是对异常类型的声明;一次可以声明多个异常,用逗号分隔;
throw 是真真正正的产生了异常对象,而throws可能产生了异常,也可能没有产生异常;
8.自定义异常
1、jdk中提供了很多的异常类型,其中的绝大部分都没有自己特有的方法
2、定义这么多异常,没有特有方法、没有特有属性,原因:
1、如果有了很多的异常类型的名字,将来在不同的异常情况下,就可以使用不同的异常类型创建对象。一旦发生了异常,可以很容易通过异常的类名来判断到底发生了什么异常情况
2、如果有了很多的异常类型,不同的异常类型,就可以有不同的处理方式
3、在自己的业务中,jdk提供的各种异常,都无法描述当前的异常情况,就需要我们自己定义异常类型,用在自己的项目的业务中。
4、自定义异常的步骤:
1、定义一个类,以Exception结尾,IllegleAgeException,表示这是一个非法年龄异常
2、让自己定义的这个类,继承一个Exception或者是RuntimeException
如果定义的是编译时异常,就使用Exception
如果定义的是运行时异常,就使用RuntimeException
3、构造方法不能被继承,需要手动添加
2.递归
方法本身调用 方法本身;
1、递:传递、逐渐的、一个接一个;归:回去,回到简单原始的状态
2、有一种从大到小,从复杂到简单的传递过程
3、递归:方法自己调用自己,解决的是一个比较复杂的问题,复杂的问题基于简单的问题已经解决的基础上,经过非常少的步骤,就可以解决这个复杂的问题。方法在自己调用自己的过程中,调用的逻辑总体不变,但是解决的问题的规模越来越小(调用者的规模越来越小,参数的规模越来越小),一直小到不需要递归的方式,也能容易解决这个问题为止,就不需要再递归调用该方法了。
4、递归代码的特点:
1、自己调用自己:总体逻辑不变,但是规模在缩小;由于自己调用自己,所以功能都要单独的定义成一个方法
2、代码会有两个分支:自己调用自己的分支,规模还比较大的时候,无法直接简单解决的时候;不需要自己调用自己的分支,规模已经简单到不需要自己调用自己,而使用一个很简单的操作就可以完成
3、每次递归调用的时候,朝着规模减小的方向、朝着不需要递归的方向调用
使用递归的注意事项
1、递归的效率比较低,因为方法需要不断的进栈和出栈
2、递归的算法比较浪费栈内存的空间,栈内存本身比较小,很容将栈内存的内存空间耗尽,那么程序就无法继续执行下去,报出一个错误:
StackOverflowError:栈内存溢出
3、国外有一个网站:StackOverflow,专业版的知乎
4、递归算法的好处:
思路比较简单,假设简单问题解决了
5、所有的递归算法,都有非递归的解决方式,只不过非递归的算法设计比较困难
3.File
1.概述:
1、File类型:用于表示一个文件或者是文件夹的路径的对象(抽象路径名)
2、路径:用于描述文件或者文件夹的所在位置的字符串
3、路径分类:绝对路径、相对路径
4、绝对路径:从根目录开始的路径,称为绝对路径
Windows系统中:盘符目录就是根目录,D:、E:
Linux系统中:/就是根目录,从/开始的路径就是绝对路径
5、相对路径:相对于某个路径而言的路径
相对于不同的路径,同样的相对路径,表达的是不同的路径
Dos命令行中:相对于当前路径(Dos命令行所在的路径),a/b/c.txt
Eclipse中:相对于当前工程的根目录
2.构造方法:
1、File(String path):把字符串的路径,封装成一个File对象
2、File(String parent, String child):将父级路径和子级路径封装成一个File对象,其实描述的是父级路径和子级路径拼接后的路径
3、File(File parent, String child):将父级File对象路径和字节路径封装成一个File对象,其实描述的也是父级路径和子级路径拼接后的路径
3.创建文件和文件的方法:
1、boolean createNewFile():创建当前File对象所描述的路径的文件
2、boolean mkdir():创建当前File对象所描述的路径的文件夹(如果父级路径不存在,那么不会自动创建父级路径)
3、boolean mkdirs():创建当前File对象所描述的路径的文件夹(如果父级路径不存在,那么自动创建父级路径)
4.删除文件夹或者文件
1、delete():删除调用者描述的文件或者文件夹
2、注意事项:
1、delete在删除文件夹的时候,只能删除空文件夹
2、delete方法不走回收站
5.重命名
1、renameTo(File dest)
调用者是当前的文件或者文件夹的路径对象
参数是变化之后的文件或者文件夹的路径对象
2、注意事项:
如果在同一个文件夹下,修改路径,就是重命名
如果在不同文件夹下,修改路径,就是剪切
6.文件及文件夹的判断功能
1、exists():判断当前调用者File对象,是否存在
2、isFile():判断当前调用者File对象,是否是文件
3、isDirectory():判断当前调用者File对象,是否是文件夹
7.文件及文件夹的获取功能
1、getAbsolutePath():获取当前File对象的绝对路径
2、getPath():获取的就是在构造方法中封装的路径
3、getName():获取最底层的简单的文件或者文件夹名称(不包含所造目录的路径)
4、length():获取文件的字节个数
该方法被文件File对象调用时,返回的是文件的字节个数
该方法被文件夹File对象调用时,返回的数据是不确定的
5、String[] list():获取当前文件夹下的所有文件和文件夹的名称,到一个字符串数组中
6、File[] listFiles():获取当前文件夹下的所有文件和文件夹的File对象,到一个File对象数组中