一、异常
即程序中一些程序处理不了的特殊情况
Exception 能被程序本身处理( try-catch ), Error 是无法处理的(只能尽量避免)。
1、异常类 Exception
见过的异常 NullPointerException ArrayIndexoutOfBoundException等
String str=null;
System.out.println(str.length());//NullPointerException异常
String name="张三";
boolean bool=str.equals(name);//NullPointerException异常
System.out.println(bool);
int i=12;
int a=0;
System.out.println(i/a);//ArithmeticException异常
2、异常的分类
当程序中出现异常,就会中断程序,代码不会继续运行
(1)检查型异常(编译异常)
在编译时就会抛出的异常(代码上会报错),需要在代码中编写处理方式 (和程序之外的资源访问) 直接继承Exception
File file=new File("D:\\easy.text");
//检查性异常 编译异常
FileInputStream fis=new FileInputStream(file);//FileNotFoundException
(2) 运行时异常
在代码运行时可能会出现的异常,可以不用明文处理,而通过代码避免异常的发生 继承RunTimeException
String str=null;
//System.out.println(str.length());//NullPointerException异常
if(str!=null){
System.out.println(str.length());
}else{
System.out.println("str是null值");
}
String name="张三";
//boolean bool=str.equals(name);//NullPointerException异常
boolean bool=name.equals(str);
System.out.println(bool);
int i=12;
int a=0;
//System.out.println(i/a);//ArithmeticException异常
if(a!=0){
System.out.println(i/a);
}else {
System.out.println("a==0不能做除数");
}
3、处理异常
try...catch...finally
File file=new File("D:\\easy.text");
//检查型异常 编译异常
//FileInputStream fis=new FileInputStream(file);//FileNotFoundException
FileInputStream fis=null;
try{
//try块尝试捕捉异常 其中是可能会抛出异常的代码
fis=new FileInputStream(file);
//fis.close();
}catch (FileNotFoundException e){
//捕捉到异常后要处理的代码
e.printStackTrace();//打印异常日志
}finally {
//无论是否出现异常都会执行的代码块
//一般用在关闭资源
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4、处理多种异常
(1)try处理
try {
System.out.println(12/0);
Object strA="";
System.out.println((Integer)strA);
fis=new FileInputStream(file);
}catch (ArithmeticException e){
//出现ArithmeticException要执行的代码
System.out.println("出现ArithmeticException");
}catch (ClassCastException e){
System.out.println("出现ClassCastException");
}catch (FileNotFoundException e){
System.out.println("出现FileNotFoundException");
}finally {
if (fis!=null){
try {
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
(2)合并处理方案 一个catch块捕捉多种异常
使用 | 声明多种异常
try {
System.out.println(12/0);
Object strA="";
System.out.println((Integer)strA);
fis=new FileInputStream(file);
}catch (ArithmeticException | ClassCastException | FileNotFoundException e){
}
(3)catch块声明父类异常,捕捉所有子类异常
try {
System.out.println(12/0);
Object strA="";
System.out.println((Integer)strA);
fis=new FileInputStream(file);
}catch (Exception e){
}
5、catch 异常捕捉的顺序
子类异常优先处理,父类异常后置处理
try{
List list=new ArrayList();
list.remove(8);//Indexout
int[] arr=new int[2];
arr[8]=22;//ArrayIndex
String strA="abc";
strA.charAt(8);//StringIndex
}catch (ArrayIndexOutOfBoundsException e){
}catch (StringIndexOutOfBoundsException e){
}catch (IndexOutOfBoundsException e){
e.printStackTrace();
}
6、注意
如果catch块抛出了异常,没有finally就会中断程序
执行try 或者catch中的return语句之后,在返回之前,如果有finally,就会运行finally,如果finally中有return语句,那么程序就按finally中return,所以finally中的return是一定会被return的
public class EasyException {
public static void main(String[] args) {
System.out.println(test());//3
}
public static int test(){
try{
System.out.println(12/0);
return 1;
}catch (Exception e){
return 2;
}finally {
//System.out.println(12/0);
return 3;
}
//只返回最后一次执行的返回值
//若finally中没有return 且try中有异常,那么返回catch中的return
//若finally中没有return 且try中没有异常,那么返回try中的return
}
}
try不能单独编写 必须有其他语句块
try块中没有检查性异常,不能在catch块中随意捕捉
try...catch
public static void testA(){
try{
System.out.println(12/0);
}catch (Exception e){
}
}
try...finally
public static void testA(){
File file=null;
FileInputStream fis=null;
try{
System.out.println(12/0);
//不能出现检查型异常 该类异常必须用catch捕捉
//fis=new FileInputStream(file);
}finally {
}
}
7、自定义异常
//自定义一个检查型异常 是Exception的直接子类
class StudentNameIsNullException extends Exception{
public StudentNameIsNullException(){}
public StudentNameIsNullException(String msg){
super((msg));
}
}
8、throws、throw
throws 声明方法可能要抛出哪种异常 声明抛出多个异常(用','连接) throw 在方法体中抛出一个具体的异常对象 没有解决异常,只是抛给使用这段代码的人
运行时异常不用必须声明要抛出哪种异常 检查型异常则不行
public void infoA(){
if(name==null){
throw new NullPointerException("name is null");
//throw new RuntimeException(".....");
//throw new Exception();
}
}
方法重写:子类对父类中继承过来的方法进行重新定义 约束: 返回值类型 方法名 参数列表不能变 访问权限只能更开放 抛出的异常只能更精确 范围应该更小,不能扩大(指检查型异常)
class BigStudent extends Student{
@Override
public void info() throws StudentNameIsNullException {
}
}
class Student{
String name;
public void info() throws StudentNameIsNullException,NullPointerException{
//name==null是一个特殊情况 不符合业务需求
if(name==null){
throw new StudentNameIsNullException("Student name is null");
}
System.out.println("我的名字是"+name);
}
}
二、File 文件类
java中对文件的处理 java.io包
1、定义File类
File f=new File("D:\\easy.txt");
2、常用方法
(1)判断是否存在该文件 exists()
boolean bool=f.exists();
System.out.println(bool);
(2)创建文件 createNewFile()
if(!bool){
try{
bool=f.createNewFile();
if(bool){
System.out.println("成功创建文件");
}
}catch (IOException e){
e.printStackTrace();
}
}
(3)创建文件夹
//创建时路径完整
f.mkdir();
//创建时路径不需要完整 会自己补全
f.mkdirs();
(4)获取是否是文件
bool=f.isFile();
System.out.println(bool);
(5)是否是文件夹
bool=f.isDirectory();
System.out.println(bool);
(6)获取文件的大小
f=new File("");
long len=f.length();
System.out.println(len);
(7)文件存在时删除文件
if(bool){{
//删除文件夹时,文件夹必须是空的文件夹
bool=f.delete();
System.out.println("成功删除文件"+bool);
}
注:删除文件夹时,文件夹必须是空的文件夹
三、IO 输入输出流
流动的是数据 数据的形式是二进制
1、分类
根据流动的方向不同 输入流和输出流 根据流动的介质(单位)不同 字符流和字节流 字符流只能读取文本 .txt .xml .html .yml .properties 字节流可以读取所有的文件类型 根据功能(作用)不同 节点流和工具流 打印流 数据流 对象流
//字节输入流
InputStream is;
//字节输出流
OutputStream os;
//字符输入
Reader r;
//字符输出
Writer w;
2、读取 写出
(1)读取
public static void readFile(){
FileInputStream fis=null;
try{
fis=new FileInputStream("D:\\easy.txt");
byte[] arr=new byte[12];
//读取多少就转换多少
int length=0;
while((length=fis.read(arr))!=-1){
//arr 中就是读到的数据
String str=new String(arr,0,length);
System.out.print(str);
// String.valueOf(arr);
}
}catch (IOException e){
e.printStackTrace();
}finally {
if(fis!=null){
try{
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
(2)写出
public static void writeFile(){
String str="埃弗拉看看发货了覅发记得你说过拉法基的阿凡达发生过阿斯弗而奋";
byte[] arr=str.getBytes();
FileOutputStream fos=null;
try{
//覆盖不加第二个参数,追加第二个参数置为true
fos=new FileOutputStream("D:\\easy.txt",true);
fos.write(arr);
}catch (IOException e){
e.printStackTrace();
}finally {
if(fos!=null){
try{
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
默认为覆盖式写出,若要改为追加式可在定义输出流时将第二个参数置为true
3、缓冲流
public static void readFileBuffer(){
//文件字节输入流
FileInputStream fis=null;
//工具流
//转换流 字节流转换成字符流
InputStreamReader isr=null;
//缓冲流
BufferedReader br=null;
try{
fis=new FileInputStream("D:\\easy.txt");
isr=new InputStreamReader(fis);
br=new BufferedReader(isr);
String line=br.readLine();
System.out.println(line);
}catch (IOException e){
e.printStackTrace();
}finally {
if(fis!=null){
try{
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
是工具流的一种,当使用BufferedReader
读取数据时,它会从底层流中读取一定数量的数据到内部缓冲区中进行暂时的保存,当读入到特定字符(如:\t \r)后一起发出
4、序列化与反序列化
(1)序列化
将内存对象转换成序列(流),叫做序列化
这个对象必须是可序列化的 即实现Serializable接口
public static void wirteObject(){
Staff staff=new Staff();
staff.name="张三";
staff.sex="男";
staff.salary=3500;
ObjectOutputStream oos=null;
FileOutputStream fos=null;
try{
fos=new FileOutputStream("D:\\easy.txt");
oos=new ObjectOutputStream(fos);
oos.writeObject(staff);
}catch (IOException e){
e.printStackTrace();
}finally {
if(fos!=null){
try{
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
if(oos!=null){
try{
oos.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
对应的类:
public class Staff implements Serializable {
String name;
String sex;
int salary;
@Override
public String toString() {
return "Staff{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", salary=" + salary +
'}';
}
}
(2)反序列化
将对象序列读入程序, 转换成对象的方式:反序列化
反序列化会创建新的对象
public static void readObject(){
FileInputStream fis=null;
ObjectInputStream ois=null;
try{
fis=new FileInputStream("D:\\easy.txt");
ois=new ObjectInputStream(fis);
Object obj=ois.readObject();
System.out.println(obj);
}catch (Exception e){
e.printStackTrace();
}finally {
if(fis!=null){
try{
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
if(ois!=null){
try{
ois.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
(3)序列化版本控制 transient关键词
对于序列化对象,它的属性也必须是可序列化的,除非该属性是transient修饰的
serialVersionUID 是一个类的序列化版本号 如果该量没有定义,jdk会自动给与一个版本号,当该类发生变化时 该序列化版本号会发生变化,反序列化就会失败 自定义该版本号,只要该版本号不发生变化,即使类中属性/方法改变 该类的对象依旧可以反序列化反序列化的对象是一个新的对象
private static final long serialVersionUID=1L;
private transient String sex;
transient修饰属性 作用: 禁止属性的值被序列化
当一个类的属性中有一个是不可序列化的类型或者不想被序列化时,可以使用transient禁止其序列化
(4)输出流的flash方法
强制将缓冲区中的数据写出到目的地。 在某些情况下,缓冲区中的数据并不会自动写出到目的地, 而是需要显式地调用 flush 方法来实现。 在关闭输出流之前,通常会调用 flush 方法来确保所有待处理的数据都被写出到目的地。 大流套小流 大流执行了flush(),其嵌套的小流会自动执行flush()flush()虽然只对缓冲流有作用,但习惯上,所有的输出流在关闭前都会调用 flush()
public static void writeStudent(Student stu){
FileOutputStream fos=null;
ObjectOutputStream oos=null;
File file=new File("D:\\student.data");
if(!file.exists()){
try{
file.createNewFile();
}catch (IOException e){
e.printStackTrace();
}
}
try{
fos=new FileOutputStream(file);
oos=new ObjectOutputStream(fos);
oos.writeObject(stu);
oos.flush();
//强制将缓冲区中的数据写出到目的地。
// 在某些情况下,缓冲区中的数据并不会自动写出到目的地,
// 而是需要显式地调用 flush 方法来实现。
//在关闭输出流之前,通常会调用 flush 方法来确保所有待处理的数据都被写出到目的地。
//大流套小流 大流执行了flush(),其嵌套的小流会自动执行flush()
}catch (IOException e){
e.printStackTrace();
}finally {
if(oos!=null){
try{
oos.close();
}catch (IOException e){
e.printStackTrace();
}
}
if(fos!=null){
try{
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
补充总结:
创建对象的方法 1 new 2 克隆 3 反序列化 4 反射