【JAVA教程】第四讲 Java的例外处理和I/O流

【Java】I/O 流篇 —— 字节 I/O 流 I/O流(Input/Output Stream)是计算机中数据传输的一种抽象概念,用于描述数据在程序和外部设备(如文件、网络、内存等)之间的流动方式。可以将它想象成一条“数据管道”,数据像水流一样在这条管道中连续传输。作用:I/O 流用于读写文件中的数据(可以是读写文件,或网络中的数据)。读(Read) → Input(输入)当程序从外部(如文件、键盘、网络等)获取数据时,称为“读”操作。例如:读取文件内容、接收用户键盘输入、获取网络数据等。这属于输入(Input) 阅读详情

4.1 什么是例外

  例外就是在程序的运行过程中所发生的异常事件,它中断指令的正常执行。Java中提供了一种独特的处理例外的机制,通过例外来处理程序设计中出现的错误。

4.1.1 例外示例

【例4-1】

     import java.io.*;
     class ExceptionDemo1{
      public static void main( String args[ ] ){
       FileInputStream fis = new FileInputStream( "text" );
       int b;
       while( (b=fis.read())!=-1 ){
        System.out.print( b );
       }
       fis.close( );
      }
     }

    查看编译结果

【例4-2】

     class ExceptionDemo2{
      public static void main( String args[ ] ){
       int a = 0;
       System.out.println( 5/a );
      }
     }

    运行结果

C:\>javac ExceptionDemo2.java
C:\>java ExceptionDemo2
  java.lang.ArithmeticException: / by zero at
  ExceptionDemo2.main(ExceptionDemo2.java:4)

  因为除数不能为0,所以在程序运行的时候出现了除0溢出的异常事件。为什么有的例外在编译时出现,而有的例外是在运行时出现的?让我们继续学习java 的例外处理机制。

4.1.2 例外处理机制

  抛弃(throw)例外:
  在Java程序的执行过程中,如果出现了异常事件,就会生成一个例外对象。生成的例外对象将传递给Java运行时系统,这一例外的产生和提交过程称为抛弃(throw)例外

 两种处理例外的机制:

  ◇ 捕获例外:
  当Java运行时系统得到一个例外对象时,它将会沿着方法的调用栈逐层回溯,寻找处理这一例外的代码。找到能够处理这种类型的例外的方法后,运行时系统把当前例外对象交给这个方法进行处理,这一过程称为捕获(catch)例外。这是积极的例外处理机制。如果Java运行时系统找不到可以捕获例外的方法,则运行时系统将终止,相应的Java程序也将退出。

  ◇ 声明抛弃例外:
  如果一个方法并不知道如何处理所出现的例外,则可在方法声明时,声明抛弃(throws)例外。这是一种消极的例外处理机制。

4.1.3 例外类的层次

  在jdk中,每个包中都定义了例外类,而所有的例外类都直接或间接地继承于Throwable类。图4-1为jdk中例外类的继承关系。

  java中的例外类可分为两大类:

  Error
 
  动态链接失败,虚拟机错误等,通常Java程序不应该捕获这类例外,也不会抛弃这种例外。

  Exception
  
  1)运行时例外: 
  继承于RuntimeException的类都属于运行时例外,例如算术例外(除零错)、数组下标越界例外等等。由于这些例外产生的位置是未知的,Java 编译器允许程序员在程序中不对它们做出处理。 

  2)非运行时例外: 
  除了运行时例外之外的其他由Exception 继承来的例外类都是非运行时的例外,例如FileNotFoundException(文件未找到例外)。Java编译器要求在程序中必须处理这种例外,捕获例外或者声明抛弃例外。

4.2 例外的处理

  java语言中有两种例外处理机制:捕获例外和声明抛弃例外。下面我们做详细介绍。

4.2.1 捕获例外

  
捕获例外是通过try-catch-finally语句实现的。

  try{
  ......
   }catch( ExceptionName1 e ){
   ......
   }catch( ExceptionName2 e ){
   ......
   }
   ......
   }finally{
   ......
  }

  ◇ try

  捕获例外的第一步是用try{…}选定捕获例外的范围,由try所限定的代码块中的语句在执行过程中可能会生成例外对象并抛弃。

  ◇ catch

  每个try代码块可以伴随一个或多个catch语句,用于处理try代码块中所生成的例外事件。catch语句只需要一个形式参数指明它所能够捕获的例外类型,这个类必须是Throwable的子类,运行时系统通过参数值把被抛弃的例外对象传递给catch块。

  在catch块中是对例外对象进行处理的代码,与访问其它对象一样,可以访问一个例外对象的变量或调用它的方法。getMessage( )是类Throwable所提供的方法,用来得到有关异常事件的信息,类Throwable还提供了方法printStackTrace( )用来跟踪异常事件发生时执行堆栈的内容。例如:

  try{
    ......
   }catch( FileNotFoundException e ){
    System.out.println( e );
    System.out.println( "message: "+e.getMessage() );
    e.printStackTrace( System.out );
   }catch( IOException e ){
    System.out.println( e );
   }

  catch 语句的顺序:
  捕获例外的顺序和catch语句的顺序有关,当捕获到一个例外时,剩下的catch语句就不再进行匹配。因此,在安排catch语句的顺序时,首先应该捕获最特殊的例外,然后再逐渐一般化。也就是一般先安排子类,再安排父类。


  ◇ finally

  捕获例外的最后一步是通过finally语句为例外处理提供一个统一的出口,使得在控制流转到程序的其它部分以前,能够对程序的状态作统一的管理。不论在try代码块中是否发生了异常事件,finally块中的语句都会被执行。

