19.01_异常(异常的概述和分类)
- A:异常的概述
- 异常就是Java程序在运行过程中出现的错误。
- B:异常的分类
- 通过API查看Throwable(异常顶层的类)
- Error
- 服务器宕机,数据库崩溃等(我们不能解决的)
- Exception C:异常的继承体系
- Throwable
- Error
- Exception
- RuntimeException(运行时异常)
- 除RuntimeException外都是编译时异常(在编译时必须对其进行处理)
19.02_异常(JVM<Java虚拟机>默认是如何处理异常的)
- A:JVM默认是如何处理异常的
- main函数收到这个问题时,有两种处理方式:
- a:自己将该问题处理(try....catch),然后继续运行
- b:自己没有针对的处理方式,只有交给调用main的jvm来处理
- jvm有一个默认的异常处理机制,就将该异常进行处理.
- 并将该异常的名称,异常的信息.异常出现的位置打印在了控制台上,同时将程序停止运行
- B:案例演示
- JVM默认如何处理异常
19.03_异常(try...catch的方式处理异常1)
- A:异常处理的两种方式
- a:try…catch…finally * try是用来检测异常的 * catch是用来捕获异常的 * finally释放资源
- b:throws(抛出异常)
- B:try...catch处理异常的基本格式
- try…catch…finally
- C:案例演示
- try...catch的方式处理1个异常
-
Demo d = new Demo(); try { int x = d.div(10, 0); /*抛出异常对象new ArithmeticException(" / by zero") try检测到异常,将异常交给catch,执行catch中的语句 */ System.out.println(x); } catch (ArithmeticException e) {//ArithmeticException e = new ArithmeticException(" / by zero") /*try检测到异常,将异常交给catch后,执行ArithmeticException e = new ArithmeticException(" / by zero") * e 有值了,可以对e进行操作。 */ System.out.println("除数为零了"); } } } class Demo { public int div(int a,int b) {//a = 10,b = 0 return a / b; //除数不能为0 /*除数为0后,创建一个异常对象new ArithmeticException(" / by zero") 因主方法main调用的Demo()方法,就将new ArithmeticException(" / by zero")异常对象抛给了主方法 由主方法中的X去接收,x是int型,x接不住, main将异常对象抛给了虚拟机,虚拟机找到对应的异常处理方式,将异常信息打印到控制台 */ } } ******************************************* 除数为零了
19.04_异常(try...catch的方式处理异常2)
- A:案例演示
- try...catch的方式处理多个异常
- 一个try可以跟多个catch
* 安卓都是try{}catch(Exception e){}客户端
* EE都是从底层往上抛 服务端
-
int a = 10; int b = 0; int[] arr = {11,22,33}; try { System.out.println(a / b); System.out.println(arr[5]); //ArrayIndexOutOfBoundsException数组索引越界异常 } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {//1.7版本的异常处理,注意不能子父类同时放 /*|或(catch捕获的是算数运算异常或是数组越界异常)
f(e.getClass()==ArithmeticException.class)//如果是同一个字节码文件(判断引用e指向的异常对象指向的字节码文件和对应字节码文件是否一样)System.out.println("除数为零了"); } catch (Exception e3) {//Exception e3父类引用指向子类对象 /* * 最大的异常应该写在最后 */ System.out.println("出问题了"); } System.out.println("over"); } ************************************** 除数为零了 over
19.05_异常(JDK7针对多个异常的处理方案)
- A:案例演示
- JDK7以后处理多个异常的方式及注意事项
19.06_异常(编译期异常和运行期异常的区别)
-
A:编译期异常和运行期异常的区别
- Java中的异常被分为两大类:编译时异常和运行时异常。
-
所有的RuntimeException类及其子类的实例被称为运行时异常,其他的异常就是编译时异常
-
编译时异常
- Java程序必须显示处理,否则程序就会发生错误,无法通过编译
- 未雨绸缪,在准备要做某件事的时候,要提前想到可能会发生什么事
- 运行时异常
- 无需显示处理,也可以和编译时异常一样处理
- 编译时不会报错,程序运行起来如果有错误就会报异常,运行时异常都是程序员犯的错误,需要回来修改代码
- 常见运行时异常:
- ClassCastException//类型转换异常
ConcurrentModificationException并发修改异常
IndexOutOfBoundsException数组索引越界异常
NullPointerException空指针异常
UnsupportedOperationException//当不支持请求的操作时,抛出该异常
ArithmeticException//运算异常
NoSuchElementException//表明枚举中没有更多的元素
- 编译期异常和运行期异常的区别
-
19.07_异常(Throwable的几个常见方法)
- A:Throwable的几个常见方法
- a:getMessage()
- 获取异常信息,返回字符串。
- b:toString()
- 获取异常类名和异常信息,返回字符串。
- c:printStackTrace()
- 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。(等同于JVM处理异常的方式)
- a:getMessage()
- B:案例演示
- Throwable的几个常见方法的基本使用
-
public static void main(String[] args) { try { System.out.println(1/0);//new ArithmeticException("/ by zero");产生运算异常对象 } catch (ArithmeticException e) {//将运算异常对象赋给e System.out.println(e.getMessage()); //获取异常信息(打印构造方法中的字符串) System.out.println(e.toString()); //错误类名+异常信息 e.printStackTrace();//错误类名+异常信息+错误位置(行号)jvm默认处理异常使用此方法 } } ***************************************** / by zero //getMessage()结果 java.lang.ArithmeticException: / by zero //toString()结果 java.lang.ArithmeticException: / by zero //printStackTrace()结果 at cn.itcast.exception.Demo4_Exception.main(Demo4_Exception.java:10)
19.08_异常(throws的方式处理异常)
- A:throws的方式处理异常
- 定义功能方法时,需要把出现的问题暴露出来让调用者去处理。
- 那么就通过throws在方法上标识。
- * throws如果抛出的是RuntimeException及其子类,调用该方法的时候不用处理,抛出RutimeException和不抛效果一样如果抛出的是除了RuntimeException及其子类.调用方法必须处理再次抛出,throws....抛给虚拟机处理try....catch处理
- B:案例演示
- 举例分别演示编译时异常和运行时异常的抛出
-
public static void main(String[] args) throws Exception { Test t = new Test(); int x = t.div(10, 0); System.out.println(x); } } class Test { public int div(int a,int b) throws Exception { /*Exception是编译异常,编译的时候要做处理 * throws Exception在div()方法上做了一个标识,表示:该方法在调用时肯能会出现问题 */ return a / b; } }
19.09_异常(throw的概述以及和throws的区别)
- A:throw的概述
- 在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。
- B:案例演示
- 分别演示编译时异常对象和运行时异常对象的抛出
- C:throws和throw的区别
- a:throws
- 用在方法声明后面,跟的是异常类名
- 可以跟多个异常类名,用逗号隔开
- 表示抛出异常,由该方法的调用者来处理
- b:throw
- 用在方法体内,跟的是异常对象名
- 只能抛出一个异常对象名
- 表示抛出异常,由方法体内的语句处理
-
/* * throws用在方法声明中,后面跟异常类,可跟多个异常类(之间用,隔开) * (Exception异常类和其子类,在此处没有先后关系。抛出Exception与抛出其子类是有两种结果) */ public void setAge(int age) throws Exception,ArithmeticException { /*throws抛出异常由其调用者处理, * 此处是main函数调用,由main处理, * main可以自己处理(添加try...cantch语句) * 也可以交给虚拟机处理(再在main方法声明中抛出异常throws Exception,ArithmeticException) */ if(age>0&&age<200){ this.age = age; } else {/*throw用在在方法中,后面跟异常对象(只能跟一个异常对象) throw new Exception("年龄错误");/*在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。*/ } }
- a:throws
19.10_异常(finally关键字的特点及作用)
- A:finally的特点
- 被finally控制的语句体一定会执行
- 特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))
- B:finally的作用
- 用于释放资源,在IO流操作和数据库操作中会见到
- C:案例演示
- finally关键字的特点及作用
19.11_异常(finally关键字的面试题)
- A:面试题1
- final,finally和finalize的区别
- * final,finally是关键字
* finalize方法名
* final可以修饰类,方法,变量(常量)使得(类不能被继承,方法不能被重写,变量为常量不能改变<基本数据变量不能改变其值,引用数据变量不能改变其地址值但可以改变其中的属性>)
* finally写在try catch语句用于释放资源(关闭数据库,关闭流)
* finalize()是一个方法,在垃圾回收的时候调用
- B:面试题2
- 如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问是在return前还是return后。
- finally的代码会在return前执行
-
public static int getNum() { int x = 10; try { System.out.println(10 / 0); return x;//try和catch里面都应该有return语句,如果try没有检测到问题 } catch (Exception e) { //不会跳转到catch里面去,那么需要try里面有返回 x = 20; return x;//return建立了一个返回路径 /* *出现异常执行catch中的语句:x=20;碰见return,建立返回路径并将20放入返回路径中(还未返回),再看有没有finally语句。 *有finally:执行finally中语句; *将返回路径中的20返回 */ }finally {//finally 释放资源 x = 30; System.out.println("执行了吗"); //return x;//finally可以写return语句,但是不要这么写,因为会将结果改变 }//finally中写return语句,会将前面的所有返回值覆盖掉 } //finally的作用就是为了释放资源 }
19.12_异常(自定义异常概述和基本使用)
- A:为什么需要自定义异常
- 举例:人的年龄
- B:自定义异常概述
- 继承自Exception
- 继承自RuntimeException
- C:案例演示
- 自定义异常的基本使用
-
public class AgeOutOfBoundsException extends Exception { /*
自定义异常类: * 1,起一个恰当的名字继承Exception * 2.重写构造方法 */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~public AgeOutOfBoundsException (){ super(); } //自定义异常的有参构造方法 public AgeOutOfBoundsException (String message){ super(message); } }
public void setAge(int age) throws AgeOutOfBoundsException {
/*throws抛出AgeOutOfBoundsException自定义异常由其调用者处理,
* 此处是main函数调用,由main处理,
* main可以自己处理(添加try...cantch语句)
* 也可以交给虚拟机处理(再在main方法声明中抛出异常throws Exception,ArithmeticException)
*/
if(age>0&&age<200){
this.age = age;
}
else
{/*throw用在在方法中,后面跟异常对象(只能跟一个异常对象)
*/
throw new AgeOutOfBoundsException("年龄非法");//throw后面跟的是一个自定义类型的异常
}
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static void main(String[] args) throws AgeOutOfBoundsException {
Person p = new Person();
p.setAge(-18);
p.setName("张三");
System.out.println(p.getName() + "," + p.getAge());
}
}
19.13_异常(异常的注意事项及如何使用异常处理)
- A:异常注意事项
- a:子类重写父类方法时,子类方法如果抛出异常:子类的方法必须抛出与父类相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
- b:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
- c:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try...catch处理,不能throws
-
-
B:如何使用异常处理
- 原则:如果该功能内部可以将问题处理(自己可以处理),用try,如果处理不了,交由调用者处理,这是用throws
-
区别:
- 后续程序需要继续运行就try
- 后续程序不需要继续运行就throws
-
如果JDK没有提供对应的异常,需要自定义异常。
19.14_异常(练习)
- 键盘录入一个int类型的整数,对其求二进制表现形式
- 如果录入的整数过大,给予提示,录入的整数过大请重新录入一个整数BigInteger
- 如果录入的是小数,给予提示,录入的是小数,请重新录入一个整数
- 如果录入的是其他字符,给予提示,录入的是非法字符,请重新录入一个整数
-
Scanner sc = new Scanner(System.in);//创建键盘录入对象 System.out.println("请输入一个整数"); while(true) { String line = sc.nextLine(); //将键盘录入的结果存储在line中 try { int num = Integer.parseInt(line);//将数字字符串转成数字 System.out.println(Integer.toBinaryString(num));//将数字转换成二进制打印 break; } catch (Exception e) { try { new BigInteger(line);//如果能封装到BigInteger对象中说明是一个过大的整数 System.out.println("录入的整数过大请重新录入一个整数:"); } catch (Exception e2) { try { new BigDecimal(line); /*如果能封装到BigDecimal对象中说明是一个小数 BigDecimal()也可以接收过大的整数 */ System.out.println("录入的是小数,请重新录入一个整数"); } catch (Exception e3) { System.out.println("录入的是非法字符,请重新录入一个整数"); } } } } } } ********************************************* 请输入一个整数 111111111111111111111111111111111111111111111111111111111 录入的整数过大请重新录入一个整数: 12.3 录入的是小数,请重新录入一个整数 12 1100
19.15_File类(File类的概述和构造方法)
- A:File类的概述
- File更应该叫做一个路径
- 文件路径或者文件夹路径
- 路径分为绝对路径和相对路径
- 绝对路径是一个固定的路径,从盘符开始
- 相对路径相对于某个位置。(在eclipse下是指当前项目下,在dos下指的是当前路径)
- 查看API
- 文件和目录路径名的抽象表示形式
- File更应该叫做一个路径
- B:构造方法
- File(String pathname):根据一个路径得到File对象
- File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
- File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象
- C:案例演示
- File类的构造方法
-
File parent = new File("F:\\2015\\0302"); //父级路径的文件对象 String child = "day19异常+File"; //子级路径 File file = new File(parent, child); System.out.println(file.exists()); } public static void demo2() { /* * File(String parent, String child):根据一个目录和一个子文件/目录得到File对象 */ String parent = "F:\\2015\\0302"; //父级路径 String child = "day19异常+File"; //子级路径 File file = new File(parent, child); System.out.println(file.exists());//file.exists()查看文件路径是否存在 } public static void demo1() { /* * File(String pathname):根据一个路径得到File对象 */ File file1 = new File("F:\\2015\\0302\\day19异常+File"); //绝对路径 File file2 = new File("xxx.txt");/*相对路径,相对于eclipse当前项目下 文件存在于当前项目下,而不是src下 */ boolean b1 = file1.exists(); //判断路径是否存在 System.out.println(b1); boolean b2 = file2.exists(); System.out.println(b2); }
19.16_File类(File类的创建功能)
- A:创建功能
- public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
- public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
- public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来
-
B:案例演示
-
File类的创建功能
-
注意事项:
- 如果你创建文件或者文件夹忘了写盘符路径,那么,默认在项目路径下。
- 创建的文件可以没后缀名,创建的文件夹可以有后缀名
-
File dir1 = new File("aaa"); boolean b1 = dir1.mkdir();//创建文件夹 System.out.println(b1); /* * 文件夹也可以有后缀 */ File dir2 = new File("bbb.txt"); boolean b2 = dir2.mkdir(); //创建单级目录 System.out.println(b2); File dir3 = new File("ccc\\ddd"); boolean b3 = dir3.mkdirs(); //创建多级目录 System.out.println(b3); } public static void demo1() throws IOException { File file = new File("yyy.txt");/*得到相对路径,会在当前项目下找yyy.txt */ boolean b1 = file.createNewFile();//创建新文件 /* * 可能出现异常,因为new File("yyy.txt")中的路径可能不存在。 * */ System.out.println(b1); System.out.println(file.exists()); //创建的文件不一定都有后缀。 File file2 = new File("zzz"); boolean b2 = file2.createNewFile(); /*创建一个新文件,如果文件不存在就创建返回true ,file2这个路径如果已经存在(即文件已存在)不在创建文件。*/ System.out.println(b2); //如果文件存在,就不创建,返回false System.out.println(file2.exists()); } }
-
19.17_File类(File类的删除功能)
- A:删除功能
-
B:案例演示
-
File类的删除功能
-
- public boolean delete():删除文件或者文件夹
File file1 = new File("xxx.txt");//得到一个路径 boolean b1 = file1.delete(); System.out.println(b1); File file2 = new File("bbb.txt"); boolean b2 = file2.delete(); //删除文件夹,必须删的是空的 System.out.println(b2);
-
注意事项:
- Java中的删除不走回收站。
- 要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹
-
19.18_File类(File类的重命名功能)
- A:重命名功能
- public boolean renameTo(File dest):把文件重命名为指定的文件路径
-
B:案例演示
-
File类的重命名功能
-
注意事项:
- 如果路径名相同,就是改名。
- 如果路径名不同,就是改名并剪切。
-
File file1 = new File("zzz.txt"); File file2 = new File("D:\\xxx.txt"); boolean b = file1.renameTo(file2); System.out.println(b);
-
19.19_File类(File类的判断功能)
- A:判断功能
- public boolean isDirectory():判断是否是目录
- public boolean isFile():判断是否是文件
- public boolean exists():判断是否存在
- public boolean canRead():判断是否可读
- public boolean canWrite():判断是否可写
- public boolean isHidden():判断是否隐藏
- B:案例演示
- File类的判断功能
-
File file = new File("bbb.txt"); //file.setReadable(false); //设置成不可读 //在windows系统下所有的文件都是可读 //boolean b1 = file.canRead();//判断能不能读 //System.out.println(b1); file.setWritable(true); //在windows系统下可以设置为不可写 boolean b2 = file.canWrite(); System.out.println(b2); File file2 = new File("ccc.txt"); System.out.println(file2.isHidden()); //判断是否是隐藏文件 System.out.println(file.isHidden()); } public static void demo1() { File file1 = new File("aaa"); File file2 = new File("bbb.txt"); System.out.println(file1.isDirectory()); System.out.println(file2.isDirectory()); System.out.println("---------------------------"); System.out.println(file1.isFile()); System.out.println(file2.isFile()); } }
/** * @param args * 键盘录入一个文件路径 * 1,如果不存在提示,你录入的路径不存在 * 2,如果是文件夹,提示您录入的是文件夹路径 * 3,如果是文件,返回该文件 */ public static void main(String[] args) { File file = getFile(); System.out.println(file); } /* * 根据键盘录入获取文件对象 * 1,File * 2,参数列表() * D:\\xxx.txt */ public static File getFile() { Scanner sc = new Scanner(System.in); System.out.println("请输入一个文件路径"); while(true) { String line = sc.nextLine(); //将键盘录入的文件路径结果存储在line中 File file = new File(line); //封装file对象 if(!file.exists()) {//判断文件路径是否存在 System.out.println("您录入的文件路径不存在,请重新输入一个文件路径"); }else if(file.isDirectory()) {//判读是不是文件夹路径 System.out.println("您输入的是一个文件夹路径,请重新输入一个文件路径"); }else { return file;//遇见return整个方法都结束 } } } }
19.20_File类(File类的获取功能)
- A:获取功能
- public String getAbsolutePath():获取绝对路径
- public String getPath():获取相对路径
- public String getName():获取名称
- public long length():获取长度。字节数
- public long lastModified():获取最后一次的修改时间,毫秒值
- public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
- public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组
- B:案例演示
- File类的获取功能
-
File dir = new File("F:\\2015\\0302\\day19异常+File");//dir是一个文件夹 String[] arr1 = dir.list(); //只是为了获取名字 for (String string : arr1) { System.out.println(string); } File[] subFiles = dir.listFiles(); //为了获取File对象,对其做各种操作 for (File file : subFiles) { System.out.println(file);//File重写tostring方法,打印绝对路径 } } public static void demo3() { File file = new File("ccc.txt"); long time = file.lastModified();//获取文件最后的修改时间 System.out.println(time);//距离1970年1月1日00:00:0;的毫秒值 Date d = new Date(time);//得到毫秒值对应的时间 System.out.println(d); } public static void demo2() { File file = new File("F:\\2015\\0302\\day19异常+File\\day19笔记.md"); long len = file.length();//如果获取的是文件返回的是字节个数 System.out.println(len); File file2 = new File("F:\\2015\\0302\\day19异常+File"); long len2 = file2.length(); //如果直接获取文件夹的大小返回就是0 System.out.println(len2); } public static void demo1() { File file1 = new File("ccc.txt"); System.out.println(file1.getAbsolutePath()); //获取绝对路径 System.out.println(file1.getPath()); //获取相对路径 System.out.println(file1.getName()); File file2 = new File("D:\\150302\\day19"); System.out.println(file2.getName()); //获取名称(文件和文件夹) } }
19.21_File类(输出指定目录下指定后缀的文件名)
- A:案例演示
- 需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称
-
File dir = new File("E:\\");//将路径封装成File对象 String[] arr = dir.list();//获取这个路径下所有的文件或文件夹路径 for (String s : arr) { if(s.endsWith(".jpg")) {//判断字符串是否以某个指定字符串结尾 System.out.println(s); } }
-
File[] subFiles = dir.listFiles();//将路径中的文件夹和目录封装到File数组中 for (File subFile : subFiles) {//得到文件对象,可判断是文件还是目录 if(subFile.isFile() && subFile.getName().endsWith(".jpg")) { System.out.println(subFile.getName()); } }
19.22_File类(文件名称过滤器的概述及使用)
- A:文件名称过滤器的概述(将含有某一文件(夹)名字的保留)
- public String[] list(FilenameFilter filter)
- public File[] listFiles(FilenameFilter filter)
-
接口 FilenameFilter实现此接口的类实例可用于过滤器文件名
-
boolean accept(File dir,String name)//测试指定文件是否应该包含在某一文件列表中
-
文件名称过滤器的使用:实现接口FilenameFiler的同时,要重写accept()方法
- B:文件名称过滤器的使用
- 需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称
- C:源码分析
- 带文件名称过滤器的list()方法的源码
-
String[] arr = dir.list(new FilenameFilter() {//匿名内部类 @Override public boolean accept(File dir, String name) {//重写accept() File file = new File(dir,name);//dir父级,name子级 return file.isFile() && file.getName().endsWith(".jpg"); /*满足某种条件(是一个文件,且后缀名为.jpg)返回ture就将瞒足条件的返回到arr数组中 */ } }); for (String s : arr) { System.out.println(s); } }
19.22_File类(递归)
* 递归
* 方法自己调用自己
* 弊端:容易栈内存溢出
* 好处:不用知道调用次数
* 方法自己调用自己
* 弊端:容易栈内存溢出
* 好处:不用知道调用次数
* 构造函数不能使用递归
* 递归调用是否必须有返回值?
不一定(可以有也可以没有)
* 递归调用是否必须有返回值?
不一定(可以有也可以没有)
- 5的阶乘
-
int result = 1; for(int i = 1; i <= 5; i++) { result = result * i; } System.out.println(result); }
public static int fun(int num) { if(num == 1) { return 1; }else { return num * fun(num - 1); } }
}System.out.println(fun(10000));
19.23_day19总结
把今天的知识点总结一遍。