134.事件处理相关概念
- 事件
- 用户对组件的操作,称为一个事件
- 事件源
- 能够产生事件的GUI组件对象,如按钮、文本
- 事件处理方法
- 能够接收、解析和处理事件类对象,实现与用户交互功能的方法
- 事件监听器
- 可以处理事件的一个类
135.事件处理步骤
- 假设事件为XXX
- 向事件源注册某种事件的事件监听器对象
- addXXXListener()
- 设计好可以处理这种事件的事件监听器
- Class 类名 implements XXXListener
- {
- 重写XXXListener接口中的方法
- }
- 说明
- 要想设计出能够处理XXX事件的监听器,只需编写出实现XXXListener接口的类就行了,因为XXXListener接口已经定义了可以处理XXX事件的方法
136.事件处理相关概念
- 默认情况下事件源是不会自动产生任何事件,程序员需要做两件事:
- 告诉事件源可以自动产生哪类事件,即:向事件源注册某种事件的事件监听器对象
- 设计好可以处理这种事件的事件监听器
- 一旦完成了这两步操作,当用户对事件源进行操作时,事件源就会自动产生事件,事件源就会自动把产生的事件封装成一个事件对象,并且把封装好的事件对象传递给事件监听器
- 事件监听器收到事件源发送过来的事件时,事件监听器就会自动调用相应的事件处理方法来对该事件进行相应处理
137.遗留问题
- 事件有哪些?
- java.awt.event包中含有所有的事件,常用的事件有:
- ActionEvent:激活组件时发生的事件
- KeyEvent:操作键盘时发生的事件
- MouseEvent:操作鼠标时发生的事件
- WindowEvent:操作窗口时发生的事件,如最大化或最小化某一窗口
- 一个事件源可以自动产生哪些事件?
- 第三方软件会自动显示
138.事件处理示意图
139.TestField监听器
140.内部类
- 内部类定义:
- 在A类的内部但是所有方法的外部定义了一个B类,则B类就是A类的内部类,A是B的外部类
- 内部类访问原则
- 内部类的方法可以访问外部类所有的成员
- 外部类的方法不可以直接访问内部类的成员
- 内部类的优点
- 可以让一个类更方便的访问另一个类的所有成员
- 增加程序的安全性,有效避免其它不相关类对该类的访问
- 何时使用内部类
- 如果一个A类要使用B类的所有成员,并且A类不需要被B类以外的其它类访问,则我们应该把A类定义为B的内部类
141.内部类举例
- 编程实现,两个文本框内容相加所得结果赋给第三个文本框
142.匿名类
- 匿名类是一种特殊的内部类
- 如果在一个方法内部定义了匿名类,则该匿名类可以访问
- 外部类的所有成员
- 包裹该匿名类的方法中的所有final类型的局部变量
- 注意:非final类型的局部变量无法被匿名类访问
143.创建匿名类的三种方式
- 继承父类
- 实现接口
- 实现抽象类
144.创建匿名类之实现接口
- 假设A是接口名
- 格式:
New A()
{
实现接口中方法的代码
}
- 功能:
- 生成一个实现了A接口的匿名类
145.创建匿名类之实现抽象类
- 假设A是抽象类
- 格式:
- New A()
- {
- 实现了类A的所有抽象类的方法代码
- 添加自己的方法或属性代码(不建议)
- }
- 功能:
- 生成一个匿名类,该匿名类必须得实现了A类的所有抽象方法,当然该匿名类也可以定义自己的属性和方法
146.创建匿名类之继承父类
- 假设A是个类名
- 格式:
- New A()
- {
- 重写了A类的方法代码
- 添加自己的属性和方法(不建议)
- }
- 功能:
- 生成A类的一个子类对象,该匿名类对象继承了A的所有非私有成员
147.匿名类的优缺点
- 如果一个类的语句比较少,逻辑比较简单,而且不会经常变动,这个时候可以使用匿名类
- 如果一个类包含了很重要的逻辑,将来要经常修改,则这个类就不应该当做匿名类来使用,匿名类会导致代码的混乱
148.可运行jar包生成步骤
- 新建一个记事本,假设为1.txt.
- 文件内容:
- Main-Class:可运行类的名字
- 附注:记得敲回车
- dos下命令
- Jar cvfm haha.jar 1.txt*.class
- 记住:只有GUI程序生成的class文件才可作为main-Class
149.设计一个计算器预备知识
- Button类有如下常用方法
- Public String getLabel()
- getLabel()返回的一定是我们在显示器上能够看到的按钮上的信息,即返回的是标签字符串的信息,如果按钮的标间字符串为空,则getLabel()返回null
- Public String getActionCommand()
- 返回此按钮激发的动作事件的命令名称,如果以前没有通过setActionCommand()方法设置动作事件的命令名称,则本方法返回按钮的标签字符串的信息
- Public void setActionCommand(String command)
- 设置此按钮激发的动作事件的命令名称,如果没有设置动作事件的命令名称,则动作事件的命令名称称默认值与按钮标签字符串的值一样
150.流
- 节点流与处理流
- 节点流:也叫原始流
- 处理流:也叫包裹流
- 流的定义:
- 流就是程序和设备之间嫁接起来的一根用于数据传输的管道。这个管道上有很多按钮,不同的按钮可以实现不同的功能
- 这根带按钮的用于数据传输的管道就是流
- 流就是一根管道
151.流的示意图
- 输入时,程序在源(文件、网络、内存)上打开一个stream,然后如图一个一个顺序读,写也一样
152.流的分类标准
- Java.io包中定义了多个流类型(类或抽象类)来实现对输入/输出功能进行分类:
- 按数据流的方向不同可以分为输入流和输出流
- 按处理数据单位不同可以分为字节流和字符流
- 按照功能不同可以分为节点流(原始流)和处理流(包裹流)
153.必须掌握的知识点
- 什么叫流
- 流与类的关系
- 如果一个类是用作设备和程序之间的数据传输,则这个类一定有一个名字叫流
- 流一定是类,类不一定是流
- 原始流(节点流)和包裹流(处理流)的关系
154.四大基本抽象流
- InputStream 和 OutputStream 读写数据的单位是一个字节
- Reader和Writer读写数据的单位是一个字符
- 在Java中,一个字符占两个字节
- InputStream、OutputStream、Reader、Writer都是抽象类,或者说都是抽象流,通常我们使用的都是它们的子类
- 凡是以stream结尾的都是字节流
155.InputStream流中常用的方法
- Public int read() throws IOException
- 读取一个字节并以整数形式返回
- 如果读取到输入流的末尾则返回-1
- Public int read(byte【】 b) throws IOException
- 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中,以整数形式返回实际读取的字节数
- 如果b的长度为0,则不读取任何字节并返回0,如果因为流位于文件末尾而没有可用的字节,则返回-1
- 例子:
- FileInputStream fis = new FileInputStream(“d:\\share\\errorlog.txt”)
- Len = fis.read(buf)
- // 从fis流所关联的(d:\\share\\errorlog.txt)文件中读取数据,并将读取的数据放入buf数组中,返回值是实际写入buf数组的字节个数,如果读取到文件末尾,则返回-1
- Public int read(byte【】b,int off,int len)throws IOException
- 从输入流中最多读取len个字节的数据并存入byte数组中
- b表示读取的数据要存入的数组的名字
- off表示第一个读出的数据要存入的位置,是下标
- len表示最多能读取的字节数
- 将从输入流所关联到的设备中读取的第一个字节存储在b【off】中,下一个字节存储在b【off+1】中,以此类推,读取的字节数最多等于len
- 尝试读取len个字节,但读取的字节数也可能小于该值,以整数形式返回实际读取的字节数
- 如果读到了文件末尾,则返回-1
- Void close() throws IOException
- 关闭此输入流并释放与该流相关联的所有系统资源
- Long skip(long n) throws IOException
- 跳过和丢弃此输入流中数据的n个字节
- 这个用的少
156.OutputStream流中常用的方法
- Void write(int b) throws IOException
- 向输出流中写入一个字节数据,该字节数据为参数b的第八位
- Void write(byte【】b)throws IOException
- 将一个字节类型的数组中的数据写入到输出流
- Void write(byte【】b,int off,int len)throws IOException
- 将一个字节类型的数组中的数据从指定位置(off)开始的len个字节写入到输出流
- Void close()throws IOException
- 关闭释放内存资源
- Void flush()throws IOException
- 将输出流缓冲的数据全部写出到目的地
157.Rader流的常用方法
- Int read()throws IOException
- 读取一个字符并以整数的形式返回(0~255),如果返回的是-1,则已到输入流的末尾
- Int read(char【】buffer)throws IOException
- 读取一系列字符并存储到一个数组buffer中,返回实际读取的字符数,如果读取前已到输入流的末尾,则返回-1
- Int read(char【】 buffer,int offset,int length)throws IOException
- 最多读取length个字符,并存储到数组buffer,从offset位置开始返回实际读取的字符数,如果读取以前已到输入流的末尾,则返回-1
- Void close()throws IOException
- 关闭流释放内存资源
- Long skip(long n)throws IOException
- 跳过n个字符不读,返回实际跳过的字符数
158.Writer流中常用方法
- Void write(char c)throws IOException
- 向输出流写入一个字符型数据
- Void write(char【】buffer)throws IOException
- 将一个字符数组中的数据写入到输出流
- Void write(char【】buffer,int offset,int length)throws IOException
- 将一个字符数组中的数据从指定的位置(offset)开始的length个字符写入到输出流
- Void write (String str)throws IOException
- 将一个字符串中的字符写入到输出流
- Void write(String str,int offset,int length)throws IOException
- 将一个字符串从offset开始的length个字符写入到输出流
- Void close()throws IOException
- 关闭流释放内存资源
- Void fflush()throws IOException
- 将输出流中缓冲的数据全部写出到目的地
159.文件流
- 文件流包括:
- FileInputStream、FileOutputStream ——字节流
- FileReader、FileWriter ——字符流
- 例子:
- 读取一个文件的内容并将其输出到显示器上,共统计读取出来的字符个数。
160.FileInputStream的使用
- InputStream是用来读取字节的,是个抽象类,我们通常使用它的子类
- FileInputStream是InputStream的子类,利用FileInputStream可以将一个文件的内容按字节为单位读取出来
- FileInputStream有一个很常用的构造函数
- Public FileInputStream(String filename)throws FileNotFoundException
- 利用该构造函数可以实现将输入流连接到某个文件的功能
- 必须对本构造函数抛出的异常进行捕捉
- 如果用字符串来表示操作系统的文件路径时,我们可以使用 \\ 和 / 两种方式来作为文件的路径分隔符
- FileOutputStream同理
161.FileReader的使用
- Reader是用来读取字符的,是个抽象类,我们通常使用它的子类
- FileReader是Reader的子类,利用FileReader可以将一个文件的内容以字符为单位读取出来
- FileReader有一个很常用的构造函数
- Public FileReader(String filename)throws FileNotFoundException
- 利用该构造函数可以实现将输入流连接到某个文件中的功能
- 必须对本构造函数抛出的异常进行捕捉
- 如果用字符串来表示操作系统的文件路径时,我们可以使用\\和/两种方式来作为文件夹的路径分隔符
- FileWriter同理
162.字节流和字符流的区别
- FileInputStream和FileOutputStream可以完成所有格式文件的复制
- FileReader和FileWriter只可以完成文本文件的复制,却无法完成视频格式文件的复制
- 因为字节是不需要解码和编码的,将字节转化为字符才存在解码和编码的问题
- 字节流可以从所有格式的设备中读写数据,但字符流只能从文本格式的设备中读写数据
163.缓冲流概述
- 缓冲流就是带有缓冲区的输入输出流
- 缓冲流可以显著地减少我们对IO访问的次数,保护我们的硬盘
- 缓冲流本身就是处理流(包裹流),缓冲流必须得依附于节点流(原始流)
- 处理流是包裹在原始节点流上的流,相当于包括在管道上的管道
164.BufferedOutputStream和BufferedInputStream
- BufferedOutputStream:带缓冲的输出流,允许一次向硬盘写入多个字节的数据
- BufferedInputStream:带缓冲的输入流,允许一次向程序中读入多个字节的数据
- BufferedOutputStream和BufferedInputStream都是包裹流必须得依赖于OutputStream和InputStream
- 例子:
- 利用BufferedInputStream和BufferedOutputStream完成大容量文件的复制,这远比单纯利用FileInputStream和FileOutputStream要快得多
165.BufferedReader和BufferedReader
- 只有
- BufferedInputStream
- BufferedOutputStream
- BufferedReader
- BufferedWriter
- 没有
- BufferedStream
- BufferedFileInputStream(但有FileInputStream)
- BufferedOutputStream(但有FileOutputStream)
- BufferedFileReader(但有FileReader)
- BufferedFileWriter(但有FileWriter)
- 所以前四个流都是包裹流
166.BufferedInputStream和BufferedOutputStream的方法
- BufferedInputStream流中有
- Public int read(byte【】b)
- 把当前所关联的设备读取出来的数据存入一个byte数组中
- BufferedOutputStream流中有
- Public int write(byte【】b)
- 把byte数组中的数据输出到与当前流关联的设备中去
- 如果我们希望用BufferedInputStream和BufferedOutputStream完成“将一个设备中的数据导入另一个设备中”,我们应该定义一个临时byte类型的数组,再用这个临时数组作为输入流和输出流进行交互的中转枢纽
- BufferedIntputStream BufferedOutputStream 要比 FileInputStream FileOutputStream读写数据的速度要快
167.BufferedReader和BufferedWriter
- Reader、FileReader 、InputStream、FileInputStream、BufferedInputStream流中都没有readLine方法
- DataInputStream流中有readLine方法,但已过时
- BufferedReader流中有readLine方法,并且该方法可以被使用
- 利用BufferedReader和BufferedWriter可以提高读写文本文件内容的速度
- 示例:
- 利用BufferedWriter和BufferedReader完成文本文件的复制
168.DataInputStream
- DataInputStream能够以一种与机器无关的方式,直接从底层字节输入流读取Java的基本类型和String类型的数据,常用方法包括:
- Public datainputStream(inputStream in)
- Public final boolean readBoolean()
- Public final byte readbyte()
- Public final char readchar()
- Public final float readfloat()
- Public final double readdouble()
- Public final int readint()
- Public final long readlong()
- Public final short readshort()
- Public final String readString()
- DataInputStream是包裹流,必须依赖于InputStream
169.DataOutputStream
- DataOutputStream能够以一种与机器无关的方式,直接将Java的基本类型和String类型的数据写出到其它的输出流,常用方法包括:
- Public dataoutputStream(outputStream in)
- Public final boolean writeBoolean()
- Public final byte writebyte()
- Public final charwritechar()
- Public final float writefloat()
- Public final double writedouble()
- Public final intwriteint()
- Public final long writelong()
- Public final short writeshort()
- Public final String writeString()
- DataOutputStream是包裹流,必须依赖于OutputStream
170.数据流实例:
- 例子:
- 编程实现将long类型数据写入byte数组,然后再从byte数组中把该数据读取出来
- 附注:
- 这是socket编程中经常要完成的功能
- 因为网络编程中经常要把数值型数据存入byte数组中,然后再把byte数组打包成数据包,再把数据包经过网络传输到目的机,目的机再从byte数组中把原数值型数据还原回来
- 本程序要使用:
- ByteArrayInputStream
- ByteArrayOutputStream
- DataInputStream
- DataOutputStream
171.转换流
- OutputStreamWriter流就是把OutputStream流转化为Writer流的流
- InputStreamReader流就是把InputStream流转化为Reader流的流
- OutputStreamWriter和InputStreamReader都是包裹流
- 编程:
- 如何将输入的字符组成字符串直接赋给String对象
172.readLine()和回车符的问题
- String str = "123"
- BufferedReader br = new BufferedReader(new InputStreamReader(System.in))
- Str = readLine();
- 如果直接输入回车的话,则:
- br.readLine()会丢弃回车符,而不是返回回车符,即br.readLine()遇到回车符时终止读取,并且会把读取到的回车符自动丢弃掉
- br.readLine()返回的是“”,而不是null,“”表示空字符串,null表示空指针,空指针就是空地址,空指针就是不指向任何存储单元的意思
173.Print流
- Print流只输出,不输入
- 分类:
- PrintWriter 输出字符
- PrintStream输出字节
174.Print流的由来
- Writer的write方法可以写入
- 一个字符
- 一个字符数组
- 一个字符数组的一部分
- 一个字符串
- 一个字符的一部分
- OutputStream的write方法可以写入:
- 一个字节
- 一个字节数组
- 一个字节数组的一部分
- DataOutputStream流可以写入
- 一个字节
- 一个字节数组
- 一个字节数组的一部分
- 所有基本类型的二进制代码
- PrintStream流的print可以写入:
- 所有基本类型数据的字符串表现形式
- 如:print(8.8)写入的是“8”“.”“8”这三个字符,共占3个字节
- 所有基本类型数据的字符串表现形式
175.PrintStream
- PrintStream在OutputStream基础之上提供了增强的功能,即可以方便地输出各种类型数据(而不仅限于byte型)的格式化表示
- PrintStream重载了print和println方法,用于不同数据类型的格式化输出
- 格式化输出是指将一个数据用其字符串格式输出
- DataOutputStream中的writeXXX(data)方法是把data在内的二进制数据写入文件
- PrintStream中的println(data)是该数据的格式化后的字符串写入文件
176.PrintWriter
- PrintWriter提供了PrintStream的所有打印方法,其方法也从不抛出IOException
- 与PrintStream的区别:
- 作为处理流使用时,PrintSteam只能封装OutputStream类型的字节流,而PrintWriter既可以封装OutputStream,还能够封装Writer
- PrintStream中的println()方法具有更好的跨平台性
177.标准输入输出的重定向
- 例子:
- 编程实现将键盘输入的数据输入A文件中,如果输入有误,则把出错信息输出到B文件中
- 对象的序列化
- Serializable接口中并没有任何方法,这种类型的接口被称为标记接口,如果一个类实现了Serializable接口,潜在含义就是告诉编译器这个类是允许被序列化的,如果程序中存在序列该对象的代码,编译器就会自动进行相应的处理已完成该对象的序列化,如果该对象没有实现Serializable接口,程序中却存在该对象被序列化的代码,编译器编译时会自动报错
- 在Java中transient修饰的成员变量在对象序列化时不能被序列化