4.2.2 声明抛弃例外

 1.声明抛弃例外

  如果在一个方法中生成了一个例外,但是这一方法并不确切地知道该如何对这一异常事件进行处理,这时,一个方法就应该声明抛弃例外,使得例外对象可以从调用栈向后传播,直到有合适的方法捕获它为止。

  声明抛弃例外是在一个方法声明中的throws子句中指明的。例如:

  public int read () throws IOException{
        ......
  }

  throws子句中同时可以指明多个例外,之间由逗号隔开。例如: 

  public static void main(String args[]) throws 
  IOException,IndexOutOfBoundsException {…}


 2.抛出例外

  抛出例外就是产生例外对象的过程,首先要生成例外对象,例外或者由虚拟机生成,或者由某些类的实例生成,也可以在程序中生成。在方法中,抛出例外对象是通过throw语句实现的。

  例如:
  IOException e=new IOException();
  throw e ;

  可以抛出的例外必须是Throwable或其子类的实例。下面的语句在编译时将会产生语法错误:
  throw new String("want to throw");

4.3 自定义例外类的使用

  自定义例外类必须是Throwable的直接或间接子类。

  注意:一个方法所声明抛弃的例外是作为这个方法与外界交互的一部分而存在的。所以,方法的调用者必须了解这些例外,并确定如何正确的处理他们。

4.4 I/O 流概述

  输入/输出处理是程序设计中非常重要的一部分,比如从键盘读取数据、从文件中读取数据或向文件中写数据等等。

  Java把这些不同类型的输入、输出源抽象为流(stream),用统一接口来表示,从而使程序简单明了。

  Jdk 提供了包java.io,其中包括一系列的类来实现输入/输出处理。下面我们对java.io包的内容进行概要的介绍。


4.4.1 I/O流的层次

  1.字节流:

  从InputStream和OutputStream派生出来的一系列类。这类流以字节(byte)为基本处理单位。
  ◇ InputStream、OutputStream
  ◇ FileInputStream、FileOutputStream
  ◇ PipedInputStream、PipedOutputStream
  ◇ ByteArrayInputStream、ByteArrayOutputStream
  ◇ FilterInputStream、FilterOutputStream
  ◇ DataInputStream、DataOutputStream
  ◇ BufferedInputStream、BufferedOutputStream

 2.字符流:

  从Reader和Writer派生出的一系列类,这类流以16位的Unicode码表示的字符为基本处理单位。
  ◇ Reader、Writer
  ◇ InputStreamReader、OutputStreamWriter
  ◇ FileReader、FileWriter
  ◇ CharArrayReader、CharArrayWriter
  ◇ PipedReader、PipedWriter
  ◇ FilterReader、FilterWriter
  ◇ BufferedReader、BufferedWriter
  ◇ StringReader、StringWriter

 3.对象流

  ◇ ObjectInputStream、ObjectOutputStream

 4.其它

  ◇ 文件处理:
  File、RandomAccessFile;

  ◇ 接口
  DataInput、DataOutput、ObjectInput、ObjectOutput;

4.4.2 InputStream 和OutputStream

 1.InputStream

  ◇ 从流中读取数据:
  int read( ); //读取一个字节,返回值为所读的字节
  int read( byte b[ ] ); //读取多个字节,放置到字节数组b中,通常
              //读取的字节数量为b的长度,返回值为实际
              //读取的字节的数量

  int read( byte b[ ], int off, int len ); //读取len个字节,放置
                       //到以下标off开始字节
                       //数组b中,返回值为实
                       //际读取的字节的数量

  int available( );   //返回值为流中尚未读取的字节的数量
  long skip( long n ); //读指针跳过n个字节不读,返回值为实际
             //跳过的字节数量


  ◇ 关闭流:
  close( ); //流操作完毕后必须关闭
  
  ◇ 使用输入流中的标记:
  void mark( int readlimit ); //记录当前读指针所在位置,readlimit
                 //表示读指针读出
readlimit个字节后
                //所标记的指针位置才失效

  void reset( );     //把读指针重新指向用mark方法所记录的位置
  boolean markSupported( ); //当前的流是否支持读指针的记录功能

  有关每个方法的使用,详见java API。


 2.OutputStream

  ◇ 输出数据:
  void write( int b );   //往流中写一个字节b
  void write( byte b[ ] ); //往流中写一个字节数组b
  void write( byte b[ ], int off, int len ); //把字节数组b中从
              //下标off开始,长度为len的字节写入流中


  ◇ flush( )       //刷空输出流,并输出所有被缓存的字节
  由于某些流支持缓存功能,该方法将把缓存中所有内容强制输出到流中。

  ◇ 关闭流:
   close( );       //流操作完毕后必须关闭

