黑马程序员14——异常、IO流1

来源:互联网 发布:linux登陆时间 编辑:程序博客网 时间:2024/06/05 19:05

------- android培训、java培训、期待与您交流! ----------


1. 异常概述

  什么是异常:异常就是程序在运行中出现的不正常的现象
  写的案例 /0案例
  程序出现了异常,而且异常一旦发生,后面的程序不在执行了
  Java中,任何事物,都是对象,异常这个事物也不例外,Java就将异常这个事物进行了对象的封装
  就有对于对象的描述的类


2. Java中的异常继承体系
  Java中的异常有一个顶层的类
  java.lang.Throwable 是所有错误和异常的超类
     Error类  错误
     Exception类  异常
       RuntimeException 运行时期异常
  
  错误:是程序中比较严重的问题,不修改代码,程序不能运行  -- 非典 艾滋  癌
  异常:是程序中比较轻微的问题,处理掉异常后,程序可以继续运行 -- 感冒,阑尾炎


  Throwable顶层类的方法
    构造方法Throwable(String message) 参数,异常信息
    String toString()返回此 throwable 的简短描述。对异常的信息,简短的描述
    String getMessage() 对异常的信息的详细描述
    void printStackTrace()throwable 及其追踪输出至标准错误流。将异常信息通过IO流直接输出控制台
    推荐使用,信息最多,最全 JVM 也默认调用这个方法,输出异常信息


    sop(getMessage)
    printStackTrace()


3. 异常处理的第一种方式  try  catch处理
  标准写法格式
    try{
       写可能出现异常的代码
       检查异常
    }catch(异常类  变量){
      异常的处理方式
      比如,输出异常信息,调用方法,循环,判断
    }


4. 异常处理的第二种方式 抛出异常
  通过一个案例,演示抛出异常


  通过方法之间的调用来实现的
  方法内部,手动抛出异常对象,新的关键字 throw  异常对象
  在方法声明上,抛给调用者的异常,新的关键字 throws 异常类


  throw 用于写在方法内部 后面是异常对象 new XXXException()
  throws 用于在方法的声明上,声明我这个方法有异常,调用者需要处理  后面的是异常类 XXXException


  如果不是最终调用者,可以继续是用throws在方法声明上抛出异常
  如果是最终的调用者,选择try...catch处理掉异常


6. 编译时期异常,运行时期异常
  编译时期异常:
    调用了一个抛出异常的方法,不处理,出现编译失败
  
  运行时期异常:
    Exception--RuntimeException
    凡是RuntimeException下的所有子类,都属于运行时期异常
    空指针,越界异常,类型转换异常
  
  运行时异常的特点:
    程序如果出现运行时期异常,那么程序人员,必须修改代码,从新运行
    这类异常,在程序中,是不允许发生的,一旦发生,修改源码
    运行时期异常,一旦发送,后面的程序没有在运行的意义了


    如果程序中抛出的异常,是运行时异常,方法声明上,不需要写throws
    调用者,不需要try..catch处理


    小结:
      如果用户乱传递参数,导致程序后面再计算已经没有意义了,直接抛出运行时异常


7. finally 代码块
  格式 
     try{
     
     }catch(Exception e){
     
     }finally{
       这里的代码,必须执行
     }


     try{


     }finally{
     
     }
    finally用于释放资源使用
    IO流,读写文件,但是IO没有这个本事
    调用Windows功能,读写文件


    数据库,。Java连接,一旦连接上,数据库资源网络资源都被占用
    Java程序操作数据库,无论操作成功还是失败,作用finally必须释放资源


    public static boolean a(){
        boolean b = true;
        try{
b = false;
}catch(Exception e){

}finally{
 //  return true;
 sop()
}
return b;
    }
 如果finally写return,肯定返回finally中的内容
 如果finally没有写return,也会执行finally,执行完毕后,返回try中执行return


