教材链接:https://book.douban.com/subject/11534743/
示例代码:https://pan.baidu.com/s/1EQW8Ijyqvak0vxscaMfjtg | 提取码:k3q4
第七章 类和对象
7.1 面向对象概述
早期的程序开发使用结构化开发语言,但是随着软件的规模越来越大,已经不再适用。因此引入面向对象的开发思想,将所有要处理的问题抽象为对象。
- 7.1.1 什么是对象
- 通常将对象划分为动态部分和静态部分,即行为和属性。
- 7.1.2 什么是类
- 类是封装对象属性和行为的载体,具有相同属性和行为的一类实体称为类
- 7.1.3 面向对象的特点
- 封装:将对象的属性和行为封装起来,对用户隐藏起细节;
- 继承:类与类之间有关联,如果超市类和售货员类;继承是关联的一种。当处理一个问题时,可以将有用的类保留下来,遇到类似的问题可以拿来复用,这就是继承。继承利用了同类对象之间的共有属性,减少开发工作。
- 多态:将父类对象应用与子类的特征,就是多态。继承的过程中的实例化,即为多态。
7.2 类
- 7.2.1 类的构造方法
- 在类型中除了成员方法,还有一种特殊的方法,称为构造方法。对象的创建通过构造方法完成,每实例化一个对象,类会自动调用构造方法。
- 构造方法必须与类同名,构造方法没有返回值,但是与一般方法不同,不需要关键void进行声明。定义构造方法的语法:
public classname(){}
- 示例:构建AnyThting类。
- 7.2.2 类的主方法
- 主方法是类的入口,提供了程序的流程控制:
public static void main(String args[]){}
- 主方法是静态的。要直接在程序中调用的其他方法,也必须是静态的;
- 主方法没有返回值,主方法的形参为数组。
- 示例:创建TestMain类。
- 主方法是类的入口,提供了程序的流程控制:
- 7.2.3 成员变量
- 成员变量对应于对象的属性;
- 使用private关键字声明成员变量,否则为局部变量;
- 示例:创建Book类;
- 7.2.4 成员方法
- 成员方法对应于对象的行为;
- 成员方法定义格式:
极限修饰符 返回值类型 方法标识符(参数类型 参数
- ` 标识符){`
-
方法体(语句块);
-
return 返回值;
}
- 示例:参考上节的Book类;
- 7.2.5 局部变量
- 示例:参考上节的Book类;
- 7.2.6 局部变量的有效范围
- 局部变量的作用域从该变量的声明到该变量的结束为止(可理解为大括号中的范围);
- 互不嵌套的作用域(大括号)可以声明两个同类型、同名称的局部变量;
- 7.2.7 静态变量、常量和方法
- 由static修饰的变量、常量和方法称为静态的;也称为静态成员;
- 静态:在处理问题时,可能需要两个类共享一个数据。这是可以通过类名和’.’运算符调用;
- 不能将方法体内的局部变量声明为静态;
- 对类进行初始化,可以在类中划分静态区域:
public class example{
-
static{
-
//初始化变量
-
}
}
- 示例:创建StaticTest类。
- 7.2.8 极限修饰符
访问包位置 | 本类 | 本包其他类或子类 | 其他包的类或子类 |
---|---|---|---|
private | 可见 | 不可见 | 不可见 |
protected | 可见 | 可见 | 不可见 |
public | 可见 | 可见 | 可见 |
- 7.2.9 this关键字 +成员变量可以与成员方法中的形参同名,为了区分,可以使用this.指定成员变量;
- 7.2.10 范例:自定义图书类,创建Books类。
- 7.2.11 范例:温度单位转换工具,创建CelsiusConverter类。
7.3 对象
- 7.3.1 对象的创建
- 格式:
classname objectname = new classname(args[]);
- 格式:
- 7.3.2 访问对象的行为和属性
- 引用格式:
obj.类成员
- 示例:创建TransferProperty类。
- 引用格式:
- 7.3.3 对象的引用
- 对Book类的引用:
Book book; //不一定要与一个新对象相关联
- 对Book类的引用:
- 7.3.4 对象的比较
- 使用
==
运算符比较和使用equals方法比较; - 示例:创建Compare类。
- 使用
- 7.3.5 对象的销毁
- 当对象的生命周期结束,占用的内存会被回收;
- 被回收的情况:当对象引用超过其作用范围(该作用域执行结束),这个对象将视为垃圾;将对象赋值为null。
- 7.3.6 范例:略。
7.4 经典范例
- 汉诺塔问题求解,创建HanoiTower类。
第八章 接口、继承与多态
继承和多态可以使程序的架构更加有弹性,减少代码的冗余度。多态机制可以动态调整对象的调用,降低对象之间的依存关系。同时,为了优化继承和多态,一些类除了继承父类,还使用接口的形式。Java中的类可以同时实现多个接口,接口被用来建立类与类之间关联的标准。
8.1 接口的使用
Java只支持单重继承,不支持多继承,即一个类只能有一个父类。但是在实际 中需要使用多继承来解决问题,因此Java提供了接口来实现多继承功能。
- 8.1.1 接口的定义
1
2
3
4
5
6
7
8
// 使用interface关键字定义一个接口
[修饰符] interface 接口名 [extends 父接口名列表]{
//接口体:
[public] [static] [final] 变量名;
[public] [abstract] 方法;
}
// 示例:定义一个计算圆的周长和面积的接口:ICalculate.java
- 8.1.2 接口的实现
- 接口定义后,就可以在类中实现该接口,使用了implements关键字:
[修饰符] class <类名> [extends 父类名] [implements 接口列表]{}
- 示例:创建Cire类,实现8.1.1的接口;
- 接口定义后,就可以在类中实现该接口,使用了implements关键字:
- 8.1.3 范例:图片的不同格式储存
- 首先编写ImageSaver接口,在该接口中定义save方法;
- 然后在项目中创建GIFSaver类,实现ImageSaver接口;
- 8.1.4 范例:为汽车增加GPS功能
- 在项目中创建Car类,并定义car的属性和方法;
- 在项目中编写GPS接口,定义getLocation方法;
- 在项目中编写GPSCar类,继承Car类并实现GPS接口;
8.2 类的继承
- 8.2.1 继承的实现
- 使用extends关键字显式指定继承的父类:
[修饰符] class 子类名 extends 父类名{类体}
- 示例:创建Bird类,并创建Pigeon类继承Bird类。
- 使用extends关键字显式指定继承的父类:
- 8.2.2 继承中的重写
- 重写也称覆盖,当子类继承父类中所有可能被子类访问的成员方法时,子类的成员方法如果与父类方法同名,则发生重写。重写允许同一方法在不同的子类变现不同行为。
- 示例:创建Animal父类,创建Dog子类,重写父类的cry方法。
- 8.2.3 使用super关键字
- 子类可以继承父类的非私有(不是用private声明的)成员变量和成员方法。但是如果子类成员变量(或方法)与父类成员(或方法)同名,则父类成员变量被隐藏。
- 如果要访问父类中被隐藏的成员方法或变量,可以使用super关键字。以下是super关键字的两种用法:
- 在子类构造方法中用super关键字调用父类构造方法
super([参数列表]); //父类构造方法的参数列表
- 示例:创建Beast类和Tiger类;
- 操作被隐藏的成员变量或被重写的成员方法
super.成员变量名;
super.成员方法名([参数列表]);
- 示例:在上一节例子中添加。
- 在子类构造方法中用super关键字调用父类构造方法
- 8.2.4 范例:创建Employee、Manager和Test类。
- 8.2.5 范例:重写父类的方法,见上一个范例。
8.3 多态
- 8.3.1 什么是多态
- 在Java语言中,通常使用方法的重载(Overloading)和重写(Overriding)实现类的多态性。
- 重写实现多态性是因为子类方法与父类方法名称相同但功能不同;
- 重载是指一个类中出现多个方法名相同,但参数个数或参数类型不同的方法。
- 示例:创建Calculate类。
- 8.3.2 范例:计算几何图形的面积 +创建抽象类Shape,然后创建Circle、Rectangle继承Shape,最后创建类testShape测试两个子类。
- 8.3.3 范例:汽车销售市场
- 创建抽象类Car,然后创建子类BMW、Benz,然后创建CarFactory类,根据指定车型创建对象,最后创建Customer类进行测试。
8.4 经典范例
- 8.4.1 使用Comparable接口自定义排序
- 8.4.2 动态设置类的私有域
第九章 类的高级特性
高级特性,如包、内部类等;包在管理繁杂的类文件,解决类的重名问题,控制访问权限,等方面有重要作用;Java的一个更有效的隐藏细节的技巧是使用内部类。将内部类中的方法设置为类最小范围的修饰极限,就可以隐藏内部类的细节。
9.1 抽象类
- 抽象类只声明方法的存在,而不具体实现。抽象类不能被实例化,只能被继承。
- 声明格式:
abstract class 类名{
类体
}
- 在抽象类中声明没有实际意义的,必须由子类重写的抽象方法:
abstract <返回值类型> 方法名(参数列表);
- 注意:抽象方法不能使用private或static进行修饰;如果一个类中定义了抽象方法,那么该类只能定义为抽象类。
- 示例:创建抽象类Fruit,创建子类Apple、Orange,并在Farm中测试。
9.2 内部类
即,在类中再定义一个类;可分为成员、局部以及匿名内部类。
- 9.2.1 成员内部类
- 格式:
public class OuterClass{
-
private class InnerClass{
-
//...
-
}
}
- 在内部类中可以自由使用外部类的成员变量和成员方法,尽管这类成员被修饰为private。同时内部类的实例绑定在外部类的实例上,如果在外部类中初始化一个内部类对象,那么该内部类对象就会被绑定在外部类对象上。
- 内部类初始化方式和其他类相同,都是使用new关键字。
- 示例:创建OuterClass类。
- 示例:在内部类中使用this关键字,创建TheSameName类。
- 格式:
- 9.2.2 局部内部类
- 局部内部类是指在类的方法中定义的类,作用域在方法体之内。
- 示例:创建SellOutClass类,在其sell方法中创建局部内部类Apple。
- 9.2.3 匿名内部类
- 不给内部类取名,直接以对象名代替,简化代码增加可读性。
- 基本格式:
return new A(){
-
//类体
}
- 匿名内部类编译后产生“外部类名$序号.class”文件。
- 示例:创建OutString类。
- 9.2.4 静态内部类
- 在内部类前添加符static,则是静态内部类。一个静态内部类中可以声明 static 成员,而非静态内部类中不能声明静态成员。
- 静态内部类的最大特点,就是不可以使用外部类的非静态成员,因此在程序开发中比较少用。
- 可以认为普通的内部类对象隐式地在外部保存了一个引用,指向创建它的外部类对象,但如果内部类被定义为static时,则具有更多的限制。静态内部类具有两个特点:
- 创建静态内部类对象,不需要其外部类对象;
- 不能从静态内部类的对象访问非静态外部类对象。
- 示例:创建StaticInnerClass类。
- 9.2.5 内部类的继承
- 创建OutputInnerClass类,使其继承ClassA中的内部类ClassB:
1 2 3 4 5 6 7 8 9
public class OutputInnerClass extends ClassA.ClassB{ public OutputInnerClass(ClassA a){ a.super(); } } class ClassA{ class ClassB{ } }
- 创建OutputInnerClass类,使其继承ClassA中的内部类ClassB:
- 9.2.6 范例:局部内部类设置闹钟,9_2_6.java;
- 9.2.7 范例:静态内部类求极值,9_2_7.java。
9.3 Class类与Java反射
通过Java反射机制,可以访问已经装载到JVM中的Java对象的描述,实现访问、检测和修改描述Java对象本身信息的功能。在java.lang.reflect包中提供了对该功能的支持。
Java的所有类默认继承了Object类,在Object类中定义了一个getClass方法,该方法返回一个类型为Class的对象,通过该对象可访问类的描述信息:Class textFieldC = textField.getClass();
具体textField对象的组成和成员方法见文中表格。
- 9.3.1 访问构造方法
- 通过下列一组方法访问构造方法时,将返回Constructor类的对象或数组。
- 每个Constructor对象代表一个构造方法,利用Constructor对象可操作对应的构造方法:
getConstructor()
getConstructor(Class<?>...parameterTypes)
getDeclaredConstructor()
getDeclaredConstructor(Class<?>...parameterTypes)
- Constructor类提供的常用方法:略。
- 示例:创建MoreConstructor类,在AccessConstructor中测试。
- 9.3.2 访问成员变量
- 在通过下列一组方法访问成员变量时,将返回Field类型对象或数组。每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量。
getFields()
getField(String name) //访问指定的成员变量
getDeclaredFields()
getDeclaredField(String name) //访问指定的成员变量
- Field类提供的方法:略。
- 示例:创建MoreFields类,在其中声明不同访问权限的成员变量,在AccessFields类中测试。
- 在通过下列一组方法访问成员变量时,将返回Field类型对象或数组。每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量。
- 9.3.3 访问方法
- 通过下列方法访问方法,返回Method类的对象:
getMethods()
getMethod(String name, Class<?>...parameterTypes)
getDeclaredMethods()
getDeclaredMethod(String name, Class<?>...parameterTypes)
- Method类提供的方法:略。
- 示例:略。
- 通过下列方法访问方法,返回Method类的对象:
- 9.3.4 范例:运用反射查看类的成员,创建ClassDeclarationViewer类。
9.4 经典范例
- 利用反射重写toString方法,创建StringUtils类。
第十章 Java集合类
集合可以看作一个容器。Java提供不同的集合类,这些类具有不同的储存对象的方式,并提供相应的方法方便用户对集合进行遍历;通过本章:掌握集合类接口的常用方法,掌握集合类接口的实现类,掌握迭代器的创建和使用。
10.1 集合类概述
- Java的java.util包中提供了一些集合类,这些集合类又称为容器。容器的概念与数组类似,与数组不同在于,集合的长度可变,而Java数组的长度不可变。
- 数组用来存放基本类型的数据,集合用来存放对象的引用。
- 常用的集合有List集合、Set集合、Map集合等,其中List和Set实现了Collection接口。各接口还提供了不同的实现类。
- 上述集合类的继承关系:(向上继承)
- java.lang.Object
Collection
- Set
- HashSet, TreeSet
- List
- ArrayList, LikedList
- Set
Map
- HashMap, TreeMap
- java.lang.Object
10.2 集合类接口的常用方法
Collection接口是层次结构中的根接口。构成Collection的单位称为元素。Collection接口通常不能直接使用,该接口提供添加和删除元素、管理数据的方法。这些方法对其子集合类Set和List是通用的。
- 10.2.1 List接口的常用方法
add(int index, Object obj)
, void, 在指定位置添加对象;addAll(int index, Collection coll)
, boolean, 添加集合类对象;remove(int index)
, Object, 移除指定对象;get(int index)
, Object, 获取指定对象;indexOf(Object obj)
, int, 返回对象第一次出现的索引,不存在返回-1;lastIndexOf(Object obj)
, int, 返回最后一次出现的索引或-1;subList(int formIndex, int toIndex)
, List, 返回元素列表;set(int index, E element)
, Object, 替换指定位置元素并返回原元素;listIterator()
, ListIterator, 返回列表迭代器;- 示例:set()与add()的区别,创建CollectionDemo类;
- 示例:indexOf与lastIndexOf,在上例中添加。
- 10.2.2 Set接口的常用方法
add(Object obj)
, boolean, 如果Set集合中不存在指定元素则添加;addAll(Collection coll)
, boolean, 添加元素集合;remove(Object obj)
, boolean, 将指定对象移出集合;retainAll(Collection c)
, boolean, 保存Set集合与指定集合重复的内容removeAll(Collection c)
, boolean, 移除Set集合与指定集合重复的内容clear()
, void, 清空集合;iterator()
, Iterator, 返回迭代器;size()
, int, 返回元素个数;isEmpty()
, boolean, 返回是否不包含元素;- 示例:创建SetDemo类。
- 10.2.3 Map接口的常用方法
- Map接口提供了将键映射到值的对象。一个映射不能包含重复的键,且每个键只能映射到唯一的值。
- Map接口中的常用方法
put(key k, value v)
, Object, 向集合中添加键值对;containskey(Object key)
, boolean, 返回是否含有某个键;containsValue(Object value)
, boolean, 如果存在一个或多个键映射到指定值,则返回true;get(Object key)
, Object, 返回某个指定键对应的值;keySet()
, Set, 返回所有键组成的Set集合;values()
, Collection, 返回所有值组成的Collection集合;
- 示例:创建MapDemo类。
- 10.2.4 范例:用List集合传递学生信息
- 10.2.5 范例:Map集合二级联动
10.3 集合类接口的实现类
- 10.3.1 List接口的实现类
- 使用List集合,通常需要声明为List类型,然后通过List接口的实现类来对集合进行实例化。List接口的常用实现类有ArrayList和LinkedList。
- ArrayList类,实现了可变数组,允许所有元素,包括null。可以根据索引位置对集合进行快速访问。缺点是向指定索引位置插入对象或删除对象的速度较慢。语法格式如下:
List<String> list = new ArrayList<String>();
- LinkedList类,采用链表结构保存对象。优点是插入和删除对象的速度比ArrayList高。但是对于随机访问集合中的对象,效率较低。语法格式:
List<String> list = new LinkedList<String>();
- 示例:创建Gather类。
- 10.3.2 Set接口的实现类
- 要使用Set集合,通常需要声明为Set类型,然后通过Set接口的实现类来实例化。Set接口的实现类常用有HashSet和TreeSet类。语法格式:
Set<String> set = new HashSet<String>();
Set<String> set = new TreeSet<String>();
- Set集合中的对象是无序的,遍历Set集合的结果与插入Set集合的顺序不同
- 示例:创建People类,并在testPeople类中测试。
- 要使用Set集合,通常需要声明为Set类型,然后通过Set接口的实现类来实例化。Set接口的实现类常用有HashSet和TreeSet类。语法格式:
- 10.3.3 Map接口的实现类
- Map接口常用的实现类有HashMap和TreeMap。通常建议使用HashMap实现Map集合,因为HashMap类实现对于添加和删除映射关系的效率更高。HashMap是基于哈希表的Map接口实现,HashMap通过哈希码对其内部的映射关系进行快速查找。虽然HashMap效率较高,但是集合对象没有对象,而TreeMap类实现的集合对象存在顺序。
- HashMap类,基于哈希表的Map接口实现,该实现提供所有可选的映射操作,并允许使用null和null键,但必须保持键的唯一性。
- TreeMap类,该类不仅实现Map接口,还实现了java.util.SortedMap接口,因此集合中的映射关系具有一定的顺序。但在添加、删除和定位映射关系上性能不如HashMap。由于TreeMap类实现的Map集合中的映射关系是根据对象按照一定顺序排列的,因此不允许键对象为null。
- 示例:创建Emp类,在testEmp类中测试。
- 10.3.4 范例:for循环遍历ArrayList,创建GeneralForDemo类。
- 10.3.5 范例:用动态数组保存学生姓名,略。
10.4 迭代器
- 10.4.1 迭代器的创建和使用
- Iterator接口位于java.util包下。接口定义了三个方法:
hasNext()
|next()
|remove()
:从迭代器指向的collection中移除迭代器返回的最后一个元素。
- 示例:创建ListIteratorDemo类。
- Iterator接口位于java.util包下。接口定义了三个方法:
- 10.4.2 范例:Iterator遍历ArrayList,创建IteratorDemo类。
- 10.4.3 范例:ListIterator遍历ArrayList,创建InverseIteration类。
第十一章 异常处理
11.1 异常概述
异常类的继承关系(不完全):
1
2
3
4
5
Throwable:
Error:
AWTError/ IOErroe/ other subclass...
Exception:
IOException/ RuntimeException/ SQLException/ other subclass...
其中Exception类可以捕获,Error类为不被捕获的严重问题。
11.2 异常的分类
- 11.2.1 可控式异常
- Java中把可以预知的错误,例如文件读取、数据库操作等,在编译时就对程序中可能存在的错误进行处理,并给出具体的错误信息。这类错误称为可控式异常。
- 常用的可控式异常:
- IOException; I/O异常
- SQLException; 数据库访问异常
- ClassNotFoundException; 类没有找到异常
- NoSuchFieldException; 类不包含指定名称的字段时产生的异常
- NoSuchMethodException; 无法找到某一特定的方法时产生的异常
- 示例:创建Example_01类。
- 11.2.2 运行时异常
- 一些错误不能被编译器检测到,例如进行除法运算时除数为零,试图将不是由数字组成的字符串强制转换为整型,等。这些异常称为运行时异常。
- 常用的运行时异常:
- IndexOutOfBoundsException; 集合或数组索引超出范围
- NullPointerException; 当程序在需要对象的地方使用null时发生的异常
- ArithmeticException; 出现异常的运算条件时发生的异常
- IllegalArgumentException; 向方法传递了不合法的参数时发生的异常
- ClassCastException; 试图将对象强制转换为不是实例的子类时发生的异常
- 示例:创建Example_02类。
- 11.2.3 范例:算术异常,创建ExceptionTest类。
- 11.2.4 范例:数组下标越界异常,创建ArrayExceptionTest类。
11.3 获取异常信息
- Java中的java.lang.Throwable类是所有异常类的超类,该类提供了获得异常信息的方法:
- String getLocalizedMessage(); 获得此Throwable的本地化描述
- String getMessage(); 获得此Throwable的详细消息字符串
- void printStackTrace(); 将此Throwable及其栈踪迹输出至标准错误流
- String toString(); 获得此Throwable的简短描述
- 示例:创建Example_03类。
11.4 处理异常
- 11.4.1 使用try-catch处理异常
- 11.4.2 使用try-catch-finally处理异常
1 2 3 4 5 6 7 8
try{ 需要执行的语句 }catch{ 对异常进行处理的语句 }finally{ 一定会被执行的语句 } // 示例:创建Example_04类。
- 11.4.3 使用try-finally处理异常
- 示例;创建Example_05类。
11.5 抛出异常
除了用try-catch-finally处理异常外,还可以用抛出异常。
- 11.5.1 使用throws声明抛出异常
- throws通常用于方法的声明,当方法中可能存在异常,而不想在方法中对异常进行处理时,可以用throws声明抛出异常,然后在其他方法中进行处理
- 声明格式:
极限修饰符 方法名(形参列表) throws 异常类1, 异常类2, ...,异常类n{方法体}
- 异常类可以是Java内置异常类或自定义异常类。
- 示例:创建Example_06类。
- 11.5.2 使用throw语句抛出异常
- 通常系统会自动抛出异常,但是有时希望程序自行抛出异常。
- throw语句常用在方法中,抛出异常的实例,通常与if语句结合使用。
- throw语句格式:
throw new Exception("对异常的说明");
- 示例:创建Example_07类。
- 11.5.3 范例:方法中抛出异常,创建Example_08类。
- 11.5.4 范例:方法上抛出异常,创建Example_09类。
11.6 自定义异常
- 11.6.1 创建自定义异常类
- 创建自定义异常类需要继承自Exception类,并提供一个含有String类型形参的构造方法,该形参就是描述异常的信息,可以通过getMessage方法获取。格式如下:
1 2 3 4 5
public class NewException extends Exception{ public NewException(String e){ super(s); } }
- 创建自定义异常类需要继承自Exception类,并提供一个含有String类型形参的构造方法,该形参就是描述异常的信息,可以通过getMessage方法获取。格式如下:
- 11.6.2 使用自定义异常类
- 示例:创建Example_10类。
11.7 异常的使用原则
- 不要过多使用,会增加系统的负担;
- 使用try-catch语句捕获异常时,需要对异常做出处理;
- 语句块覆盖范围不要太大,这样不利于异常的分析;
- 一个抛出异常的方法被覆盖时,覆盖它的方法必须抛出相同的异常或子异常。
11.8 经典范例
- 数据库操作异常,创建DBExceptionTest公共类。
第十二章 输入输出
将程序创造更改的数据保存到磁盘文件,或在程序运行时读取磁盘文件。通过本章:了解Java中流的概念;掌握输入输出流的分类和使用方法;掌握带缓存的输入输出流的使用法;理解ZIP压缩输入输出流的应用。
12.1 流概述
- “流”是一组有序的数据序列,输入/输出流提供一条通道程序,可以使用这条通道把源中的字节序列送到目的地。
- 源除了磁盘文件,还可以是键盘、鼠标、内存或显示器等。
- 输入流的来源和输出流的目的地:文件、网络、压缩包、其他。
12.2 输入 / 输出流
Java中定义了许多负责输入输出的类,存放在java.io包中。其中所有输入流都是抽象类InputStream(字节输入流)或Reader(字符输入流)的子类;所有输出流都是抽象类OutputStream或Writer的子类。
- 12.2.1 输入流
- InputStream抽象类的子类:AudioInputStream | ByteArrayInputStream | StringBufferInputStreaam | FileInputStream | FilterInputStream | InputStream | ObjectInputStream | SequenceInputStream | PipedIInputStream
- InputStream类的常用方法:(不是所有子类都支持以下所有方法)
read();
从输入流读取下一字节。返回八位字节值。如果没有下一位返回-1read(byte[] b);
从输入流读取指定长度的字节,以整数形式返回字节值mark(int readlimit);
放置输入流失效标记,读取一定字节数后失效reset();
将输入流指针重置到当前所做的标记处skip(long n);
跳过输入流上的n个字节,返回实际跳过的字节数markSupported();
当前输入流是否支持mark和reset操作close();
关闭输入流并释放所有相关的系统资源
- Reader抽象类的子类:CharArrayReader | BufferedReader | FilterReader | InputStreamReader | PipedReader | StringReader
- Reader类的常用方法与InputStream类相似。
- Java中的字符是Unicode编码的,是双字节的。InputStream处理字节的形式用来处理文本不太方便。Reader类在处理字符时更简单。
- 12.2.2 输出流
- OutputStream抽象类的子类:ByteArrayStream | FileOutputStream | FilterOutputStream | ObjectOutputStream | OutputStream | PipedOutputStream
- OutputStream类的常用方法:(均返回void)
write(int b);
将指定字节写入输出流write(byte[] b);
将b.length个字节从指定的byte数组写入输出流write(byte[] b, int off, int len);
将指定byte数组从偏移量off开始写入len个字节flush();
彻底完成输出并清空缓存区close();
关闭输出流
- Writer抽象类的子类:BufferedWriter | CharArrayWriter | FilterWriter | OutputStreamWriter | PipedWriter | PrintWriter | StringWrite
- 12.2.3 范例:显示指定类型的文件,创建FilesList类。
- 12.2.4 范例:查找替换文本文件内容,创建ReplaceTool类。
12.3 File类
File类是java.io包中唯一代表磁盘文件本身的对象,而文件是数据流最常用的数据媒体。File类定义了一些与平台无关的方法来操作文件,如创建、修改、重命名等。
File对象主要用来获取文件信息,如路径、长度、读写权限等。
- 12.3.1 文件的创建和删除
- File类三种创建方式:
new File("C:/....../test.txt");
new File(String parent, String child); //分别代表父路径和子路径
new File(File f, String child); //f代表父路径对象
- 创建时如果指定文件已经存在,可通过delete方法将该文件删除后重建。
- 示例:创建FileTest类。
- File类三种创建方式:
- 12.3.2 获取文件信息
- File类常用方法:
getName();
获取文件名canRead();
是否可读canWrite();
是否可写exists();
是否存在length();
字节长度getAbsulotePath();
获取绝对路径getParent();
获取父路径isFile();
是否存在isDirectory();
是否是一个目录isHidden();
是否隐藏lastModified;
最后修改时间 ·示例:创建FileMethod类。
- File类常用方法:
- 12.3.3 范例:文件批量重命名,创建RenameTool类。
- 12.3.4 范例:批量移动文件,创建FileMoveTool类。
12.4 文件输入 / 输出流
使用文件输入/输出流将内存中的数据永久保存到文件中。
- 12.4.1 FileInputStream与FileOutputStream类
- 分别继承了InputStream和OutputStream类,用于操作磁盘文件。
- 常用的构造方法:
FileInputStream(String name) //形参代表文件名
FileInputStream(File file) //形参为File对象
- 示例:创建FileIOStream类。
- 12.4.2 FileReader类和FileWriter类
- 使用FileOutputStream写文件或者使用FileInputStream读文件时,都是对字节或者字节数组进行读取。由于汉字占两个字节,使用字节流读写容易出现乱码。可以使用FileReader类和FileWriter类。
- 示例:创建ReadNWriteFile类。
- 12.4.3 范例:删除文件夹中的所有文件,创建DeleteAllFile类。
12.5 带缓存的输入 / 输出流
缓存可以说是I/O的一种性能优化。缓存流为I/O流增加了内存缓存区。有了缓存区才可能执行skip(), mark(), reset()等操作。
- 12.5.1 BufferedInputStream类和BuffueredOutputStream类
- BufferedInputStream类可以对任意InputStream类进行带缓存区的包装以达到性能的优化。
- BufferedInputStream类的两个构造函数:
BufferedInputStream(InputStream in); //默认缓存区大小为32字节
BufferedInputStream(InputStream in, int size); //自定义大小
- 从构造函数可以看出,BufferedInputStream对象位于InputStream类之前:
- File –> InputStream –> BufferedInputStream –> 目的地
- BufferedOutputStream类的内容一一对应,多了一个flush()方法,用于将将缓存区的数据强制输出完。flush()方法只对使用了缓存区的OutputStream对象有效,即使不使用flush,在close()之前,系统也会将缓存区的文件刷新到磁盘文件中。
- 12.5.2 BufferedReader类和BuffueredWriter类
- 分别继承Reader类和Writer类,以row为单位进行输入和输出:字符数据–>BufferedWrite–>OutputStreamWriter–>OutputStream–>文件
- BufferedReader类常用方法:
read();
读取单个字符readLine();
读取一行文本,返回为字符串write(String s, int off, int len);
写入字符串的某一部分flush();
刷新该流的缓存newLine();
写入一个行分隔符(换行符)
- 示例:创建BufferedTest类。
- 12.5.3 范例:略。
12.6 数据输入 / 输出流
- 数据输入输出流(DataInputStream和DataOutputStream类)允许应用程序以与机器无关的方式从底层输入流中读取基本Java数据类型。
- 构造方法:
DataInputStream(InputStream in);
DataOutputStream(OutputStream out);
- DataOutputStream类提供了三种写入字符串的方法:
writeBytes(String s);
writeChars(String s);
writeUTF(String s);
- Java中的字符是Unicode编码,是双字节的,writeBytes只将每个字符的低字节写入目标设备中;writeChars将整个字符写入;writeUTF将字符串按照UTF编码后的字节长度写入目标设备,然后再写入UTF编码。
- DataInputStream类只提供了readUTF()方法。因为,在一个连续的字节流中读取一个字符串,如果没有特殊标记作为结尾,无法确定读到什么位置结束。而在DataOutputStream的writeUTF方法中,写入了字符串长度,因此可以通过readUTF准确地读回字符串。
- 示例:创建DataIOStream公共类。
12.7 ZIP压缩输入 / 输出流
使用ZIP压缩文件可以节省储存空间。使用java.util.zip包中的ZipOutputStream和ZipInputStream类可以实现对文件的压缩和解压缩。
Java实现了I/O数据流与网络数据流的单一接口,因此数据的压缩、网络传输和解压缩的实现比较容易。
向ZIP文件内部读取或写入文件,需要找到对应文件的“目录进入点”,通过ZipEntry类实现。
- 12.7.1 压缩文件
- ZipOutputStream类,构造函数:
ZipOutputStream(OutputStream out);
- ZipOutputStream类常用方法:
putNextEntry(ZipEntry e);
开始写入一个新的ZipEntry,并将流内的位置移至此入口所指数据的开头。write(byte[] b, int off, int len);
将字节数组写入当前ZIP条目数据finish();
完成写入并关闭对应的OutputStreamsetComment(String comment);
可设置ZIP文件的注释文字
- 示例:创建writeZIP类。
- ZipOutputStream类,构造函数:
- 12.7.2 解压缩ZIP文件
- ZipInputStream类构造方法:ZipInputStream(InputStream in);
- ZipInputStream类常用方法:
read(byte[] b, int off, int len);
读取目标数组b内off偏移量的位置available();
判断是否已经读取完当前entry的数据,已读完返回0closeEntry();
关闭当前ZIP条目并定位流,以读取下一个条目skip(long n);
跳过当前ZIP条目中指定的字节数getNextEntry();
读取下一个ZipEntry,并将流内的位置移至其开头createZipEntry(String name);
以指定的name创建一个新的entry
- 示例:创建Decompressing类。
- 12.7.3 范例:略。