4.4.3 I/O中的例外

  进行I/O操作时可能会产生I/O例外,属于非运行时例外,应该在程序中处理。如:FileNotFoundException, EOFException, IOException

4.5 文件处理

  I/O处理中,最常见的是对文件的操作,java.io包中有关文件处理的类有:File、FileInputStream、FileOutputStream、RamdomAccessFile和FileDescriptor;接口有:FilenameFilter。 

4.5.1 文件描述

  类File提供了一种与机器无关的方式来描述一个文件对象的属性。下面我们介绍类File中提供的各种方法。

 ◇ 文件或目录的生成

  public File(String path);/*如果path是实际存在的路径,则该File对象
    /*表示的是目录;如果path是文件名,则该File对象表示的是文件。*/

  public File(String path,String name);//path是路径名,name是文件名
  public File(File dir,String name);//dir是路径名,name是文件名

 ◇ 文件名的处理

  String getName( ); //得到一个文件的名称(不包括路径)
  String getPath( ); //得到一个文件的路径名
  String getAbsolutePath( );//得到一个文件的绝对路径名
  String getParent( ); //得到一个文件的上一级目录名
  String renameTo(File newName); //将当前文件名更名为给定文件的
                   完整路径

 ◇ 文件属性测试

  boolean exists( ); //测试当前File对象所指示的文件是否存在
  boolean canWrite( );//测试当前文件是否可写
  boolean canRead( );//测试当前文件是否可读
  boolean isFile( ); //测试当前文件是否是文件(不是目录)
  boolean isDirectory( ); //测试当前文件是否是目录

 ◇ 普通文件信息和工具

  long lastModified( );//得到文件最近一次修改的时间
  long length( ); //得到文件的长度,以字节为单位
  boolean delete( ); //删除当前文件

 ◇ 目录操作

  boolean mkdir( ); //根据当前对象生成一个由该对象指定的路径
  String list( ); //列出当前目录下的文件

 【例4-3】
  import java.io.*; //引入java.io包中所有的类
  public class FileFilterTest{
    public static void main(String args[]){
     File dir=new File("d://ex"); //用File 对象表示一个目录
     Filter filter=new Filter("java"); //生成一个名为java的过滤器
     System.out.println("list java files in directory "+dir);
     String files[]=dir.list(filter); //列出目录dir下,文件后缀名
                       为java的所有文件

     for(int i=0;i<files.length;i++){
      File f=new File(dir,files[i]); //为目录dir 下的文件或目录
                       创建一个File 对象

       if(f.isFile()) //如果该对象为后缀为java的文件,
                则打印文件名

        System.out.println("file "+f);
       else 
        System.out.println("sub directory "+f ); //如果是目录
                             则打印目录名

     }
    }
   }
   class Filter implements FilenameFilter{
    String extent;
    Filter(String extent){
     this.extent=extent;
    }
    public boolean accept(File dir,String name){
     return name.endsWith("."+extent); //返回文件的后缀名
    }
   }

4.5.2 文件的顺序处理

  类FileInputStream和FileOutputStream用来进行文件I/O处理,由它们所提供的方法可以打开本地主机上的文件,并进行顺序的读/写。例如,下列的语句段是顺序读取文件名为text的文件里的内容,并显示在控制台上面,直到文件结束为止。

  FileInputStream fis; 
   try{
    fis = new FileInputStream( "text" );
   System.out.print( "content of text is : ");
     int b;
     while( (b=fis.read())!=-1 ) //顺序读取文件text里的内容并赋值
                    给整型变量b,
直到文件结束为止。 
     {              
       System.out.print( (char)b );
     }
   }catch( FileNotFoundException e ){
   System.out.println( e );
   }catch( IOException e ){
   System.out.println( e );
   }

4.5.3 随机访问文件

  对于InputStream 和OutputStream 来说,它们的实例都是顺序访问流,也就是说,只能对文件进行顺序地读/写。随机访问文件则允许对文件内容进行随机读/写。在java中,类RandomAccessFile 提供了随机访问文件的方法。类RandomAccessFile的声明为:
public class RandomAccessFile extends Object implements DataInput, DataOutput

  接口DataInput 中定义的方法主要包括从流中读取基本类型的数据、读取一行数据、或者读取指定长度的字节数。如:readBoolean( )、readInt( )、readLine( )、readFully( ) 等。 

  接口DataOutput 中定义的方法主要是向流中写入基本类型的数据、或者写入一定长度的字节数组。如:writeChar( )、writeDouble( )、write( ) 等。 下面详细介绍RandomAccessFile类中的方法。

 ◇ 构造方法:
  RandomAccessFile(String name,String mode); //name是文件名,mode
          //是打开方式,例如"r"表示只读,"rw"表示可读写,"

  RandomAccessFile(File file,String mode); //file是文件对象

 ◇ 文件指针的操作
  long getFilePointer( ); //用于得到当前的文件指针
  void seek( long pos ); //用于移动文件指针到指定的位置
  int skipBytes( int n ); //使文件指针向前移动指定的n个字节