8. 自定义异常
  Java程序中,经常出现的异常,进行了对象的封装
  比如:
    越界异常  抛出 XXXXOutOfBoundsException
    空指针    抛出 NullPointerException
  
  当我们程序发生了问题,但是这个问题没有封装的异常类,自定义异常


  定义自己的异常
    定义类,类的名字后缀必须是Exception,继承Exception,或者继承RuntimeException
    将异常的描述信息(by zero) 通过参数方式传递给父类的构造方法, super
    throw 抛出定义的异常


  如果定义的异常是运行时异常,不需要throws 也不需要try..catch处理


9. 子类父类中的异常
 前提是,子类继承父类,重写父类方法后
   如果父类中的方法,抛出了异常
   子类重写后,异常怎么办,子类可以抛,可以不抛
   如果子类抛出异常,子类抛出的异常,不能大于父类抛出的异常


   如果父类方法,不抛异常
   子类冲写后,能否抛异常,父类不抛,子类不能抛
   如果子类调用了一个抛出异常的方法,子类只能选择try  catch处理异常


=========================================================================


10. IO概述
  IO流用来处理设备之间的数据传输
  流技术,将数据从一个设备,传递到另一个设备的技术,流技术
  IO流,数据的操作,读Input  写Output


  流按操作数据分为两种:字节流与字符流
  字符流:专门处理文本文件,文本数据
    特点是,查询本机默认编码表 GBK
    开发这个流对象的意义,在于方便操作文本文件
    一次操作16个二进制位
  
  字节流:处理任意文件,不会查编码表
    一次操作8个二进制位


  流按流向分为:输入流,输出流。
    输入流,读取数据,读文件,读取互联网数据
    输出流,写入数据,向硬盘写文件,向互联网发送数据


11. IO的继承体系
   字符流
     字符输出流:抽象基类 java.io.Writer
       Writer 方法
         write()字符数组,字符数组一部分,单个字符,字符串


     字符输入流: 抽象基类 java.io.Reader
       Reader 方法
         read()字符数,字符数组一部分,单个字符
   


   字节流
     字节输出流:抽象基类 java.io.OutputStream
     字节输入流:抽象基类 java.io.InputStream


12. 字符输出流Writer
  找到了子类FileWriter,写文本文件
  构造方法,传递一个字符串的文件名
  调用write方法写数据
  字符输出流,写文本数据的时候,流会将数据写到内存中,没有到目的文件
  调用另一个方法,刷新,将内存中的数据,刷到目的文件
  字符流写数据,必须刷新
  如果字符流刷新了,数据必走向目的地


  字符流写文件。创建文件,必须依靠Windows底层功能,使用完毕后
  必须释放Windows资源


  close()关闭流对象,关闭之间先刷新
  close(){
    flush();
  }


  异常处理,在IO流中很重要


  文件的续写:
  FileWriter构造方法中,字符串的文件名,布尔值
  写true,追加写入

==============================================

1. 字符流的输出,写文件

  字符输出流的最高父类Writer
  write写的方法,字符数组,字符串,单个字符,数组一部分
  flush刷新 ,close关闭资源
  写的数据很多,write一次,flush一次
  资源的释放,必须要做close方法,finally中,单独对close写try catch 健壮性的判空


  FileWriter,创建对象的时候,构造方法中直接写字符串的文件名
  会创建一个文件出来,如果文件存在,覆盖源文件
  调用父类方法,写,刷新,关闭


  实现文件的追加写入,FileWriter的构造方法中,传递一个true参数,就可以实现文件续写




2. 字符输入流,读文件Reader
  读取单个字符
     int read()
  读取字符数组
     int read(char[] ch)
  读取字符数组一部分
     int read(char[] ch,int offset,int length)


   
   read方法,每次只读取一个字符,每执行一次read方法,自动的向后读
   读取到文件末尾,返回-1


   找到子类FileReader
   构造方法,传递字符串文件名


   int read(char[] ch)
   read方法中的数组,JVM读取文件时候,读取到的字符装在数组中
   read方法返回值,如果返回-1,文件结束了
   返回值,结构是每次读取的时候,字符数组中装的有效字符个数


   char[] ch = new char[长度]多少合适
   一个文本文件,1kb  5MB可能


   数组的长度,一般写1024的倍数
   char[1024] = short
   byte[1024]  = 1KB


   1024b = 1kb = 102k =1mb  1024mb =1gb  1024gb=1tb


