JavaSE | 11-异常和File

异常

Throwable(所有异常/错误的根类)
|
├─ Error(系统级致命错误,程序无法恢复)
│  ├─ OutOfMemoryError(内存溢出,如创建超大对象/无限集合)
│  └─ StackOverflowError(栈溢出,如无限递归调用)
└─ Exception(程序可处理的异常)运行时异常+编译时异常
   |
   ├─ RuntimeException(运行时异常/非检查型,编译器不强制捕获)
   |  |
   │  ├─ NullPointerException(空指针,调用null对象的方法/属性)
   │  ├─ IndexOutOfBoundsException(下标越界,如数组/集合下标超出范围)
   │  ├─ ClassCastException(类型转换异常,如String强转Integer)
   │  ├─ IllegalArgumentException(参数非法,如传入不符合规则的参数)
   │  └─ ArithmeticException(算术异常,如整数除以0)
   |
   └─ CheckedException(检查型异常,编译器强制捕获/声明抛出)
	  |
      ├─ IOException(IO操作异常)
      │  └─ FileNotFoundException(文件未找到,如读取不存在的文件)
      ├─ SQLException(数据库操作异常,如SQL语法错误/连接失败)
      └─ InterruptedException(线程中断异常,如休眠线程被打断)

捕获异常try-catch

	int[] arr = {1,2,3};  
	try{  
		//程序创建异常,与catch()中的异常对比,可捕获 -> 执行catch{..}
		//当catch{..}执行完毕,继续向下执行
	    System.out.println(arr[10]);     
	}catch (ArrayIndexOutOfBoundsException e){  
	    System.out.println("数组越界了");  
	}  
	System.out.println("执行!");

常见问题

如果try中没有遇到问题,怎么办?

会把try中的所有代码全部执行完毕,不会执行catch中的代码

注意: 只有出现了异常,才会执行catch

如果try中可能遇到多个问题,怎么办?

写多个catch与之对应

注意: 如果捕获多个异常,父类一定要写在下面

JDK7以后,可以用catch捕获多个异常,中间用|隔开

如果try中遇到的问题没有被捕获,怎么办?

JVM虚拟机默认处理异常,会停止程序

如果try中遇到了问题,那么try下面的其他代码块还会执行吗?

不会执行 ,会直接跳转到对应的catch

常用方法

方法名返回值作用
e.getMessage()String简报:只告诉你最简单的错误原因(如 “By zero”)。
e.toString()String中报:异常类型 + 错误原因(如 java.lang.ArithmeticException: / by zero
e.printStackTrace()void详报:在控制台打印完整的堆栈信息,最常用

抛出处理

关键字位置作用后面跟什么
throws方法声明处向上抛异常类名(可以跟多个)
throw方法体内制造异常异常对象(只能跟一个)
  • 运行时异常不需要throws声明

自定义异常

  • 定义异常类
  • 写继承关系
  • 空参构造
  • 带参构造
类型继承 Exception(检查型)继承 RuntimeException(非检查型)
强制要求必须用 try-catch 捕获,或声明 throws无需强制捕获,按需处理
适用场景必须处理的严重业务异常(比如文件读写失败)普通业务异常(比如余额不足、用户不存在)
代码复杂度高(到处加 try-catch)低(只在需要处理的地方捕获)

File

常用方法

类别方法名返回值核心功能备注
获取getName()String获取文件或文件夹名称带后缀名(如 a.txt
length()long获取文件大小,文件夹为0单位是字节 (Byte),UTF-8一个汉字三个字节
lastModified()long最后修改时间毫秒值,需转换日期
路径getPath()String获取构造时传入的路径怎么 new的就给什么
getAbsolutePath()String获取绝对路径从盘符开始的全路径
判断exists()boolean路径是否存在最常用,防报错必备
isFile()boolean是否为文件路径不存在则返回 false
isDirectory()boolean是否为文件夹路径不存在则返回 false
创建createNewFile()boolean创建新文件文件夹不存在会创建失败
mkdirs()boolean递归创建文件夹建议永远用带 s 的这个
删除delete()boolean删除文件/空文件夹不走回收站,直接消失

综合练习: 统计各种文件的数量


    /**
     * 递归方法:统计指定目录下所有文件的后缀名数量(包含子目录)
     * @param src 要统计的目标目录File对象
     * @return 后缀名-数量的HashMap,键为后缀名/无后缀,值为对应数量
     */
public static HashMap<String,Integer> getCount(File src){
	HashMap<String,Integer>hm = new HashMap<>();
	File[] fs = src.listFiles();
	// 判空:避免目录为空/无访问权限导致空指针
	
	if (fs != null) {
		for (File f : fs) {
			if (f.isFile()) {
				// 按"."分割文件名,用于提取后缀名(注意转义符\\.)
				String[] split = f.getName().split("\\.");
				
				// 分割后长度>=2说明有后缀名(如test.txt分割后是[test,txt])
				if(split.length >= 2){
					// 取分割数组最后一个元素作为后缀名
					String endName = split[split.length-1];
					
					if(!hm.containsKey(endName))
						hm.put(endName,1);
					else
						hm.put(endName,hm.get(endName)+1);

				}else{
					// 分割后长度<2说明无后缀名(如readme、.gitignore)
					// 首次统计"无后缀":初始化为1
					
					if(!hm.containsKey("无后缀"))
						hm.put("无后缀",1);
					else
						hm.put("无后缀",hm.get("无后缀")+1);
				}
			}else{
				// 当前File是子目录:递归调用getCount统计子目录的后缀名
				HashMap<String,Integer> dfs = getCount(f);
				// 遍历子目录的统计结果,合并到当前目录的HashMap中
				
				for (String k : dfs.keySet()){
					// 当前目录未统计过该后缀:直接赋值子目录的统计数
					if(!hm.containsKey(k))
						hm.put(k,dfs.get(k));
					// 当前目录已统计过该后缀:累加子目录的统计数
					else
						hm.put(k,hm.get(k)+dfs.get(k));
				}

			}
		}

	}
	// 返回当前目录(含子目录)的最终统计结果
	return hm;
}
今日访问 ... 次 | 今日访客 ... 人 | 本页阅读 ...
小站已萌萌哒运行了 0 0 0
已累计耕耘 16 篇博文 · 共 42.69k 个字
总访问量 ...