4.6 过滤流

  过滤流在读/写数据的同时可以对数据进行处理,它提供了同步机制,使得某一时刻只有一个线程可以访问一个I/O流,以防止多个线程同时对一个I/O流进行操作所带来的意想不到的结果。类FilterInputStream和FilterOutputStream分别作为所有过滤输入流和输出流的父类

  过滤流类层次:

          java.lang.Object
                |
                +----java.io.InputStream
                          |
                          +----java.io.FilterInputStream



  为了使用一个过滤流,必须首先把过滤流连接到某个输入/出流上,通常通过在构造方法的参数中指定所要连接的输入/出流来实现。例如:

  FilterInputStream( InputStream in );
  FilterOutputStream( OutputStream out );

4.6.1 几种常见的过滤流

  ◇ BufferedInputStream和BufferedOutputStream
    缓冲流,用于提高输入/输出处理的效率。

  ◇ DataInputStream 和 DataOutputStream
    不仅能读/写数据流,而且能读/写各种的java语言的基本类型,如:boolean,int,float等。

  ◇ LineNumberInputStream
    除了提供对输入处理的支持外,LineNumberInputStream可以记录当前的行号。

  ◇ PushbackInputStream
    提供了一个方法可以把刚读过的字节退回到输入流中,以便重新再读一遍。

  ◇ PrintStream
    打印流的作用是把Java语言的内构类型以其字符表示形式送到相应的输出流。

4.7 字符流的处理

  java中提供了处理以16位的Unicode码表示的字符流的类,即以Reader和Writer 为基类派生出的一系列类。

4.7.1 Reader和Writer

    这两个类是抽象类,只是提供了一系列用于字符流处理的接口,不能生成这两个类的实例,只能通过使用由它们派生出来的子类对象来处理字符流。

 1.Reader类是处理所有字符流输入类的父类。

  ◇ 读取字符 
  public int read() throws IOException; //读取一个字符,返回值为读取的字符
  public int read(char cbuf[]) throws IOException; /*读取一系列字符到数组cbuf[]中,返回值为实际读取的字符的数量*/
  public abstract int read(char cbuf[],int off,int len) throws IOException; 
  /*读取len个字符,从数组cbuf[]的下标off处开始存放,返回值为实际读取的字符数量,该方法必须由子类实现*/

  ◇ 标记流
  public boolean markSupported(); //判断当前流是否支持做标记
  public void mark(int readAheadLimit) throws IOException; 
   //给当前流作标记,最多支持readAheadLimit个字符的回溯。
  public void reset() throws IOException; //将当前流重置到做标记处

  ◇ 关闭流
  public abstract void close() throws IOException;

 2. Writer类是处理所有字符流输出类的父类。 

  ◇ 向输出流写入字符
  public void write(int c) throws IOException;
  //将整型值c的低16位写入输出流

  public void write(char cbuf[]) throws IOException;
  //将字符数组cbuf[]写入输出流

  public abstract void write(char cbuf[],int off,int len) throws IOException;
  //将字符数组cbuf[]中的从索引为off的位置处开始的len个字符写入输出流
  public void write(String str) throws IOException;
  //将字符串str中的字符写入输出流
  public void write(String str,int off,int len) throws IOException;
  //将字符串str 中从索引off开始处的len个字符写入输出流

  ◇ flush( )
  刷空输出流,并输出所有被缓存的字节。

  ◇ 关闭流
  public abstract void close() throws IOException;

4.7.2 InputStreamReader和OutputStreamWriter

  java.io包中用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介。

   ◇ 生成流对象
  public InputStreamReader(InputStream in); 
  /*in是字节流,而InputStreamReader是字符流,但是其来源是字节流in,
  因此InputStreamReader就可以把字节流in转换成字符流处理。/*


  public InputStreamReader(InputStream in,String enc) throws UnsupportedEncodingException;
  /*enc是编码方式,就是从字节流到字符流进行转换时所采用的编码方式,
   例如 ISO8859-1,UTF-8,UTF-16等等*/


  public OutputStreamWriter(OutputStream out);
  /*out是字节流,而OutputStreamReader是字符流 */

  public OutputStreamWriter(OutputStream out,String enc) throws UnsupportedEncodingException; //enc是编码方式

  InputStreamReader和OutputStreamWriter的方法:

  ◇ 读入和写出字符
  基本同Reader和Writer。

  ◇ 获取当前编码方式
  public String getEncoding();

  ◇ 关闭流
  public void close() throws IOException;

4.7.3 BufferedReader和BufferedWriter

 ◇ 生成流对象

  public BufferedReader(Reader in); //使用缺省的缓冲区大小
  public BufferedReader(Reader in, int sz); //sz为缓冲区的大小
  public BufferedWriter(Writer out);
  public BufferedWriter(Writer out, int sz);

 ◇ 读入/写出字符

  除了Reader和Writer中提供的基本的读写方法外,增加对整行字符的处理。
  public String readLine() throws IOException; //读一行字符
  public void newLine() throws IOException; //写一行字符

【例4-4】


  import java.io.*;
  public class NumberInput{
   public static void main(String args[]){
    try{
      InputStreamReader ir;
      BufferedReader in;
      ir=new InputStreamReader(System.in); 
      //从键盘接收了一个字符串的输入,并创建了一个字符输入流的对象
      in=new BufferedReader(ir);
      String s=in.readLine();
      //从输入流in中读入一行,并将读取的值赋值给字符串变量s
      System.out.println("Input value is: "+s);
      
int i = Integer.parseInt(s);//转换成int型
      i*=2;
      System.out.println("Input value changed after doubled: "+i);
    }catch(IOException e)
    {System.out.println(e);}
   }
  }

    运行结果