3. 字符流赋值文本文件
  将一源文件c:\\demo.txt  数据源  Reader
  复制到d:\\demo.txt  数据目的  Writer


  读取数据源,数据源中的数据写到目的地中


  第一种复制方式,读一个字符,写一个字符
     建立2个流对象,读取源 ,写目的


  第二种复制方式,读一个字符数组,写一个字符数组


4. 字符流的缓冲区对象
  字符流的缓冲区,提高字符流读写效率
  字符输出流的缓冲区对象
   BufferedWriter
  
  缓冲区的构造方法(Writer out) 传递一个Writer的子类
  目前为止可以传递的子类只有一个FileWriter


  BufferedWriter目的是为了提高流的操作效率,提高哪一个流呢,这个流对象作为参数传递进来


  new BufferedWriter(new FileWriter)缓冲区,对传递的FileWriter这个对象进行高效操作


  void newLine()写一个换行


  可以在写数据的时候,加上\r\n换行符号
  调用缓冲区的newLine()方法,也可以换行


  日后开发选择newLine()方法,这个方法具有跨平台功能
  如果安装JVM是Windows版本,newLine()方法中写的就是\r\n


  如果安装JVM是Linux版本,newLine()方法中写的就是\n
  推荐使用newLine写换行


  字符输入流的缓冲区对象,提高字符输入的读取效率
  BufferedReader
  构造方法BufferedReader(Reader in) 
  创建BufferedReader类的对象的时候,传递一个字符输入流对象
  目前未知,能传递的只有一个字符输入流对象 FileReader


  new BufferedReader(new FileReader)


  String readLine()读取文本一行,返回一个新的字符串
  如果读取文件结尾 readLine()返回  null


  使用readLine()读取了一行,记事本中,每行的结尾换行符号\r\n
  readLine()方法 返回String的时候,包含这个\r\n吗,没有换行符号


5. 字符流的缓冲区对象复制文本文件
  原始流对象FileReader,FileWriter
  缓冲区对象BufferedWriter,BufferedReader
  读一行,写一行,写换行,刷一行


  如果以后遇到复制文件的案例,采用读写数组的方式,可以采用读写行的方式

字符流复制文件三种方式:

