文章目录
Java_异常机制
基本概念
- 异常就是"不正常"的含义,在Java语言中主要指程序执行中发生的不正常情况。
- java.lang.Throwable类是Java语言中错误(Error)和异常(Exception)的超类。
- 其中Error类主要用于描述Java虚拟机无法解决的严重错误,通常无法编码解决,如:JVM挂掉了等。
- 其中Exception类主要用于描述因编程错误或偶然外在因素导致的轻微错误,通常可以编码解决,如:0作为除数等。
- 语法错误和逻辑错误,这两种情况,不属于异常
- 有些异常时因为用户错误引起的,有的使用程序错误引起的,还有的是因为物理错误引起的,异常发生的原因有输入了非法数据,打开的不存在的文件,网络通信时连接中断,JVM内存溢出等
异常的分类
Exception
类是Throwable
类的子类。除了Exception
类外,Throwable还有一个子类Error 。
- Java不捕获错误,错误在Java的程序处理的范畴之外,
Error
用来指示运行时环境发生的错误:例如,JVM 内存溢出。一般地,程序不会从错误中恢复。
- java.lang.Exception类是所有异常的超类,主要分为以下两种:
- RuntimeException - 运行时异常,也叫作非检测性异常
- IOException和其它异常 - 其它异常,也叫作检测性异常,所谓检测性异常就是指在编译阶段都能被编译器检测出来的异常。
- 其中RuntimeException类的主要子类:
- ArithmeticException类 - 算术异常
- ArrayIndexOutOfBoundsException类 - 数组下标越界异常
- NullPointerException - 空指针异常
- ClassCastException - 类型转换异常
- NumberFormatException - 数字格式异常
- 当程序执行过程中发生异常但又没有手动处理时,则由Java虚拟机采用默认方式处理异常,而默认处理方式就是:打印异常的名称、异常发生的原因、异常发生的位置以及终止程序。
- Java采用的异常处理机制,是将异常处理的程序代码集中在一起,与正常的程序代码分开
异常处理的两种方式:try-catch-finally
和 throws + 异常类型
**
异常的捕获
语法格式
try {
编写可能发生异常的代码;
}
catch(异常类型 引用变量名) {
编写针对该类异常的处理代码;
}
...
finally {
编写无论是否发生异常都要执行的代码;
}
注意事项
a.当需要编写多个catch分支时,切记小类型应该放在大类型的前面;
b.懒人的写法:
catch(Exception e) {}
c. finally通常用于进行善后处理,如:关闭已经打开的文件等。
- 通过
e.getMessage()
获取异常信息,返回字符串 e.printStackTrace()
获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
package com.company;
public class IndexOutExp {
public static void main(String[] args) {
String friends[] = { "lisa", "bily", "kessy" };
try {
for (int i = 0; i < 5; i++) {
System.out.println(friends[i]);
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("index err");
} finally {
System.out.println("finally err");
}
System.out.println("\nthis is the end");
}
}
IOException异常处理
package com.company;
import java.io.FileInputStream;
import java.io.IOException;
public class Java_IOExp {
public static void main(String[] args) {
try {
FileInputStream in = new FileInputStream("atguigushk.txt");
int b;
b = in.read();
while (b != -1) {
System.out.print((char) b);
b = in.read();
}
in.close();
} catch (IOException e) {
System.out.println(e);
} finally {
System.out.println(" It’s ok!");
}
}
}
异常的抛出
-
在某些特殊情况下有些异常不能处理或者不便于处理时,就可以将该异常转移给该方法的调用者,这种方法就叫异常的抛出。当方法执行时出现异常,则底层生成一个异常类对象抛出,此时异常代码后续的代码就不再执行。
-
语法格式
访问权限 返回值类型 方法名称(形参列表) throws 异常类型1,异常类型2,...{ 方法体; } 如: public void show() throws IOException{}
-
方法重写的原则
a.要求方法名相同、参数列表相同以及返回值类型相同,从jdk1.5开始支持返回子类类型; b.要求方法的访问权限不能变小,可以相同或者变大; c.要求方法不能抛出更大的异常; 注意:子类重写的方法不能抛出更大的异常、不能抛出平级不一样的异常,但可以抛出一样的异常、更小的异常以及不抛出异常。
-
若父类中被重写的方法没有抛出异常时,则子类中重写的方法只能进行异常的捕获处理。
-
若一个方法内部又以递进方式分别调用了好几个其它方法,则建议这些方法内可以使用抛出的方法处理到最后一层进行捕获方式处理。
异常对象的生成:
- 第一种生成方式:由虚拟机自动生成:程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象并抛出——自动抛出
- 第二种生成方式:由开发人员手动创建:
Exception exception = newClassCastException()
;——创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样
抛出RemoteExcepption异常
import java.io.*;
public class className {
public void deposit(double amount) throws RemoteException {
// Method implementation
throw new RemoteException();
}
//Remainder of class definition
}
- 如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
- 在方法声明中用
throws
语句可以声明抛出异常的列表,throws
后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。
声明抛出异常:
package com.company;
import java.io.FileInputStream;
import java.io.IOException;
public class ThrowTest {
public static void main(String[] args) {
ThrowTest t = new ThrowTest();
try {
t.readFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFile() throws IOException {
FileInputStream in = new FileInputStream("Java.txt");
int b;
b = in.read();
while (b != -1) {
System.out.print((char) b);
b = in.read();
}
in.close();
}
}
重写方法声明抛出异常的原则:
- 重写方法不能抛出比被重写方法范围更大的异常类型。在多态的情况下,对
methodA()
方法的调用-异常的捕获按父类声明的异常处理。
自定义异常
-
当需要在程序中表达年龄不合理的情况时,而Java官方又没有提供这种针对性的异常,此时就需要程序员自定义异常加以描述。
-
用户自定义异常类都是
RuntimeException
的子类,并且需要编写几个重载的构造器。 -
自定义的异常通过throw抛出,并且自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型。
-
实现流程
a.自定义xxxException异常类继承Exception类或者其子类。 b.提供两个版本的构造方法,一个是无参构造方法,另外一个是字符串作为参数的构造方法。
-
异常的产生:
throw new 异常类型(实参); 如: throw new AgeException("年龄不合理!!!");
用户自定义异常类MyException,用于描述数据取值范围错误信息。用户自己的异常类必须继承现有的异常类。
package com.company;
class MyException extends Exception {
static final long serialVersionUID = 13465653435L;
private int idnumber;
public MyException(String message, int id) {
super(message);
this.idnumber = id;
}
public int getId() {
return idnumber;
}
}
public class MyExpTest {
public void regist(int num) throws MyException {
if (num < 0)
throw new MyException("人数为负值,不合理", 3);
else
System.out.println("登记人数" + num);
}
public void manager() {
try {
regist(-30);
} catch (MyException e) {
System.out.print("登记失败,出错种类" + e.getId());
}
System.out.print("本次登记操作结束");
}
public static void main(String args[]) {
MyExpTest t = new MyExpTest();
t.manager();
}
}
Java_File类
- java.io.File类主要用于描述文件或目录路径的抽象表示信息,可以获取文件或目录的特征信息,如:大小等。
File对象 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身
。如果需要访问文件内容本身,则需要使用输入/输出流。- 在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。
File对象
可以作为参数传递给流的构造器
常用的方法
方法声明 | 功能概述 |
---|---|
File(String pathname) | 根据参数指定的路径名来构造对象,可以是绝对路径或者相对路径,如果pathname 是相对路径,则默认的当前路径在系统属性user.dir 中存储。 |
File(String parent, String child) | 根据参数指定的父路径和子路径信息构造对象 |
File(File parent, String child) | 根据参数指定的父抽象路径和子路径信息构造对象 |
boolean exists() | 测试此抽象路径名表示的文件或目录是否存在 |
String getName() | 用于获取文件的名称 |
long length() | 返回由此抽象路径名表示的文件的长度 |
long lastModified() | 用于获取文件的最后一次修改时间 |
String getAbsolutePath() | 用于获取绝对路径信息 |
boolean delete() | 用于删除文件,当删除目录时要求是空目录 |
boolean createNewFile() | 用于创建新的空文件 |
boolean mkdir() | 用于创建目录 |
boolean mkdirs() | 用于创建多级目录 |
File[] listFiles() | 获取该目录下的所有内容 |
boolean isFile() | 判断是否为文件 |
boolean isDirectory() | 判断是否为目录 |
File[] listFiles(FileFilter filter) | 获取目录下满足筛选器的所有内容 |
String workingDir = System.getProperty("user.dir");
:通过读取user.dir系统属性
来获取JVM
的当前工作目录System.setProperty("user.dir", "C:\\myDir");
:使用System.setProperty()
方法更改当前工作目录。- File判断文件存在
import java.io.File; public class Main { public static void main(String[] argv) { // Create a File object File dummyFile = new File("dummy.txt"); // Check for the file"s existence boolean fileExists = dummyFile.exists(); if (fileExists) { System.out.println("The dummy.txt file exists."); } else { System.out.println("The dummy.txt file does not exist."); // 输出结果The dummy.txt file does not exist } } }
路径
-
绝对路径在文件系统上唯一标识文件。规范路径是唯一标识文件系统上文件的最简单路径
-
使用
getAbsolutePath()
分别获得由File对象
表示的绝对路径 -
使用
getCanonicalPath()
方法来获取File对象
表示的规范路径。import java.io.File; import java.io.IOException; public class Main { public static void main(String[] args) { printFilePath("dummy.txt"); printFilePath(".." + File.separator + "notes.txt"); } public static void printFilePath(String pathname) { File f = new File(pathname); System.out.println("File Name: " + f.getName()); System.out.println("File exists: " + f.exists()); System.out.println("Absolute Path: " + f.getAbsolutePath()); try { System.out.println("Canonical Path: " + f.getCanonicalPath()); } catch (IOException e) { e.printStackTrace(); } } }
文件操作
- 使用
File类的createNewFile()
方法创建一个新文件:File dummyFile = new File("test.txt");boolean fileCreated = dummyFile.createNewFile();
如果文件已成功创建,则返回true;否则,返回false。如果发生I/O错误,该方法将抛出IOException。
createNewFile()
方法创建一个新的空文件,如果有指定名称的文件不存在。
创建文件夹:
- 使用
mkdir()或mkdirs()
方法创建一个新目录。 - 可以在默认的临时文件目录或目录中创建一个临时文件,使用
File类的createTempFile()
静态方法,该方法接受前缀和后缀以生成临时文件名。File tempFile = File.createTempFile("abc", ".txt");
File newDir = new File("C:\\users\\home")
;仅当路径名中指定的父目录已存在时,mkdir()
方法才创建目录。只有当C:\users
目录已经存在时,newDir.mkdir()
方法才会创建主目录。
删除文件:
- 使用
File类的delete()
方法来删除文件/目录。 - 目录必须为空,我们才能删除它。
- 如果文件/目录被删除,
File类的delete()
方法返回true; 否则,返回false。 - 可以延迟删除文件,直到JVM通过使用
deleteOnExit()
方法终止。 - 在程序中创建临时文件,当程序退出时要删除,这将非常有用。
立即删除dummy.txt文件
File dummyFile = new File("dummy.txt");
dummyFile.delete();
在JVM终止时删除dummy.txt文件
File dummyFile = new File("dummy.txt");
dummyFile.deleteOnExit();
文件重命名:
-
要重命名文件,可以使用
renameTo()
方法,renameTo()
使用一个File对象来表示新文件:
boolean fileRenamed = oldFile.renameTo(newFile);
-
下例中的文件命名已经存在了,所以,
renameTo()
方法返回false。
import java.io.File;
public class Main {
public static void main(String[] argv) {
// Rename old-dummy.txt to new_dummy.txt
File oldFile = new File("old_dummy.txt");
File newFile = new File("new_dummy.txt");
boolean fileRenamed = oldFile.renameTo(newFile);
if (fileRenamed) {
System.out.println(oldFile + " renamed to " + newFile);
} else {
System.out.println("Renaming " + oldFile + " to " + newFile
+ " failed."); // 输出结果
}
}
}
文件属性:
- File类包含让我们获取/设置文件和目录的属性的方法。
- 可以设置分别使用
setReadOnly(),setReadable(),setWritable()和setExecutable()
方法将文件设置为只读,可读,可写和可执行。
- 使用
lastModified()和setLastModified()
方法来获取和设置文件的最后修改日期和时间。 - 使用
isHidden()
方法检查文件是否被隐藏。
文件大小:
- 使用File类的length()方法获取文件的大小(以字节为单位)。
File myFile = new File("myfile.txt");
long fileLength = myFile.length();
- 如果File对象表示不存在的文件,则
length()
方法返回零。 length()
方法的返回类型是long,而不是int。
查看文件和目录:
- 使用File类的listRoots()静态方法获取文件系统中可用根目录的列表。 它返回一个File对象数组
File[] roots = File.listRoots();
- 使用
File类的list()或listFiles()
方法列出目录中的所有文件和目录。list()方法返回一个String
数组,而listFiles()方法返回一个File
数组。
文件过滤器
- 要从列表中排除扩展名为.SYS的所有文件,可以使用由功能接口FileFilter的实例表示的文件过滤器来实现。它包含一个
accept()
方法,它将File
作为参数列出,如果应该列出文件,则返回true。
返回false
不会列出文件。
创建一个文件过滤器,将过滤扩展名为.SYS的文件。
FileFilter filter = file -> {
if (file.isFile()) {
String fileName = file.getName().toLowerCase();
if (fileName.endsWith(".sys")) {
return false;
}
}
return true;
};