D:\>java NumberInput
123
Input value is 123
Input value changed after doubled: 246



  注意:在读取字符流时,如果不是来自于本地的,比如说来自于网络上某处的与本地编码方式不同的机器,那么我们在构造输入流时就不能简单地使用本地缺省的编码方式,否则读出的字符就不正确;为了正确地读出异种机上的字符,我们应该使用下述方式构造输入流对象:
  
    ir = new InputStreamReader(is, "8859_1");

  采用ISO 8859_1编码方式,这是一种映射到ASCII码的编码方式,可以在不同平台之间正确转换字符。

4.8 对象的串行化(Serialization)

4.8.1 串行化的定义

    1. 什么是串行化

  对象的寿命通常随着生成该对象的程序的终止而终止。有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复。我们把对象的这种能记录自己的状态以便将来再生的能力,叫做对象的持续性(persistence)。对象通过写出描述自己状态的数值来记录自己,这个过程叫对象的串行化(Serialization)。

   2. 串行化的目的

  串行化的目的是为java的运行环境提供一组特性,其主要任务是写出对象实例变量的数值。

4.8.2 串行化方法

  在java.io包中,接口Serializable用来作为实现对象串行化的工具,只有实现了Serializable的类的对象才可以被串行化。

 1. 定义一个可串行化对象

  public class Student implements Serializable{
    int id; //学号
    String name; //姓名
    int age; //年龄
    String department //系别
    public Student(int id,String name,int age,String department){
     this.id = id;
     this.name = name;
     this.age = age;
     this.department = department;
    }
  }

 2. 构造对象的输入/输出流

  要串行化一个对象,必须与一定的对象输入/输出流联系起来,通过对象输出流将对象状态保存下来,再通过对象输入流将对象状态恢复。

  java.io包中,提供了ObjectInputStream和ObjectOutputStream将数据流功能扩展至可读写对象。在ObjectInputStream中用readObject()方法可以直接读取一个对象,ObjectOutputStream中用writeObject()方法可以直接将对象保存到输出流中。

  Student stu=new Student(981036,"Liu Ming",18, "CSD");
  FileOutputStream fo=new FileOutputStream("data.ser");
  //保存对象的状态
  ObjectOutputStream so=new ObjectOutputStream(fo);
  try{
    so.writeObject(stu);
    so.close();
    }catch(IOException e )
      {System.out.println(e);}
  FileInputStream fi=new FileInputStream("data.ser");
  ObjectInputStream si=new ObjectInputStream(fi);
  //恢复对象的状态
  try{
    stu=(Student)si.readObject();
    si.close();
    }catch(IOException e )
  {System.out.println(e);}

  在这个例子中,我们首先定义一个类Student,实现了 Serializable接口,然后通过对象输出流的writeObject()方法将Student对象保存到文件data.ser中。之后,通过对象输入流的readObject()方法从文件data.ser中读出保存下来的Student对象。

4.8.3 串行化的注意事项

 1.串行化能保存的元素

  只能保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量,而且串行化保存的只是变量的值,对于变量的任何修饰符,都不能保存。

 2.transient关键字
 
  对于某些类型的对象,其状态是瞬时的,这样的对象是无法保存其状态的,例如一个Thread对象,或一个FileInputStream对象,对于这些字段,我们必须用transient关键字标明

 3. 定制串行化

  缺省的串行化机制,对象串行化首先写入类数据和类字段的信息,然后按照名称的上升排列顺序写入其数值。如果想自己明确地控制这些数值的写入顺序和写入种类,必须定义自己的读取数据流的方式。就是在类的定义中重写writeObject()和readObject()方法。

  例如可在4.8.2的例子中,加入重写的writeObject()和readObject()方法,对Student 类定制其串行化。

  private void writeObject(ObjectOutputStream out)throws IOException
  {
    out.writeInt(id);
    out.writeInt(age);
    out.writeUTF(name);
    out.writeUTF(department);
  }
  private void readObject(ObjectInputStream in)throws IOException
  {
    id=in.readInt();
    age=in.readInt();
    name=in.readUTF();
    department=in.readUTF();
  }

4.9 其它常用的流

4.9.1 管道流

  管道用来把一个程序、线程或代码块的输出连接到另一个程序、线程或代码块的输入 。
  
  管道输入流作为一个通信管道的接收端,管道输出流作为发送端。在使用管道之前,管道输出流和管道输入流必须进行连接。下面有两种连接的方法:

 1. 构造方法中连接

  PipedInputStream(PipedOutputStream src);
  PipedOutputStream(PipedInputStream snk);

 2. connect()方法进行连接

  类PipedInputStream中定义为:
  void connect(PipedOutputStream src);
  类PipedOutputStream中定义为:
  void connect(PipedInputStream snk);