package cn.itcast.iostream;/* * 采用字符流,复制文本文件 * 读一个字符,写一个字符 */import java.io.*;public class CopyText {public static void main(String[] args) {long start = System.currentTimeMillis();//创建2个流对象,读取数据远的Reader,写目的的WriterFileReader fr = null;FileWriter fw = null;try{fr = new FileReader("c:\\demo.txt");fw = new FileWriter("d:\\demo.txt");int len = 0 ;while((len = fr.read())!=-1){fw.write(len);fw.flush();}}catch(IOException e){e.printStackTrace();throw new RuntimeException("复制失败");}finally{try{if(fw!=null)fw.close();}catch(IOException e){throw new RuntimeException("读取源文件关闭资源失败");}finally{try{ if(fr!=null) fr.close();}catch(IOException e){throw new RuntimeException("写入目的文件关闭资源失败");}}}long end = System.currentTimeMillis();System.out.println(end - start);}}

package cn.itcast.iostream;/* * 字符流复制文本文件 * 读一个数组,写一个数组 * 字符数组 * 案例很重要!! */import java.io.*;public class CopyText2 {public static void main(String[] args) {long start = System.currentTimeMillis();FileWriter fw = null;FileReader fr = null;try{fw = new FileWriter("d:\\demo.txt");fr = new FileReader("c:\\demo.txt");char[] cbuf = new char[1024];int len = 0 ;while((len = fr.read(cbuf))!=-1){fw.write(cbuf, 0, len);fw.flush();}}catch(IOException e){e.printStackTrace();throw new RuntimeException("文件复制失败");}finally{try{if(fr!=null){fr.close();}}catch(IOException e){throw new RuntimeException("读取源文件关闭资源失败");}finally{try{if(fw!=null)fw.close();}catch(IOException e){throw new RuntimeException("写入目的文件关闭资源失败");}}}long end = System.currentTimeMillis();System.out.println(end - start);}}

package cn.itcast.iostream;/* * 字符流的缓冲去复制文本文件 * 读一行,写一行 */import java.io.*;public class CopyText3 {public static void main(String[] args) {//创建2个对象,定义变量BufferedReader bfr = null;BufferedWriter bfw = null;try{bfr = new BufferedReader(new FileReader("c:\\a.html"));bfw = new BufferedWriter(new FileWriter("d:\\a.html"));//读一行,写一行,写换行,刷新String line = null;while((line = bfr.readLine())!=null){bfw.write(line);bfw.newLine();bfw.flush();}}catch(IOException e){e.printStackTrace();throw new RuntimeException("文件复制失败");}finally{try{if(bfw!=null)bfw.close();}catch(IOException e){throw new RuntimeException("文件写入关闭失败");}finally{try{if(bfr!=null)bfr.close();}catch(IOException e){throw new RuntimeException("文件读取关闭失败");}}}}}





6. 装饰设计模式
  IO的体系中,大量的用到了装饰设计模式
  BufferReader 字符输入流的缓冲区对象
  提高字符输入流的效率的,如果没有字符输入流,缓冲区也不会存在


  FileReader --  家里面的地面
  BufferedReader -- 地板
  地板铺在地面上的


  地面的作用是承重的,加上地板以后,承重的功能没有改变,但是由于有了这个地板,
  对我们的地面增加了功能,人可以在上面睡觉了


  地面原始功能
  地板--装饰材料,地板出现的目的,是为了增强地面的功能而已,没有地面也就没有地板


  BufferedReader出现,就是为了增强原有FileReader的功能,添加了一行的功能


  BufferedReader就是FileReader的装饰类




  使用装饰类,提高原有对象的功能
  不是用装饰类,也可以提高原有对象的功能 ,继承覆盖方法
  class Person{
    void eat(){}
  }


  class Person2 extends Person
  {
    void eat(){}
  }


  class BufferedPerson{
    private Person p;
    BufferedPerson(Person){this.p=p;}
    public void newEat(){
       p.eat();
    }
  }


  继承父类,重写方法,也可以增强原有功能
  装饰设计模式,也可以增强原有功能
  问:区别,哪个办法更加灵活实用呢


  继承是OOP三大特征之一
  设计模式为了解决实际中的问题,出现的解决办法




  一切设计模式,基石都是OOP思想


  下面有一个IO的继承体系很多类,继承和覆盖的方式增强,再次使用装饰模式增强


 继承,重写方法,进行功能的增强
  Reader
    |-- ReaderText
      |-- ReaderTextExtends extends ReaderText
    |-- ReaderMP3
      |-- ReaderMP3Extends extends ReaderMP3
    |-- ReaderVideo
      |-- ReaderVideoExtends extends ReaderVideo
    |-- ReaderGame
      |-- ReaderGameExtends extends ReaderGame
    |-- ReaderNet
      |-- ReaderNetExtends extends ReaderNet
  以上继承结构,类太多了,显得很复杂,很臃肿,对于开发者来讲,使用起来很复杂,不方便应用
  对于学习者来讲,学习难度加大




  下面采用装饰的设计模式,实现整个读取继承体系的增强
  Reader
    |-- ReaderText
    |-- ReaderMP3
    |-- ReaderVideo
    |-- ReaderGame
    |-- ReaderNet
    |-- BufferedReader(Reader r) extends Reader


  
  定义一个装饰类
    BefferdReader
  你想要装饰谁,就把谁专递进来,我就可以增强你的功能


  好处,简化了原有的继承体系,使用这个体系简单,一目了然,降低了开发成本,降低了学习成本
  继承的方式,体系庞大臃肿
  装饰省本级模式,继承体系简单易懂


7. 自定义装饰类,增强原有流对象功能
  自己写一个类,实现BufferedReader中的readLine功能


  BufferedReader(new FileReader){
       FileReader.read();
       读取到一行,将一行作为String返回
       read()==-1
       发回null
  }
0 0
原创粉丝点击