适配器模式深入.doc_第1页
适配器模式深入.doc_第2页
适配器模式深入.doc_第3页
适配器模式深入.doc_第4页
适配器模式深入.doc_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

结构型模式,顾名思义讨论的是类和对象的结构,它采用继承机制来组合接口或实现,或者通过组合一些对象,从而实现新的功能。GoF23种设计模式中的结构型模式有7种,分别是适配器模式(Adapter)、装饰器模式(Decorator)、代理模式(Proxy)、外观模式(Facade)、桥接模式(Bridge)、组合模式(Composite)、享元模式(Flyweight)。它们之间的关系如图12-1所示。图12-1 各模式之间的关系其中对象的适配器模式是各种模式的起源,是一种比较重要的适配器模式。从箭头的方向可以看出各个模式的产生关系。这7种模式的作用不同,分别如下。 适配器模式(Adapter):将某个类的接口转换成客户端期望的另一个接口表示。适配器模式可以消除由于接口不匹配所造成的类兼容性问题。 根据适配对象的不同,又分为3种类型: 类的适配器模式:用于对类进行适配。 对象的适配器模式:用于对对象进行包装。 接口的适配器模式:用于对接口抽象化。 装饰器模式(Decorator):向某个对象动态地添加更多的功能。装饰器模式是除类继承外另一种扩展功能的方法。 代理模式(Proxy):为其他对象提供一个代理以控制对这个对象的访问。 外观模式(Facade):为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 桥接模式(Bridge):将一个抽象与实现解耦,以便两者可以独立的变化。 组合模式(Composite):把多个对象组成树状结构来表示局部与整体,这样用户可以一样地对待单个对象和对象的组合。 享元模式(Flyweight):通过共享以便有效地支持大量小颗粒对象。接下来将对7种常用结构型模式进行比较,并通过经典的代表实例来说明该如何使用各种结构型模式: 适配器模式Iterator适配器(对象的适配器模式)、Enumeration适配器(对象的适配器模式)、AWT事件适配器(接口的适配器模式)、I/O字节流到字符流的适配器(对象的适配器模式)。 装饰器模式I/O输入/输出流管道的装饰器模式、Sitemesh装饰器。 代理模式Java动态代理机制。 桥接模式JDBC桥DriverManager。 组合模式AWT容器Container。 享元模式数据库连接池。下面来看详细的内容。12.1 适配器模式(Adapter)下面从以下几个方面来详细讲解适配器模式。 适配器模式的核心思想。 第一种:类的适配器模式(对类进行适配)。 第二种:对象的适配器模式(对对象进行包装)。 第三种:接口的适配器模式(对接口抽象化)。 何时使用适配器模式。 Java中的应用Iterator适配器(对象的适配器模式)。 Java中的应用Enumeration适配器(对象的适配器模式)。 Java中的应用AWT事件适配器(接口的适配器模式)。 Java中的应用I/O字节流到字符流的适配器(对象的适配器模式)。12.1.1 适配器模式的核心思想适配器模式的核心思想:把原有的接口转变成调用者期待的接口,从而使不同接口的类可以一起工作。适配器中包含如下3个角色。 源角色Adaptee:需要适配的目标类或接口。 目标角色Target:所期望得到的接口。 适配器角色Adapter:适配器类是本模式的核心,用来把源接口转换成目标接口,显然这一角色不可以是接口,而必须是具体类。这3者角色之间的交互关系便组成了适配器模式的模型,如图12-2所示。Adaptee类只有operation()方法,没有newoperation()方法,但是客户端又需要目标类同时拥有这两个方法,这时便可以新建一个接口Target,并提供一个中间环节Adapter类,Adapter类实现了Target接口,并继承自Adaptee,Adapter类的operation()方法重新封装了Adapter类的operation()方法,并同时实现了newoperation()方法,这便实现了适配的目的。图12-2 适配器模式的模型适配器也叫做包装器模式(Wrapper),根据适配对象的不同,又可以将适配器模式分为3种子类型。 类的适配器模式:用于对类进行适配。 对象的适配器模式:用于对对象进行包装。 接口的适配器模式:用于对接口抽象化。下面分别通过实例的形式来展示这3种模式的使用。12.1.2 第一种:类的适配器模式(对类进行适配)第一种模式是类的适配器模式,它用来对目标类进行包装,如图12-3所示。 Source类是具体的原始类,是待适配的对象,它拥有一个函数operation1()。 Targetable是要适配的目标接口,它拥有一个与Source同样的接口函数operation1(),并提供了一个新的接口函数operation2(),该函数是要扩展的功能。 Adapter是适配器类,它必须继承Source类,并实现Targetable接口,从而将Source的功能扩展到Targetable接口所具有的功能。适配后的Source类,即可以通过调用Targetable接口来实现对Source类的操作,如图12-3所示。图12-3 类的适配器模式下面来看具体的实现。(1)Source类的源代码如程序12-1所示,其默认的操作函数operation1()用来输出一个字符串。程序12-1 源类Source.javapackage structure.adapter;/* author liuzhongbing* 源类*/public class Source public void operation1() System.out.println(原始类的方法); (2)Targetable必须首先具备与Source相同的函数接口,这样它才能够实现Source功能,然后增加扩展函数operation2()。其源代码如程序12-2所示。程序12-2 目标接口Targetable.javapackage structure.adapter;/* author liuzhongbing* 目标接口*/public interface Targetable /* * 与源类相同的接口函数 */ public void operation1(); /* * 新的接口函数,源类中没有 */ public void operation2();(3)Adapter的作用是将Source适配为Targetable,因此它必须继承Source类并实现Targetable接口,这样它便拥有了Source函数operation1()的功能,该函数还拥有了与Targetable同样的接口;同时,它必须实现Targetable的扩展函数,它往控制台输出了一个字符串。其源代码如程序12-3所示。程序12-3 适配器类Adapter.javapackage structure.adapter;/* author liuzhongbing* 适配器模式,继承源类,并实现目标接口*/public class Adapter extends Source implements Targetable /* * 实现目标类的新接口函数 */ public void operation2() System.out.println(适配目标类后的方法); (4)我们就可以创建一个Adapter类的对象,该对象属于Targetable,调用该对象的operation1()函数将会实现对Source函数的调用,调用operation2()函数将会实现对Adatper实现函数的调用,这样就实现了对类Source到Targetable的适配。测试类源代码如程序12-4所示。程序12-4 测试类AdapterTest.javapackage structure.adapter;/* author liuzhongbing* 按照目标接口来创建实例,并调用该接口的各个实现函数*/public class AdapterTest public static void main(String args) / 创建目标接口的类实例 Targetable obj = new Adapter(); / 调用目标类的方法 obj.operation1(); obj.operation2(); 运行该程序的输出为:原始类的方法适配目标类后的方法这正是我们想要的结果:把类Source按照接口Targetable进行调用。12.1.3 第二种:对象的适配器模式(对对象进行包装)第二种模式是对象的适配器模式,它用来对目标对象进行包装,因此又叫做包装器模式,如图12-4所示。 Source类是具体的原始类,是待包装对象的类,它拥有一个函数operation1()。 Targetable是要适配的目标接口,它拥有一个与Source同样的接口函数operation1(),并提供了一个新的接口函数operation2(),该函数是要扩展的功能。 Wrapper是包装器类,它与Adapter适配器不同,它不需要继承Source,但必须拥有一个Source类型的对象source,该对象在构造函数中被赋值。在该包装器的operation1()函数中,需要调用source的operation1(),这样就实现了对原有对象的调用;同时扩展实现Targetable的operation2()函数。包装后的Wrapper类,即可以通过调用Targetable接口来实现对Source类的操作,如图12-4所示。图12-4 对象的适配器模式以上的Source类和Targetable接口与第一种模式相同,唯一不同的是Wrapper的实现方式不同。其源代码如程序12-5所示。程序12-5 包装器类Wrapper.javapackage structure.adapter;/* author liuzhongbing* 包装器模式*/public class Wrapper implements Targetable private Source source; /* * 取得源类对象 */ public Wrapper(Source source) super(); this.source = source; /* * 调用源类对象的方法 */ public void operation1() source.operation1(); /* * 实现目标类的新接口函数 */ public void operation2() System.out.println(包装目标类后的方法); 创建一个Source类的对象source,并根据该对象创建一个Wrapper包装器obj,该包装器对象属于Targetable,调用该对象的operation1()函数将会实现对Source函数的调用,调用operation2()函数将会实现对Wrapper实现函数的调用,这样就实现了对类Source到Targetable的包装。测试类源代码如程序12-6所示。程序12-6 测试类WrapperTest.javapackage structure.adapter;/* author liuzhongbing* 按照目标接口来创建实例,并调用该接口的各个实现函数*/public class WrapperTest public static void main(String args) / 创建源类对象 Source source = new Source(); / 创建source的包装类对象 Targetable obj = new Wrapper(source); / 调用目标类的方法 obj.operation1(); obj.operation2(); 运行该程序的输出为:原始类的方法包装目标类后的方法输出的结果与第一种模式相同,因此效果是与第一种模式相同的,不同的是适配的方式不同。12.1.4 第三种:接口的适配器模式(对接口抽象化)有时我们会在一个接口中定义多个接口方法,如果要实现该接口编写一个类,就必须为每一个接口方法编写实现代码,这显然会造成很大的浪费。为了解决这个问题,可以使用第三种适配器模式默认适配器。它会为原有的接口类实现一个默认的抽象类,在该抽象类中编写每一个接口的默认实现,当我们需要编写一个具体类时,只需要继承自该抽象类,而不需要实现原有的接口。并且,此时我们不需要实现所有的接口方法,只实现需要的函数即可。如图12-5所示为接口的适配器模式。 Sourceable是定义了多个接口函数的接口类。 DefaultWrapper是一个抽象类,它实现了接口Sourcable,并为每一个接口函数提供了默认的实现。依据DefaultWrapper就可以编写不同的实现,在实现中只需要重写部分待实现的函数,而不需要重写全部。图12-5 接口的适配器模式下面来看具体的实现。(1)Sourcable类的源代码如程序12-7所示,它定义了两个操作函数。程序12-7 源接口Sourcable.javapackage structure.adapter;/* author liuzhongbing* 源接口*/public interface Sourcable public void operation1(); public void operation2();(2)DefaultWrapper实现了Sourcable接口,并提供了其两个接口函数的实现,在该实现中可以什么也不做,目的只是为了给其子类提供一个默认的实现。其源代码如程序12-8所示。程序12-8 默认适配器类DefaultWrapper.javapackage structure.adapter;/* author liuzhongbing* 包装器模式*/public abstract class DefaultWrapper implements Sourcable public void operation1() public void operation2()(3)SourceSub1继承自DefaultWrapper,由于DefaultWrapper的屏蔽作用,SourceSub1可以只重新实现自己关心的函数operation1(),它负责输出一个字符串。其源代码如程序12-9所示。程序12-9 源接口的实现子类SourceSub1.javapackage structure.adapter;/* author liuzhongbing* 源接口的实现类*/public class SourceSub1 extends DefaultWrapper public void operation1() System.out.println(源接口的一个实现子类Sub1); (4)SourceSub2继承自DefaultWrapper,由于DefaultWrapper的屏蔽作用,SourceSub2可以只重新实现自己关心的函数operation2(),它负责输出一个字符串。其源代码如程序12-10所示。程序12-10 源接口的实现子类SourceSub2.javapackage structure.adapter;/* author liuzhongbing* 源接口的实现类*/public class SourceSub2 extends DefaultWrapper public void operation2() System.out.println(源接口的一个实现子类Sub2); 以上我们编写了两个实现SourceSub1和SourceSub2,下面分别创建一个对象,创建的对象都属于Sourcable。然后分别调用它们的方法operation1()和operation2()。其源代码如程序12-11所示。程序12-11 测试类DefaultWrapperTest.javapackage structure.adapter;public class DefaultWrapperTest public static void main(String args) Sourcable source1 = new SourceSub1(); Sourcable source2 = new SourceSub2(); source1.operation1(); source1.operation2(); source2.operation1(); source2.operation2(); 运行该程序的结果如下:源接口的一个实现子类Sub1源接口的一个实现子类Sub2从输出的结果可以看出,source1和source2仅仅在运行自身实现的函数时发生了作用,对于没有实现的函数则调用了默认适配器DefaultWrapper的默认函数,什么也没有输出。12.1.5 何时使用适配器模式从以上的讲解我们已经知道,如果需要将一个类变成另一个类时就可以使用适配器模式。但是根据需求的不同,可以分别选用3种不同的子模式。 类的适配器模式:当希望将一个类转换成满足另一个接口时,可以模仿Adapter的做法来构造一个新的适配器类,该类继承原有的类并实现新的接口即可。 对象的适配器模式:当希望将一个对象转换成另一个接口时,可以模仿Wrapper的做法来构造一个新的包装类,该类调用原有的类并实现新的接口即可。 默认适配器模式:当不希望实现一个接口的所有方法时,可以模仿DefaultWrapper的做法构造一个抽象类,给出所有方法的默认的实现,这样,从这个抽象类再继承下去的子类就不必实现所有的方法了。以上的说法稍显抽象,在Java API中有许多地方都运用了适配器模式,下面我们找出来分析一下,你就会明白适配器模式的实际用处了。12.1.6 Java中的应用Iterator适配器(对象的适配器模式)在Java中存在两个迭代器类:Iterator和Enumeration。两者都可以由相应的集合对象转化而来,例如ArrayList可以变成Iterator对象,Vector可以变成Enumeration对象。然而,有时你可能需要将ArrayList转换成Enumeration对象,这就需要使用包装器模式来将Iterator对象转换成Enumeration对象了。此时我们可以选择第二种适配器对象的适配器。如图12-6所示,包装器Itermeration负责将对象Iterator改造成Enumeration的形式。图12-6 Iterator适配器Iterator对象拥有如下两个函数: hasNext()判断是否有下一个对象。 next()取得下一个对象。为了将Iterator转换为Enumeration,此时可以调用上面的两个函数来分别实现Enumeration的如下两个函数: hasMoreElements()判断是否有下一个对象。 nextElement()取得下一个对象。其完整的代码如程序12-12所示。程序12-12 Iterator被包装为Enumeration类型Itermeration.javapackage structure.adapter;import java.util.Iterator;import java.util.NoSuchElementException;import java.util.Enumeration;/* author liuzhongbing* 使用了包装器模式*/public class Itermeration implements Enumeration Iterator it; public Itermeration(Iterator it) this.it = it; public boolean hasMoreElements() return it.hasNext(); public Object nextElement() throws NoSuchElementException return it.next(); 下面来编写测试代码。首先创建一个ArrayList对象并初始化数据,进而得到Iterator对象,然后根据该对象构造Itermeration的对象即可,最后即可按照Enumeration的接口进行迭代。其源代码如程序12-13所示。程序12-13 测试类ItermerationTest.javapackage structure.adapter;import java.util.ArrayList;import java.util.Enumeration;import java.util.Iterator;import java.util.List;public class ItermerationTest public static void main(String args) / 创建Iterator对象 List list = new ArrayList(); list.add(aaa); list.add(bbb); list.add(ccc); Iterator it = list.iterator(); / 取得Enumeration对象 Enumeration em = new Itermeration(it); while(em.hasMoreElements() System.out.println(em.nextElement(); 运行该程序的结果如下:aaabbbccc12.1.7 Java中的应用Enumeration适配器(对象的适配器模式)有时你可能需要将Vector转换成Iterator对象,这就需要使用包装器模式来将Enumeration对象转换成Iterator对象了。此时我们可以选择第二种适配器对象的适配器。如图12-7所示,包装器Enumerator负责将对象Enumeration改造成Iterator的形式。图12-7 Enumeration适配器Enumeration对象拥有如下两个函数: hasMoreElements()判断是否有下一个对象。 nextElement()取得下一个对象。为了将Enumeration转换为Iterator,此时可以调用上面的两个函数来分别实现Iterator的如下两个函数: hasNext()判断是否有下一个对象。 next()取得下一个对象。此外,Iterator接口还有一个删除函数remove,由于Enumeration没有提供相应的删除函数,这里我们可以不提供remove功能。其完整的代码如程序12-14所示。程序12-14 Enumeration被包装为Iterator类型Enumerator.javapackage structure.adapter;import java.util.Enumeration;import java.util.Iterator;public class Enumerator implements Iterator Enumeration em; public Enumerator(Enumeration em) super(); this.em = em; public boolean hasNext() return em.hasMoreElements(); public Object next() return em.nextElement(); public void remove() 下面来编写测试代码。首先创建一个Vector对象并初始化数据,进而得到Enumeration对象,然后根据该对象构造Enumerator的对象即可,最后即可按照Iterator的接口进行迭代。其源代码如程序12-15所示。程序12-15 测试类EnumeratorTest.javapackage structure.adapter;import java.util.Enumeration;import java.util.Iterator;import java.util.Vector;public class EnumeratorTest public static void main(String args) / 创建Enumeration对象 Vector vect = new Vector(); vect.add(aaa); vect.add(bbb); vect.add(ccc); Enumeration em = vect.elements(); / 取得Iterator对象 Iterator it = new Enumerator(em); while(it.hasNext() System.out.println(it.next(); 运行该程序的结果如下:aaabbbccc12.1.8 Java中的应用AWT事件适配器(接口的适配器模式)从以上的学习我们已经了解到,基于接口的适配器模式是采用抽象化接口的方式,来达到节省接口函数的目的,这一特性特别适合于Java AWT中的事件处理模式。对于定义的事件监听器接口,它可能包含多个事件处理函数,但在使用时我们往往只需要关注其中的某一种事件,此时就可以使用抽象化适配来将事件监听器接口进行抽象化,给出每一个接口函数的默认实现,这样在需要使用时只需要重写自己需要的函数即可,如图12-8所示。图12-8 AWT事件处理类图从图中可以看出,共分为3层: 第一层是EventListener顶层事件接口类,它只是定义了一个接口,没有包含任何接口函数。 第二层是AWT的事件监听器接口(以Listener为结尾),每一个监听器接口对应一种窗口事件,其中定义了多个事件处理函数。 第三层是AWT的事件适配器抽象类(以Adapter为结尾),它们分别为对应的监听器接口提供了默认的函数实现。所有的适配器抽象类都采用了接口的适配器模式来实现。例如,鼠标监听器接口中定义了5个鼠标事件接口函数,如程序12-16所示。程序12-16 鼠标监听器接口MouseListener.javapackage java.awt.event;import java.util.EventListener;public interface MouseListener extends EventListener /* * 鼠标单击事件 */ public void mouseClicked(MouseEvent e); /* * 鼠标按下事件 */ public void mousePressed(MouseEvent e); /* * 鼠标释放事件 */ public void mouseReleased(MouseEvent e); /* * 鼠标进入事件 */ public void mouseEntered(MouseEvent e); /* * 鼠标退出事件 */ public void mouseExited(MouseEvent e);当我们要使用该接口编写鼠标事件处理代码时,就需要实现该接口,并实现5个事件函数,如程序12-17所示。程序12-17 自定义的鼠标实现类import java.awt.event.MouseEvent;import java.awt.event.MouseListener;public class MyMouseListener implements MouseListener Override public void mouseClicked(MouseEvent arg0) System.out.println(鼠标单击事件); Override public void mousePressed(MouseEvent arg0) System.out.println(鼠标按下事件); Override public void mouseReleased(MouseEvent arg0) System.out.println(鼠标释放事件); Override public void mouseEntered(MouseEvent arg0) System.out.println(鼠标进入事件); Override public void mouseExited(MouseEvent arg0) System.out.println(鼠标退出事件); 然而,我们可能只需要处理其中的某一个事件,却不得不编写所有的接口函数,此时就可以使用适配器类MouseAdapter了。该适配器实现了3个鼠标相关的事件接口,并为这些接口中的所有函数都提供了默认的实现,这些实现的代码为空,表示什么也不做,如程序12-18所示。程序12-18 鼠标事件适配器MouseAdapter.javapackage java.awt.event;public abstract class MouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener public void mouseClicked(MouseEvent e) public void mousePressed(MouseEvent e) public void mouseReleased(MouseEvent e) public void mouseEntered(MouseEvent e) public void mouseExited(MouseEvent e) public void mouseWheelMoved(MouseWheelEvent e) public void mouseDragged(MouseEvent e) public void mouseMoved(MouseEvent e)此时如果我们只希望处理鼠标单击事件,只需要继承适配器MouseAdapter,并重写单击事件函数mouseClicked()即可,如程序12-19所示。程序12-19 单击事件处理程序MyMouseClickedListener.javaimport java.awt.event.MouseEvent;import java.awt.event.MouseAdapter;public class MyMouseClickedListener extends MouseAdapter Override public void mouseClicked(MouseEvent arg0) System.out.println(鼠标单击事件); 由此可见,通过使用事件的适配器,可以让我们的代码只关注自己的事件,而不必造成不必要的代码浪费。这就是适配器模式在事件处理中的应用。12.1.9 Java中的应用I/O字节流到字符流的适配器(对象的适配器模式)Java I/O最关键的4个类是InputStream(输入字节流)、OutputStream(输出字节流)、Reader(输入字符流)、Writer(输出字符流),它们都是public abstract class类。 InputSream和OutputStream对于数据的传送是以字节Byte为单位的,而Reader和Writer对于数据的传送是以字符Character为单位的。所以我们看到java.io包中的类大体上可以分为两大类,一类是以Byte处理为主的Stream类,它们都是以XXXStream方式命名的;一类是以Character处理为主的Reader/Writer类,它们都是以XXXReader或XXXWriter的方式命名的。表12-1展示了InputStream、OutputStream、Reader、Writer的各种实现的子类。可以分为3类:数据源类、数据流串联类、数据流过滤类。其中的数据源类是创建各种流的起始类,第二类和第三类都是对各自流实例的包装。表12-1 输入/输出流类列表输入字节流输出字节流输入字符流输出字符流抽象类InputStreamOutputStreamReaderWriter转换类InputStreamReaderOutputStreamWriter第一类:数据源类数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter文件FileInputStreamFileOutputStreamFileReaderFileWriter对象ObjectInputStreamObjectOutputStream字符串StringBufferInputStreamStringReaderStringWriter第二类:数据流串联类管道PipeInputStreamPipeOutputStreamPipedReaderPipeWriter序列SequenceInputStream第三类:数据流过滤类过滤FilterInputStreamFilterOutputStreamFilterReaderFilterWriter缓冲BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter数据DataInputStreamDataOutputStream行号LineNumberInputStreamLineNumberReader推回PushbackInputStreamPushbackReader格式化PrintStreamPrintWriter关于该表中各种类及其原理的使用,详细参见Java高手真经Java核心编程技术一书。从上表可以看出,以字符为导向的reader/writer基本上有与之相对应的以字节为导向的stream。两个对应类实现的功能相同,只是在操作时的导向不同。如 CharArrayReader和ByteArrayInputStream的作用都是把内存中的一个缓冲区作为流使用,所不同的是前者每次从内存中读取一个字节的信息,而后者每次从内存中读取一个字符。然而,字节流与字符流之间的区别却可以联系起来,这就是表中的两个类InputStreamReader和OutputStreamReader。InputStreamReader负责把字节输入流转换为字符输入流,OutputStreamReader负责把输出字节流转换为输出字符流。下面来看看如何进行转换。1字节输入流转换为字符输入流InputStreamReader是字节流通向字符流的桥梁,它使用指定的charset读取字节并将其解码为字符。它拥有一个InputStream类型的变量,并继承了Reader,使用了对象的适配器模式,如图12-9所示。图12-9 InputStreamReader适配器根据InputStream的实例创建InputStreamReader的方法有4种:InputStreamReader(InputStream in); /根据默认字符集创建InputStreamReader(InputStream in, Charset cs); /使用给定字符集创建InputStreamReader(InputStream in, CharsetDecoder dec); /使用给定字符集解码器创建InputStreamReader(InputStream in, String charsetName); /使用指定字符集创建后面的3个构造函数都指定了一个字符集,最后一个是最简单的,可以直接指定字符集的名称来创建,例如GB2312等。每次调用InputStreamReader中的一个read()方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。共有3个可用的read()方法:int read(); /读取单个字符int read(char cbuf, int offset, int length); /将字符读入数组中的某一部分boolean ready(); /判断此流是否已经准备好用于读取InputStreamReader继承自Rea

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论