4.9.2 内存的读/写

 1. ByteArrayInputStream和ByteArrayOutputStream 

  ByteArrayInputStream //从字节数组中读取以字节为单位的数据
  ByteArrayOutputStream //向字节数组中写入以字节为单位的数据

 2. StringBufferInputStream和StringBufferOutputStream 

  StringBufferInputStream 
  //从字符串缓冲区StringBuffer中读取以字符为单位的数据

  StringBufferOutputStream 
  //向字符串缓冲区StringBuffer中写入以字符为单位的数据

4.9.3 顺序输入流

  SequenceInputStream 把几个输入流顺序连接起来。顺序输入流提供了把若干不同的流统一为同一个流的功能,使得程序变得更加简洁。

【本讲小结】

  例外处理是java语言中一个独特之处,主要使用捕获例外和声明抛弃例外两种方法来处理程序中可能出现例外的语句块,其中捕获例外的方法是一种积极地处理例外的方法,而声明抛弃例外是一种消极的处理例外的方法。

  Java中的输入/输出处理是通过使用流技术,用统一的接口表示而实现的。输入/输出流中,最常见的是对文件的处理。Java语言中提供专门处理文件和目录的类,例如:java.io.File,java.io.FileInputStream,java.io.FileOutputStream,java.io.RandomAccessFile和接口java.io.FilenameFilter。输入/输出流根据处理的内容,分为字符流和字节流两种,其中字节流是以byte为基本处理单位的流;而字符流是以16位的Unicode码为处理单位的流。

Java的例外处理和IO流 Java的例外处理和IO流Java的例外处理和IO流Java的例外处理和IO流Java的例外处理和IO流Java的例外处理和IO流 立即下载

相关推荐

极路由 极1s J1S hc5661 刷padavan固件

极路由1S刷机指南 准备工作: 下载Breed不死固件 通过WinSCP上传或直接wget获取 执行mtd命令写入Breed 关键步骤: 进入Breed控制台(按住Reset键开机) 备份原厂固件和密钥 下载Padavan固件(RT-N14U-GPIO-12-xiaodu-ji1S-128M.trx) 刷机过程: 在Breed控制台更新固件 等待自动重启完成 初始设置: 管理地址:192.168.123.1 默认账号:admin/admin 无线名称:PCDN 无线密码:1234567890 注意事项:切勿

SimonLiu的博客 1302

JAVA教程 第四讲 Java的例外处理和I/O流

4.1 什么是例外  例外就是在程序的运行过程中所发生的异常事件,它中断指令的正常执行。Java中提供了一种独特的处理例外的机制,通过例外来处理程序设计中出现的错误。 4.1.1 例外示例 【例4-1】     import java.io.*;     class ExceptionDemo1{      public static void main( Strin...

weixin_34025051的博客 286

2026年5月典型AI应用落地

2026年5月AI应用全面进入商用化阶段,呈现三大特征:产业端深度渗透核心业务场景,如法律领域AI合同处理系统完成8500万元项目;消费端实现规模普及,京东618全场景AI化,智能家居产品涌现;基础设施层面运营商推出词元套餐降低使用门槛。政策法规与国际合作同步推进,日本通过首部AI专项法律,中国举办多场产业对接会。AI应用从技术验证转向实效产出,进入精算回报的成熟期。

AI_Encyc的博客 2630

java中的异常处理

异常的作用增强程序的健壮性。java中异常以什么形式存在?异常在java中以类的形式存在,每一个异常类都可以创建异常对象。JVM执行到某一处觉得有异常,会new异常对象,并且将new的异常对象抛出,打印输出信息到控制台了。如异常对应的现实生活火灾(异常类)2008年8月8日,小明家着火了(异常对象)2008年8月9日,小红家着火了(异常对象)异常体系结构注意所有异常都是在运行阶段发生的,因为只有程序运行阶段才可以new对象,因为异常的发生就是new异常对象。第一种方式。......

weixin_45581692的博客 1万+

告别玄学:手把手配置EtherCAT从站PDI接口与同步采样(含Sync/Latch信号实战)

本文详细解析了EtherCAT从站PDI接口配置与同步采样技术,涵盖微处理器通信与直接驱动IO模式选择、同步采样四大触发模式(SOF、Latch_in、Sync0/Sync1)及输出触发实战。通过伺服驱动器实例,帮助工程师突破配置难点,实现高精度同步控制,提升工业自动化系统性能。

weixin_30667649的博客 483

别再搞错了!ERA5-Land小时数据里的辐射值,原来不是你想的那个‘瞬时值’

本文深入解析ERA5-Land小时数据中辐射值的累积特性,揭示其与瞬时值的本质区别。通过详细的数据处理方法和Python代码示例,指导研究者正确转换累积辐射量为实用瞬时值,避免常见误区,提升气候模型验证的准确性。

weixin_28700411的博客 208

不同系统编码造成的诡异错误

作为码农,经常在不同操作系统间切换。Linux的文件一般为uft8无BOM格式,用换行符进行换行。Windows下vs的文件默认gb2312,用回车换行来换行。 最近碰到问题,linux(Ubuntu18)下运行正常,拿到vs2017下编译,出现两种情况: C4819警告:warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode ...

qq_31083701的博客 449

使用Python实现卷积神经网络(CNN)

卷积神经网络是一种专门用于处理具有网格状拓扑结构数据(如图像、声音)的深度学习模型。CNN的核心组件是卷积层和池化层,它们能够有效地从图像中提取特征并实现空间不变性,使得模型能够对图像中的物体进行识别和分类。我们定义一个简单的卷积神经网络模型,包括卷积层、池化层和全连接层。return x# 创建模型实例我们选择交叉熵损失函数作为分类任务的损失函数,并使用随机梯度下降(SGD)作为优化器。

Echo_Wish 4489

浅析Java Object Serialization与 Hadoop 序列化

浅析Java Object Serialization与 Hadoop 序列化

会飞的大象 2518

【硬件的单元测试 UT 3】PCIe 3.0及信号完整性测试方法

PCIe标准自从推出以来,1代和2代标准已经在PC和Server上逐渐普及,用于满足高速显卡、高速存储设备对于高速数据传输的要求。出于支持更高总线数据吞吐率的目的,PCI-SIG组织在2010年制定了PCIe 3.0,即PCIe 3代的规范,数据速率达到8Gbps。

qq_43416206的博客 1412

从数据读取到业务事件:理解 ABAP CDS 视图的目的与选型(含 RAP、扩展与分析场景)

CDS视图在SAP S/4HANA中不仅是数据查询工具,更是语义模型和运行时能力的载体。它通过分层架构(基础视图、组合视图、消费视图等)实现数据复用与场景适配,支持UI、分析、事务处理等多样化消费。视图类型包括提供数据访问的接口视图(I_前缀)、消费视图(C_前缀)和事务视图,以及不提供数据访问的扩展视图。这种分层设计确保了数据模型的稳定性与扩展性,同时支持自定义字段和上下文感知分析。正确理解CDS视图的用途和分层规则,能帮助开发者构建更健壮、可维护的SAP应用。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 302

《Java异常处理(超级详细)》

基本介绍: 异常处理就是当异常发生时,对异常处理的方式。 异常处理的方式: 1)try - catch - finally 程序员在代码中捕获发生的异常,自行处理。 2)throws 将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM。 main方法由JVM调用,main方法调用 f1 方法,f1 方法调用 f2 方法,如果 f2 方法发生异常,有两种方案,分别是 try-catch-finally 和 throws ,f2 使用 throws 方法,返回给 f1

