目录
6.2、灵魂二问:如果try中可能会遇到多个问题,怎么执行?
6.3、灵魂三问:如果try中遇到的问题没有被捕获,怎么执行?
6.4、灵魂四问:如果try中遇到了问题,那么try下面的其它代码还会执行吗?
1.2.3根据父路径对应文件对象和子路径名字符串创建文件对象
1.createNewFile() 创建一个新的空的文件,创建成功返回true
2.mkdir make Directory,文件夹(目录)
1.2、找某一个文件夹中,是否有以avi结尾的电影(不考虑子文件夹)
1.3、找某一个文件夹中,是否有以avi结尾的电影(考虑子文件夹)
一、异常
误区:不是让我们以后不出异常,而是出现异常了之后,如何去处理
1、异常的分类
1.1、Error
1.2、Exception
1.3、小结
2、编译时异常和运行时异常
2.1、编译时异常
2.2、运行时异常
2.3、为什么异常要分成编译时异常和运行时异常?
在编译阶段,Java不会运行代码,只会检查语法是否错误,或者做一些性能的优化
编译时异常更多的是提醒程序员检查本地的信息
运行时异常的核心在于提醒,而是代码出错导致程序出现的问题
2.4、小结(运行时异常和编译时异常的区别)
3、异常的作用
3.1、查看bug的关键参考信息
3.1.1
3.1.2
3.2、作为方法内部的一种特殊返回值
4、JVM默认的处理方式
示例代码:
异常:
5、try…catch(捕获异常)
5.1、示例代码
Console:
6、灵魂四问
6.1、灵魂一问:如果try中没有遇到问题,怎么执行?
顺序执行,没有问题,自然就不会触发捕获异常
6.2、灵魂二问:如果try中可能会遇到多个问题,怎么执行?
6.3、灵魂三问:如果try中遇到的问题没有被捕获,怎么执行?
6.4、灵魂四问:如果try中遇到了问题,那么try下面的其它代码还会执行吗?
6.5、小结
7、异常中的常见方法
7.1、示例代码
添加异常处理
7.2、System.err
在控制台中红色打印
8、抛出异常
8.1、示例代码
package com.yaqi.a01myexception;
public class ExceptionDemo12 {
public static void main(String[] args) {
/*
throws:写在方法定义处,表示声明一个异常。告诉调用者,使用本方法可能会有哪些异常。
throw :写在方法内,结束方法。手动抛出异常对象,交给调用者。方法中下面的代码不再执行了。
需求:
定义一个方法求数组的最大值
*/
int[] arr = null;
int max = 0;
try {
max = getMax(arr);
} catch (NullPointerException e) {
System.out.println("空指针异常");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("索引越界异常");
}
System.out.println(max);
}
public static int getMax(int[] arr)/* throws NullPointerException,ArrayIndexOutOfBoundsException*/{
if(arr == null){
//手动创建一个异常对象,并把这个异常交给方法的调用者处理
//此时方法就会结束,下面的代码不会再执行了
throw new NullPointerException();
}
if(arr.length == 0){
//手动创建一个异常对象,并把这个异常交给方法的调用者处理
//此时方法就会结束,下面的代码不会再执行了
throw new ArrayIndexOutOfBoundsException();
}
System.out.println("看看我执行了吗?");
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if(arr[i] > max){
max = arr[i];
}
}
return max;
}
}
8.2、小结
9、综合练习
异常
/**
* 设置
* @param name
*/
public void setName(String name) {
int len = name.length();
if(len<3||len>10){
throw new RuntimeException();
}
this.name = name;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
if(age<18||age>40){
throw new RuntimeException();
}
this.age = age;
}
package com.yaqi.test1;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
/*
需求:
键盘录入自己心仪的女朋友姓名和年龄。
姓名的长度在 3 - 10之间,
年龄的范围为 18 - 40岁,
超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
提示:
需要考虑用户在键盘录入时的所有情况。
比如:录入年龄时超出范围,录入年龄时录入了abc等情况
*/
//1.创建键盘录入对象
Scanner sc =new Scanner(System.in);
//2.创建女朋友对象
GirlFriend gf = new GirlFriend();
while (true) {
//3.接收女朋友姓名
try {
System.out.println("请输入你心仪的女朋友的名字");
String name = sc.nextLine();
gf.setName(name);
//4.接收女朋友的年龄
System.out.println("请输入你心仪的女朋友的年龄");
String ageStr = sc.nextLine();
int age = Integer.parseInt(ageStr);
gf.setAge(age);
//如果所有的数据都是正确的,那么跳出循环
break;
} catch (NumberFormatException e) {
System.out.println("年龄的格式有误,请输入数字");
//continue;
}catch(RuntimeException e){
System.out.println("姓名的长度或者年龄的范围有误");
//continue;
}
}
//5.打印
System.out.println(gf);
}
}
10、自定义异常
NameFormatException.java:
package com.yaqi.test2;
public class NameFormatException extends RuntimeException{
//技巧:
//NameFormat:当前异常的名字,表示姓名格式化问题
//Exception:表示当前类是一个异常类
//运行时:RuntimeException 核心 就表示由于参数错误而导致的问题
//编译时:Exception 核心 提醒程序员检查本地信息
public NameFormatException() {
}
public NameFormatException(String message) {
super(message);
}
}
AgeOutOfBoundsException.java:
package com.yaqi.test2;
public class AgeOutOfBoundsException extends RuntimeException{
public AgeOutOfBoundsException() {
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
Student类(部分代码):
/**
* 设置
* @param name
*/
public void setName(String name) {
int len = name.length();
if(len < 3 || len > 10){
throw new NameFormatException(name + "格式有误,长度应该为:3~10");
}
this.name = name;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
if(age < 18 || age > 40){
throw new AgeOutOfBoundsException(age + "超出了范围");
}
this.age = age;
}
测试类:
package com.yaqi.test2;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
/*
需求:
键盘录入自己心仪的女朋友姓名和年龄。
姓名的长度在 3 - 10之间,
年龄的范围为 18 - 40岁,
超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
提示:
需要考虑用户在键盘录入时的所有情况。
比如:录入年龄时超出范围,录入年龄时录入了abc等情况
*/
//1.创建键盘录入的对象
Scanner sc = new Scanner(System.in);
//2.创建女朋友的对象
GirlFriend gf = new GirlFriend();
while (true) {
//3.接收女朋友的姓名
try {
System.out.println("请输入你心仪的女朋友的名字");
String name = sc.nextLine();
gf.setName(name);
//4.接收女朋友的年龄
System.out.println("请输入你心仪的女朋友的年龄");
String ageStr = sc.nextLine();
int age = Integer.parseInt(ageStr);
gf.setAge(age);
//如果所有的数据都是正确的,那么跳出循环
break;
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (NameFormatException e) {
e.printStackTrace();
}catch (AgeOutOfBoundsException e) {
e.printStackTrace();
}
}
//5.打印
System.out.println(gf);
}
}
二、File
1、File的概述
- File对象就表示一个路径,可以是文件路径、也可以是文件夹路径
- 这个路径可以是存在的,也允许不存在的
1.1、路径
1.2、File常见的构造方法
1.2.1 根据文件路径创建文件对象
//1.根据字符串表示的路径,变成File对象
String str = "C:\\Users\\alienware\\Desktop\\a.txt";
File f1 = new File(str);
System.out.println(f1);//C:\Users\alienware\Desktop\a.txt
1.2.2根据父路径名字符串和子路径名字符串创建文件对象
//2.父级路径:C:\Users\alienware\Desktop
//子级路径:a.txt
String parent = "C:\\Users\\alienware\\Desktop";
String child = "a.txt";
File f2 = new File(parent,child);
System.out.println(f2);//C:\Users\alienware\Desktop\a.txt
在Java中 \ 表示转义字符,\\才能正确表示路径分隔符
File f3 = new File(parent + "\\" + child);
System.out.println(f3);//C:\Users\alienware\Desktop\a.txt
1.2.3根据父路径对应文件对象和子路径名字符串创建文件对象
//3.把一个File表示的路径和String表示路径进行拼接
File parent2 = new File("C:\\Users\\alienware\\Desktop");
String child2 = "a.txt";
File f4 = new File(parent2,child2);
System.out.println(f4);//C:\Users\alienware\Desktop\a.txt
1.3、小结
2、File的常见成员方法
2.1、创建、删除
delete方法默认只能删除文件和空文件夹,delete方法直接删除不走回收站
1.createNewFile() 创建一个新的空的文件,创建成功返回true
//1.createNewFile 创建一个新的空的文件
//细节1:如果当前路径表示的文件是不存在的,则创建成功,方法返回true
// 如果当前路径表示的文件是存在的,则创建失败,方法返回false
//细节2:如果父级路径是不存在的,那么方法会有异常IOException
//细节3:createNewFile方法创建的一定是文件,如果路径中不包含后缀名,则创建一个没有后缀的文件
File f1 = new File("D:\\aaa\\ddd");
boolean b = f1.createNewFile();
System.out.println(b);//true
2.mkdir make Directory,文件夹(目录)
//细节1:windows当中路径是唯一的,如果当前路径已经存在,则创建失败,返回false
//细节2:mkdir方法只能创建单级文件夹,无法创建多级文件夹。
File f2 = new File("D:\\aaa\\aaa\\bbb\\ccc");
boolean b = f2.mkdir();
System.out.println(b); //false
3.mkdirs 创建多级文件夹
//3.mkdirs 创建多级文件夹
//细节:既可以创建单级的,又可以创建多级的文件夹
File f3 = new File("D:\\aaa\\ggg");
boolean b = f3.mkdirs();
System.out.println(b);//true
4.delete() 删除文件、空文件夹
细节:
如果删除的是文件,则直接删除,不走回收站。
如果删除的是空文件夹,则直接删除,不走回收站
如果删除的是有内容的文件夹,则删除失败
//1.创建File对象
File f1 = new File("D:\\aaa\\eee");
//2.删除
boolean b = f1.delete();
System.out.println(b);
2.2、获取并遍历
listFIles() 获取当前路径下所有内容(重点掌握,其它了解)
listFiles()方法的细节:
listRoots() 获取系统中所有的盘符
list() 获取当前该路径下所有内容(仅仅能获取名字)
通过listFiles()实现文件过滤器的效果:
list(FilenameFilter filter) 利用文件名过滤器获取当前该路径下的所有内容
listFiles(FilenameFilter filter) 利用文件名过滤器获取当前该路径下的所有内容
2.3、判断、获取
代码示例:
//1.length 返回文件的大小(字节数量)
//细节1:这个方法只能获取文件的大小,单位是字节
//如果单位我们要是M,G,可以不断的除以1024
//细节2:这个方法无法获取文件夹的大小
//如果我们要获取一个文件夹的大小,需要把这个文件夹里面所有的文件大小都累加在一起。
package com.yaqi.a01myfile;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileDemo3 {
public static void main(String[] args) {
/*
public long length() 返回文件的大小(字节数量)
public String getAbsolutePath() 返回文件的绝对路径
public String getPath() 返回定义文件时使用的路径
public String getName() 返回文件的名称,带后缀
public long lastModified() 返回文件的最后修改时间(时间毫秒值)
*/
//1.length 返回文件的大小(字节数量)
//细节1:这个方法只能获取文件的大小,单位是字节
//如果单位我们要是M,G,可以不断的除以1024
//细节2:这个方法无法获取文件夹的大小
//如果我们要获取一个文件夹的大小,需要把这个文件夹里面所有的文件大小都累加在一起。
File f1 = new File("D:\\aaa\\a.txt");
long len = f1.length();
System.out.println(len);//12
File f2 = new File("D:\\aaa\\bbb");
long len2 = f2.length();
System.out.println(len2);//0
System.out.println("====================================");
//2.getAbsolutePath 返回文件的绝对路径
File f3 = new File("D:\\aaa\\a.txt");
String path1 = f3.getAbsolutePath();
System.out.println(path1);
File f4 = new File("myFile\\a.txt");
String path2 = f4.getAbsolutePath();
System.out.println(path2);
System.out.println("====================================");
//3.getPath 返回定义文件时使用的路径
File f5 = new File("D:\\aaa\\a.txt");
String path3 = f5.getPath();
System.out.println(path3);//D:\aaa\a.txt
File f6 = new File("myFile\\a.txt");
String path4 = f6.getPath();
System.out.println(path4);//myFile\a.txt
System.out.println("====================================");
//4.getName 获取名字
//细节1:
//a.txt:
// a 文件名
// txt 后缀名、扩展名
//细节2:
//文件夹:返回的就是文件夹的名字
File f7 = new File("D:\\aaa\\a.txt");
String name1 = f7.getName();
System.out.println(name1);
File f8 = new File("D:\\aaa\\bbb");
String name2 = f8.getName();
System.out.println(name2);//bbb
System.out.println("====================================");
//5.lastModified 返回文件的最后修改时间(时间毫秒值)
File f9 = new File("D:\\aaa\\a.txt");
long time = f9.lastModified();
System.out.println(time);//1667380952425
//如何把时间的毫秒值变成字符串表示的时间呢?
//课堂练习:
//yyyy年MM月dd日 HH:mm:ss
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date date = new Date(time);
System.out.println(sdf.format(date));//1970年01月01日 08:00:00
}
}
三、综合练习
1、File类相关的API练习题
1.1、在aaa文件夹中创建一个a.txt文件
import java.io.File;
import java.io.IOException;
public class Test1 {
public static void main(String[] args) throws IOException {
//需求:在当前模块下的aaa文件夹中创建一个a.txt文件
//1.创建a.txt的父级路径
File file = new File("myfile\\aaa");
//2.创建父级路径
//如果aaa是存在的,那么此时创建失败的。
//如果aaa是不存在的,那么此时创建成功的。
file.mkdirs();
//3.拼接父级路径和子级路径
File src = new File(file,"a.txt");
boolean b = src.createNewFile();
if(b){
System.out.println("创建成功");
}else{
System.out.println("创建失败");
}
}
}
1.2、找某一个文件夹中,是否有以avi结尾的电影(不考虑子文件夹)
package com.yaqi.a02test;
import java.io.File;
public class Test2 {
public static void main(String[] args) {
/*需求:
定义一个方法找某一个文件夹中,是否有以avi结尾的电影。
(暂时不需要考虑子文件夹)
*/
File file = new File("D:\\aaa\\bbb");
boolean b = haveAVI(file);
System.out.println(b);
}
/*
* 作用:用来找某一个文件夹中,是否有以avi结尾的电影
* 形参:要查找的文件夹
* 返回值:查找的结果 存在true 不存在false
* */
public static boolean haveAVI(File file){// D:\\aaa
//1.进入aaa文件夹,而且要获取里面所有的内容
File[] files = file.listFiles();
//2.遍历数组获取里面的每一个元素
for (File f : files) {
//f:依次表示aaa文件夹里面每一个文件或者文件夹的路径
if(f.isFile() && f.getName().endsWith(".avi")){
return true;
}
}
//3.如果循环结束之后还没有找到,直接返回false
return false;
}
}
1.3、找某一个文件夹中,是否有以avi结尾的电影(考虑子文件夹)
import java.io.File;
public class Test3 {
public static void main(String[] args) {
/* 需求:
找到电脑中所有以avi结尾的电影。(需要考虑子文件夹)
套路:
1,进入文件夹
2,遍历数组
3,判断
4,判断
*/
findAVI();
}
public static void findAVI(){
//获取本地所有的盘符
File[] arr = File.listRoots();
for (File f : arr) {
findAVI(f);
}
}
public static void findAVI(File src){//"C:\\
//1.进入文件夹src
File[] files = src.listFiles();
//2.遍历数组,依次得到src里面每一个文件或者文件夹
if(files != null){
for (File file : files) {
if(file.isFile()){
//3,判断,如果是文件,就可以执行题目的业务逻辑
String name = file.getName();
if(name.endsWith(".avi")){
System.out.println(file);
}
}else{
//4,判断,如果是文件夹,就可以递归
//细节:再次调用本方法的时候,参数一定要是src的次一级路径
findAVI(file);
}
}
}
}
}
1.4、删除一个多级文件夹
package com.yaqi.a02test;
import java.io.File;
public class Test4 {
public static void main(String[] args) {
/*
删除一个多级文件夹
如果我们要删除一个有内容的文件夹
1.先删除文件夹里面所有的内容
2.再删除自己
*/
File file = new File("D:\\aaa\\src");
delete(file);
}
/*
* 作用:删除src文件夹
* 参数:要删除的文件夹
* */
public static void delete(File src){
//1.先删除文件夹里面所有的内容
//进入src
File[] files = src.listFiles();
//遍历
for (File file : files) {
//判断,如果是文件,删除
if(file.isFile()){
file.delete();
}else {
//判断,如果是文件夹,就递归
delete(file);
}
}
//2.再删除自己
src.delete();
}
}
1.5、统计一个文件夹的总大小
package com.yaqi.a02test;
import java.io.File;
public class Test5 {
public static void main(String[] args) {
/*需求:
统计一个文件夹的总大小
*/
File file = new File("D:\\aaa\\src");
long len = getLen(file);
System.out.println(len);//4919189
}
/*
* 作用:
* 统计一个文件夹的总大小
* 参数:
* 表示要统计的那个文件夹
* 返回值:
* 统计之后的结果
*
* 文件夹的总大小:
* 说白了,文件夹里面所有文件的大小
* */
public static long getLen(File src){
//1.定义变量进行累加
long len = 0;
//2.进入src文件夹
File[] files = src.listFiles();
//3.遍历数组
for (File file : files) {
//4.判断
if(file.isFile()){
//我们就把当前文件的大小累加到len当中
len = len + file.length();
}else{
//判断,如果是文件夹就递归
len = len + getLen(file);
}
}
return len;
}
}
1.6、统计一个文件夹中每个文件的个数并打印
package com.yaqi.a02test;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test6 {
public static void main(String[] args) throws IOException {
/*
需求:统计一个文件夹中每种文件的个数并打印。(考虑子文件夹)
打印格式如下:
txt:3个
doc:4个
jpg:6个
*/
File file = new File("D:\\aaa\\src");
HashMap<String, Integer> hm = getCount(file);
System.out.println(hm);
}
/*
* 作用:
* 统计一个文件夹中每种文件的个数
* 参数:
* 要统计的那个文件夹
* 返回值:
* 用来统计map集合
* 键:后缀名 值:次数
*
* a.txt
* a.a.txt
* aaa(不需要统计的)
*
*
* */
public static HashMap<String,Integer> getCount(File src){
//1.定义集合用来统计
HashMap<String,Integer> hm = new HashMap<>();
//2.进入src文件夹
File[] files = src.listFiles();
//3.遍历数组
for (File file : files) {
//4.判断,如果是文件,统计
if(file.isFile()){
//a.txt
String name = file.getName();
String[] arr = name.split("\\.");
if(arr.length >= 2){
String endName = arr[arr.length - 1];
if(hm.containsKey(endName)){
//存在
int count = hm.get(endName);
count++;
hm.put(endName,count);
}else{
//不存在
hm.put(endName,1);
}
}
}else{
//5.判断,如果是文件夹,递归
//sonMap里面是子文件中每一种文件的个数
HashMap<String, Integer> sonMap = getCount(file);
//hm: txt=1 jpg=2 doc=3
//sonMap: txt=3 jpg=1
//遍历sonMap把里面的值累加到hm当中
Set<Map.Entry<String, Integer>> entries = sonMap.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
String key = entry.getKey();
int value = entry.getValue();
if(hm.containsKey(key)){
//存在
int count = hm.get(key);
count = count + value;
hm.put(key,count);
}else{
//不存在
hm.put(key,value);
}
}
}
}
return hm;
}
}