m0_64318566的博客 9213

使用 MATLAB/Simulink 构建一个 基于神经网络控制的单相并网逆变器系统

单相并网逆变器广泛应用于户用光伏小型储能和电动汽车V2G等场景。其核心控制目标是实现高质量的并网电流,即电流与电网电压同频同相(单位功率因数),且总谐波畸变率 (THD)极低。非线性因素:电力电子器件的开关死区非线性电感寄生参数。参数不确定性:滤波器元件(L, C)的老化温漂。电网扰动:电压谐波频率波动不平衡。模型依赖性:PI、PR等控制依赖于精确的系统模型,模型失配导致性能下降。动态响应:在光照突变(光伏)或负载突变(储能)下,需快速、无超调地响应。

xiaoheshang_123的博客 274

java 例外_JAVA教程第四讲Java的例外处理和I/O流4.1

4.1 什么是例外例外就是在程序的运行过程中所发生的异常事件,它中断指令的正常执行。Java中提供了一种独特的处理例外的机制,通过例外来处理程序设计中出现的错误。4.1.1 例外示例【例4-1】import java.io.*;class ExceptionDemo1{public static void main( String args[ ] ){FileInputStream fis = n...

weixin_31967777的博客 230

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

第四讲 Java的例外处理和I/O流

【课前思考】  1. 什么是例外?Java中有哪两种例外处理机制?  2. 字节流和字符流的基类各是什么?  3. 什么是对象的串行化?对象串行化的作用是什么?难点:  1.如何使用Java中两种例外处理机制,抛弃例外和声明抛弃例外的区别与联系。  2.处理字符流时,其构造方法的参数是一个字节流。  3.对象串行化的概念。4.1 什么是例外4.1.2 例外处理机制抛弃(throw)例外

心蓝 4662

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Java之I/O流(最详细的I/O流总结)

I/O流I/O流1、定义2、分类2.1 字节流和字符流2.2 输入流和输出流2.3 节点流和处理流3、结构4、字节流4.1 定义4.2 说明4.3 字节流概述4.4 InputStream的常用方法4.5 OutputStream的常用方法5、字节流读写文件5.1 说明5.2 注意5.3 字节输入流——相关代码5.4 字节输出流——相关代码6、文件的拷贝6.1 需求6.2 分析6.3 注意6.4 快捷键6.5 相关代码7、字节流的缓冲区7. 相关代码8、字节缓冲流8.1 说明8.2 特点8.3 相关代码8.

熊凯瑞的博客 9141

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Java I/O流面试之道

NIO的出现在于提高IO的速度,它相比传统的输入/输出流速度更快。NIO通过管道Channel和缓冲器Buffer来处理数据,可以把管道当成一个矿藏,缓冲器就是矿藏里的卡车。程序通过管道里的缓冲器进行数据交互,而不直接处理数据。程序要么从缓冲器获取数据,要么输入数据到缓冲器。

JavaSouth南哥 1363

【Java】文件类 和 I/O流详解

什么是文件?文件是计算机中存储数据的一种方式,它可以用来保存各种类型的信息,如文本、图像、音频和视频等。文件通常由文件名和扩展名组成,扩展名(后缀名)表示文件的类型或格式。在Windows系统中不同的文件后缀通常代表着不同的文件类型和默认打开方式,如 docx为WPS中word文档的后缀,jpg或png为常见的图片文件后缀,exe通过代表一个可执行程序等;但是Unix、Linux等操作系统上则没有这样精确的分类。文件的分类:文件总体上可以分为文本文件(ASCII码文件)和二进制文件。

一直往前走。 1793

Java的例外处理和I/O流

原文:http://blog.csdn.net/coolriver/article/details/100692 【课前思考】   1. 什么是例外?Java中有哪两种例外处理机制?   2. 字节流和字符流的基类各是什么?   3. 什么是对象的串行化?对象

zhujing244的专栏 733

【Java】深入了解Java I/O 流

I/O 流是用于处理输入和输出数据的机制,它是数据在程序和外部源之间传输的通道。Java中的I/O流分为两类:字节流和字符流。Java I/O流提供了灵活且强大的机制,使得我们可以轻松处理各种输入和输出需求。无论是字节流还是字符流,在不同的场景中都有各自的优势。通过学习和运用这些I/O流,你可以更好地处理文件、网络数据等实际编程任务。希望本文对你深入理解Java I/O流有所帮助。

double222222的博客 1556

Java基础——I/O流

流是一种抽象的概念,它代表了数据的有序传输。就像水流一样,数据从一个源(如文件、网络连接)流向一个目标(如内存、另一个文件)。在Java中,流可以看作是一系列的数据序列,程序可以从流中读取数据(输入流),也可以向流中写入数据(输出流)。Java的I/O流提供了丰富的类和方法,用于处理各种数据传输需求。通过合理选择字节流、字符流、处理流和对象流,可以高效地完成文件读写、网络通信等任务。在使用I/O流时,要注意资源的正确关闭,避免资源泄漏。同时,要根据具体的应用场景选择合适的流类型,以提高程序的性能和可维护性。

jukuya的博客 995

Java I/O流详解

Java I/O流 1、Java I/O流概述 IO就是输入、输出。Java IO类库基于抽象基础类InputStream和OutputStream构建了一套I/O体系,主要解决从数据源读入数据和将数据写入到目的端的问题。我们可以将数据源和目的地理解为IO流的两端。 从一种数据源中通过InputStream流对象读入数据到程序内存中流程如图 1-1所示; 从程序内存中通过OutputStream流对象写入到目的地的流程图如图 1-2所示。 图 1-1 图 1-2 然后,除了面向字节流的InputSt

Window_mouse的博客 1万+

【关于Java的 I/O 流】

《Java I/O流核心指南》摘要: Java I/O流是程序与外界交换数据的通道,分为字节流(处理二进制)和字符流(处理文本)。关键要点:1)字节流使用InputStream/OutputStream,字符流用Reader/Writer;2)必须使用缓冲流(BufferedXXX)提升性能;3)推荐try-with-resources自动关闭资源;4)文本处理需显式指定编码(如UTF-8);5)对象序列化用ObjectStream。NIO适用于高并发场景,传统项目推荐Buffered包装+正确编码处理。

weixin_64178283的博客 1057

Java语言基础(九)Java I/O 流

本篇文章主要介绍了 Java 中的 I/O ,其中最重要的是 I/O 流的概念,然后举例说明了一些常用的输入输出操作,包括控制台、文件和网络中的数据输入输出。

青何 3184

Java I/O流概述

在Java编程中,I/O流是一种用于在程序和外部数据源之间传输数据的机制。这些外部数据源可以是文件、网络连接、内存中的数据等。I/O流以字节或字符的形式操作数据,具体取决于您的需求。缓冲流用于提高I/O性能。它们在内部维护了一个缓冲区,可以一次性读取或写入多个字节或字符,减少了磁盘或网络访问的次数,从而提高了效率。通过本文,我们深入研究了Java中的I/O流。我们介绍了字节流和字符流的基本概念,讨论了缓冲流的性能提升,以及如何处理异常和管理资源。

学IT,找陈寒 6834

Java 输入与输出(I/O)流之装饰流【处理流】

按照Java 输入与输出(I/O)流的处理功能:I/O流可分为低级的节点流和高级的装饰流(又称处理流)。 - 节点流是直接从数据源(数据源可以是文件、数组、内存或网络)读/写数据的输入输出流; - 装饰流(又称处理流),是指用于对一个已存在的输入输出流进行装饰的流,装饰流在不改变数据信息的情况下添加额外的增强功能。因为装饰流不会直接连接到实际的数据源,不能够直接获取数据,所以构建一个装饰流时,需要在构造函数中传入一个节点流。装饰流可进行多层嵌套装饰。

weixin_42369079的博客 1043
上一篇: 【JAVA教程】第三讲 Java语言中的面向对象特性
下一篇: 【JAVA教程】第五讲 AWT图形用户界面设计
IT总舵主
博客等级 码龄14年 14粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值