目录
## 5. IO流
### 5.1 File类
#### 5.1.1 文件对象的构造
这个类对一个文件(夹)的描述。
关于路径分隔符:
路径分隔符是对目录的分隔。表示一层嵌套关系。
在windows系统下,分隔符是:`\`
在UNIX体系下,分隔符是:`/`
| 构造方法 | 参数 |
| -------------------------------- | ------------------------------------------------------------ |
| File(String pathName) | 使用一个指定的文件路径来实例化一个File对象 |
| File(String parent, String name) | 给定一个父目录路径和一个子文件名字,系统会自动的将其拼接在一起 |
| File(File parent, String child) | 给定一个父目录和一个子文件的名字,系统自动拼接路径 |
~~~java
public class FileDemo {
public static void main(String[] args) {
//File构造函数演示
String pathName = "hello.java";
File f1 = new File(pathName);
System.out.println(f1);
File f2 = new File("/Users/IdeaProjects/JavaSE","hello.java");
System.out.println(f2);
//将parent封装成file对象。
File dir = new File("/Users/IdeaProjects/JavaSE");
File f3 = new File(dir,"hello.java");
System.out.println(f3);
}
}
~~~
#### 5.1.2 文件和文件夹的常用方法
| 常用方 | 描述 |
| ----------------------- | -------------------------------------------------- |
| boolean exists() | 用来描述指定的路径下到底有没有文件(夹)存在。 |
| boolean isFile() | 判断指定路径的内容是不是一个文件 |
| boolean isDirectory() | 判断指定路径的内容是不是一个文件夹 |
| boolean mkdir() | 在指定的路径创建文件夹,返回值代表创建成功还是失败 |
| boolean mkdirs() | 在指定的路径创建文件夹,可以创建多级目录 |
| boolean createNewFile() | 在指定的路径创建一个空文件,会有一个IOException |
| boolean isHidden() | 判断一个文件是否是隐藏的 |
~~~java
public static void main(String[] args) throws IOException {
// 对文件或者文件加进行操作。
File file = new File("/Users/IdeaProjects/JavaSE/file.txt");
//获取文件的绝对路径,即全路径
String absPath = file.getAbsolutePath();
//File中封装的路径是什么获取到的就是什么。
String path = file.getPath();
//获取文件名称
String filename = file.getName();
//获取文件大小
long size = file.length();
System.out.println("absPath="+absPath);
System.out.println("path="+path);
System.out.println("filename="+filename);
System.out.println("size="+size);
// 创建文件,如果文件不存在,创建 true 如果文件存在,则不创建 false。
// 如果路径错误,IOException。
boolean file1 = file.createNewFile();
System.out.println("file1=" + file1);
//-----------删除文件操作-------注意:不去回收站。慎用------
boolean flag = file.delete();
System.out.println("flag="+flag);
//-----------需要判断文件是否存在------------
boolean falg1 = file.exists();
System.out.println("falg1="+falg1);
//-----------对目录操作 创建,删除,判断------------
File dir = new File("/Users/IdeaProjects/JavaSE/");
//mkdir()创建单个目录。//dir.mkdirs();创建多级目录
boolean flag2 = dir.mkdir();
System.out.println("flag2="+flag2);
//删除目录时,如果目录中有内容,无法直接删除。
boolean flag3 = dir.delete();
//只有将目录中的内容都删除后,保证该目录为空,这个目录才可以删除。
System.out.println("flag3=" + flag3);
//-----------判断文件,目录------------
File file3 = new File("/Users/IdeaProjects/JavaSE/");
// 要判断是否是文件还是目录,必须先判断存在。
System.out.println(file3.isFile());
System.out.println(file3.isDirectory());
//-----------目录遍历------------
File dir1 = new File("/Users/IdeaProjects");
//获取的是目录下的当前的文件以及文件夹的名称。
String[] names = dir.list();
for(String name : names){
System.out.println(name);
}
//获取目录下当前文件以及文件对象,只要拿到了文件对象,那么就可以获取其中想要的信息
File[] files = dir.listFiles();
for(File file4 : files){
System.out.println(file4);
}
}
~~~
#### 5.1.3 文件过滤器
实现自己的文件过滤器
~~~java
public class FileDemo{
public static void main(String[] args) {
//获取扩展名为.java所有文件
//创建File对象
File file = new File("/Users/IdeaProjects");
//获取指定目录下的文件夹
File[] files = file.listFiles(new FileFileterByDir());
//遍历获取到的所有符合条件的文件
for (File f : files) {
System.out.println(f);
}
}
}
自定义类继承FileFilter过滤器接口
//文件过滤器
class FileFileterByDir implements FileFilter{
public boolean accept(File pathname) {
return pathname.isDirectory();
}
}
~~~
### 5.2 流的分类
分类:
方向:输入流和输出流
数据单元:字节流和字符流
InputStream: 字节输入流的超类
OutputStream: 字节输出流的超类
Reader: 字符输入流
Writer: 字符输出流
无论是使用什么流,在使用结束之后,一定要记得关闭这个流。
### 5.3 字节流
InputStream:
int read(byte[] arr):
参数:从流中读取数据,需要使用到一个字节数组。read方法会将读取到的数据填充到这个字节数组中。所以,读取完成后,我们直接从这个字节数组中取数据即可。
返回值:每次读取数据后,返回这一次读取到了多少个字节的数据。如果这个方法返回值为-1,说明本次没有读取到任何数据,读取完成。
~~~java
class FileInputStreamDemo {
public static void main(String[] args) throws Exception {// 先声明
InputStream is = null;
try {
// 实例化一个流
is = new FileInputStream(new File("/Users/IdeaProjects/JavaSE/src/kaikeba/com/ArraysDemo.java"));
// InputStream: 字节输入流,数据是以字节为单位
// 从管道中读取数据:
// 实例化一个数组,用来存储每次读取到的数据
byte[] contents = new byte[100];
// 用来记录每次读取到了多少数据
int length = 0;
// 循环读取,将每次读取到的数据长度给length赋值,并判断是否为-1
while ((length = is.read(contents)) != -1) {
// 通过一个字节数组实例化一个字符串
String str = new String(contents, 0, length);
System.out.print(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 判断是否为空,因为如果最开始实例化的时候,文件不存在,则is实例化失败,依然为null
// 此时,如果is是null,那么再去关闭的时候,就会出现NullPointerException
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
~~~
outputStream:操作的数据都是字节,定义了输出字节流的基本共性功能方法。
OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件。
FileOutputStream类,即文件输出流,是用于将数据写入 File的输出流。
~~~java
public class FileOutputStreamDemo2 {
public static void main(String[] args) throws Exception {
File file = new File("myfile.txt");
FileOutputStream fos = new FileOutputStream(file, true);
String str = "\r\n"+"kaikeba.com";
fos.write(str.getBytes());
fos.close();
}
}
~~~
### 5.4 字符流
Reader:字符输入流
Writer:字符输出流
写操作
```java
public static void main(String[] args) throws IOException {
//1.创建FileWriter的对象并关联对应的文件
//注意点:
//一:如果只写文件的名字,不写具体路径,默认路径是当前的工程
//二:对于关联的文件,如果之前不存在,程序会自动创建一个,如果存在,会将原来的内容覆盖
//三:可以自己指定路径,但是必须保证路径是真实存在的,否则报异常---FileNotFountException(系统找不到指定的路径。)
FileWriter fileWriter = new FileWriter("fileWrite.txt");
//调用写入方法
//注意点四:在执行write方法时,数据被临时放到了流对象的内部数组中,这个数组是一个字节数组,会默认去查编码表
fileWriter.write("晨晨");
//刷新---将临时数组中的数据放入磁盘
//fileWriter.flush();
//4.关闭流--两个功能:a:关闭流 b:刷新
//第五个注意点:流对象使用完后必须关闭
fileWriter.close();
//第六个注意点:当流对象关闭之后,不能再进行操作,否则会报异常:Stream closed
//fileWriter.write("haha");
}
```
读操作
```java
public static void main(String[] args) throws IOException {
//1.创建文件读入流
FileReader fileReader = new FileReader("/Users/IdeaProjects/JavaSE/src/kaikeba/com/ArraysDemo.java");
//开始读操作
/*
* read():一个字符一个字符的读,每次读出一个字符
*/
//a:将当前的字符读出 b:将当前的指针后移一位
int value;
while ((value = fileReader.read()) != -1) {
System.out.println((char)value);
}
fileReader.close();
}
public static void main(String[] args) throws IOException {
//1.创建文件读入流
FileReader fileReader = new FileReader("/Users/liyunxia/IdeaProjects/JavaSE/src/kaikeba/com/ArraysDemo.java");
//开始读操作
/*
* read(数组):一次可以读出多个字符 ,数组的作用:每次会将读出的字符临时放到这个数组中
*/
/* 数组是临时存放数据的地方,我们会将读到的字符放到临时数组中,数组的大小决定了我们一次可以读到的字符个数.
* 一般这个数组的大小<=1kB
* 返回值代表本次读到的真实的字符个数,如果返回值是-1代表读完了.
*/
char[] cbuf = new char[2];
int num ;
while ((num = fileReader.read(cbuf)) != -1) {
//System.out.println(new String(cbuf)+" num:"+num);
System.out.println(new String(cbuf,0,num)+" num:"+num);
}
fileReader.close();
}
```
### 5.5 转换流
InputStreamReader、OutputStreamWriter
字节=》字符=》字节
转换流:保留了字符流对文本进行操作时候的便利性,保留了字节流的安全性。产生的一种新的流,主要用来做关于文本文件的处理。还可以解决:关于采用了不同字符集的文本之间的处理问题。可以使用指定的字符集来读取一个文本,也可以使用指定的字符集来写一个文本。
OutputStreamWriter
~~~java
public class InputStreamReaderDemo {
public static void writeCN() throws Exception {
//创建与文件关联的字节输出流对象
FileOutputStream fos = new FileOutputStream("OutputStreamWriter.txt");
//创建可以把字符转成字节的转换流对象,并指定编码
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
//调用转换流,把文字写出去,其实是写到转换流的缓冲区中
osw.write("你好");//写入缓冲区。
osw.close();
}
}
~~~
InputStreamReader
~~~java
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
//演示字节转字符流的转换流
readCN();
}
public static void readCN() throws IOException{
//创建读取文件的字节流对象
InputStream in = new FileInputStream("/Users/IdeaProjects/JavaSE/src/kaikeba/com/ArraysDemo.java");
//创建转换流对象
//InputStreamReader isr = new InputStreamReader(in);用本地默认码表读取,可能发生解码的错误
InputStreamReader isr = new InputStreamReader(in,"utf-8");
//使用转换流去读字节流中的字节
int ch = 0;
while((ch = isr.read())!=-1){
System.out.println((char)ch);
}
//关闭流
isr.close();
}
}
~~~
### 5.6 缓冲流
Java提供一套缓冲流,可提高IO流的读写速度;
缓冲流,根据流的分类分类字节缓冲流与字符缓冲流。
BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
BufferInputStream、BufferedOutputStream:
~~~java
public class BufferedStreamDemo {
public static void main(String[] args) throws IOException {
//写数据到文件的方法
write();
read();
}
private static void write() throws IOException {
//创建基本的字节输出流
FileOutputStream fileOut = new FileOutputStream("bufferedStream.txt");
//使用高效的流,把基本的流进行封装,实现速度的提升
BufferedOutputStream out = new BufferedOutputStream(fileOut);
//2,写数据
out.write("hello".getBytes());
//3,关闭流
fileOut.close
out.close();
}
private static void read() throws IOException {
//1,创建缓冲流对象
FileInputStream fileIn = new FileInputStream("bufferedStream.txt");
//把基本的流包装成高效的流
BufferedInputStream in = new BufferedInputStream(fileIn);
//2,读数据
int ch = -1;
while ( (ch = in.read()) != -1 ) {
//打印
System.out.print((char)ch);
}
//3,关闭
in.close();
}
}
~~~
BufferedReader、BufferedWriter
~~~java
public class BufferedWriterReaderDemo {
public static void main(String[] args) throws IOException {
write();
read();
}
private static void write() throws IOException {
//创建流
//基本字符输出流
FileWriter fileOut = new FileWriter("file.txt");
//把基本的流进行包装
BufferedWriter out = new BufferedWriter(fileOut);
//2,写数据
for (int i=0; i<5; i++) {
out.write("hello");
out.newLine();
}
//3,关闭流
out.close();
}
private static void read() throws IOException {
//1,创建流
BufferedReader in = new BufferedReader(new FileReader("file.txt"));
//2,读数据
//一次一个字符
//一次一个字符数组
//一次读取文本中一行的字符串内容
String line = null;
while( (line = in.readLine()) != null ){
System.out.println(line);
}
//3,关闭流
in.close();
}
}
~~~
### 5.7 序列化和反序列化流
用于从流中读取对象的操作流 ObjectInputStream 称为反序列化流
用于向流中写入对象的操作流 ObjectOutputStream 称为序列化流
特点:用于操作对象。可以将对象写入到文件中,也可以从文件中读取对象
~~~java
import java.io.*;
class Person implements Serializable {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
class ObjectStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
writeObj();//对象的序列化。
readObj();//对象的反序列化。
}
public static void writeObj() throws IOException {
//1,明确存储对象的文件。
FileOutputStream fos = new FileOutputStream("object.txt");
//2,给操作文件对象加入写入对象功能。
ObjectOutputStream oos = new ObjectOutputStream(fos);
//3,调用了写入对象的方法。
oos.writeObject(new Person("wangcai",20));
//关闭资源。
oos.close();
}
public static void readObj() throws IOException, ClassNotFoundException {
//1,定义流对象关联存储了对象文件。
FileInputStream fis = new FileInputStream("object.txt");
//2,建立用于读取对象的功能对象。
ObjectInputStream ois = new ObjectInputStream(fis);
Person obj = (Person)ois.readObject();
System.out.println(obj.toString());
}
}
~~~
**注意:**
一个对象要能被序列化,对象所属的类必须实现Serializable接口。否则会发生NotSerializableException异常。
当反序列化对象时,如果对象所属的class文件在序列化之后进行的修改,那么进行反序列化也会发生异常InvalidClassException。发生这个异常的原因如下:该类的序列版本号与从流中读取的类描述符的版本号不匹配/该类包含未知数据类型/该类没有可访问的无参数构造方法.
Serializable标记接口,给需要序列化的类,提供了一个序列版本号:serialVersionUID,该版本号的目的在于验证序列化的对象和对应类是否版本匹配。
静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。
当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient修饰。只要被transient修饰了,序列化时这个属性就不会琲序列化了。
### 5.8 标准输入输出流
System类,定义了一系列有用的属性和方法
System.in、System.out
PrintStream
System.in
结束控制台输入方案:
- 在Windows环境下,需要输入Ctrl+Z;在Linux/Unix/MAC环境下,需要输入Ctrl+D;
- 使用结束条件;
~~~java
public static void main(String[] args) throws IOException {
//创建输入流对象
InputStream is = System.in;
//创建输出流对象
FileWriter fw = new FileWriter("file.txt");
//读取数据
byte[] bys = new byte[1024];
int len;
while((len = is.read(bys))!=-1)
{
fw.write(new String(bys, 0, len));
fw.flush();
}
fw.close();
is.close();
}
~~~
System.out
~~~java
public static void main(String[] args) throws IOException {
//创建输入输出流对象
BufferedReader br=new BufferedReader(new FileReader("file.txt"));
OutputStream os=System.out;
String line;//用于存储读取到的数据
while((line=br.readLine())!=null) {
os.write(line.getBytes());
os.write("\r\n".getBytes());
}
//释放资源
os.close();
br.close();
}
~~~
由于标准输出流是一个字节输出流,所以只能输出字节或者字节数组,但是我们读到的数据则是字符串,如果想进行输出,还需要转换成字节数组,非常麻烦。我们要想通过标准输出流输出字符串,把标准输出流转换成一种字符输出流即可。可以使用转换流OutputStreamWriter。
~~~java
public static void main(String[] args) throws IOException {
//创建输入输出流对象
BufferedReader br=new BufferedReader(new FileReader("file.txt"));
Writer w=new OutputStreamWriter(System.out);//多态,父类引用指向子类对象
//进行数据读写
String line;
while((line=br.readLine())!=null) {
w.write(line);
w.write("\r\n");
}
//释放资源
w.close();
br.close();
}
~~~
还可以结合高效缓冲流使用:
~~~java
public static void main(String[] args) throws IOException {
//创建输入输出流对象
BufferedReader br=new BufferedReader(new FileReader("file.txt"));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
//进行数据读写
String line;
while((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
}
//释放资源
bw.close();
br.close();
}
~~~
### 5.9 打印流
打印流是输出信息最方便的类,注意包含字节打印流:PrintStream和字符打印流:PrintWriter
通过定义的构造方法可以发现,有一个构造方法可以**直接接收OutputStream类的实例,**与OutputStream相比起来,PrintStream可以更方便的输出数据,相当于把OutputStream类重新包装了一下,使之输出更方便。
JAVA对PrintStream功能进行了扩充,增加了格式化输出功能。直接使用Print即可。但是输出的时候需要指定输出的数据类型
1. 提供了一系列重载的print()和println()方法,用于多种数据类型的输出。
2. PrintStream和PrintWriter的输出不会抛出IOException异常。
3. PrintStream和PrintWriter有自动flush功能。
4. PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。 在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。
5. System.out返回的是PrintStream的实例。
PrintStream
~~~java
public static void main(String[] args) throws IOException {
//创建流,绑定输出的目的地
PrintStream ps=new PrintStream("a.txt");
//使用write方法写数据,保持内容不变
ps.write(97);
ps.println();
//使用print方法,会根据平台编码,进行转码工作
ps.println(97);//97->a
ps.println("HelloWorld");//HelloWorld
//释放资源
ps.close();
}
~~~
PrintWriter
~~~java
public static void main(String[] args) throws IOException {
//创建流
//PrintWriter out = new PrintWriter(new FileWriter("printFile.txt"));
PrintWriter out = new PrintWriter("a.txt");
//2,写数据
for (int i=0; i<5; i++) {
out.println("helloWorld");
}
//3,关闭流
out.close();
}
~~~
### 5.10 Properties类
Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
特点:
1. Hashtable的子类,map集合中的方法都可以用。
2. 该集合没有泛型。键值都是字符串。
3. 它是一个可以持久化的属性集。
4. 唯一一个能与IO流交互的集合
5. 有和流技术相结合的方法。
load(InputStream) 把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中
load(Reader)
store(OutputStream,commonts)把集合中的数据,保存到指定的流所对应的文件中,参数commonts代表对描述信息
store(Writer,comments);
6. 常用方法
* public Object setProperty(String key, String value)调用 Hashtable 的方法 put。
* public Set<String> stringPropertyNames()返回此属性列表中的键集,
* public String getProperty(String key)用指定的键在此属性列表中搜索属性
~~~java
//Properties的使用
public class PropertiesDemo01 {
public static void main(String[] args) {
//创建集合对象
Properties prop = new Properties();
//添加元素到集合
//prop.put(key, value);
prop.setProperty("小丽", "大学生");
prop.setProperty("小美", "研究生");
prop.setProperty("小芳", "博士生");
//遍历集合
Set<String> keys = prop.stringPropertyNames();
for (String key : keys) {
//通过键 找值
String value = prop.getProperty(key);
System.out.println(key+"==" +value);
}
}
}
~~~
使用Properties集合,完成把集合内容存储到IO流所对应文件中的操作
~~~java
public class PropertiesDemo02 {
public static void main(String[] args) throws IOException {
//1,创建Properties集合
Properties prop = new Properties();
//2,添加元素到集合
prop.setProperty("小丽", "大学生");
prop.setProperty("小美", "研究生");
prop.setProperty("小芳", "博士生");
//3,创建流
FileWriter out = new FileWriter("prop.properties");
//4,把集合中的数据存储到流所对应的文件中
prop.store(out, "save data");
//5,关闭流
out.close();
}
}
~~~
需求:从属性集文件prop.properties 中取出数据,保存到集合中
~~~java
public class PropertiesDemo03 {
public static void main(String[] args) throws IOException {
//1,创建集合
Properties prop = new Properties();
//2,创建流对象
FileReader in = new FileReader("prop.properties");
//3,把流所对应文件中的数据 读取到集合中
prop.load(in);
//4,关闭流
in.close();
//5,显示集合中的数据
System.out.println(prop);
}
}
~~~
### 5.11 NIO和NIO.2
NIO(New IO):
从 JDK 1.4 开始引入的一个用来替代传统IO的API。NIO与传统的IO具有相同的作用,但是使用的方式是不一样的。NIO是面向缓冲区(Buffe)的、基于通道(Channel)。
从 JDK 1.7 开始加入了一些新的元素。被称作 NIO.2
NIO 和 IO 有什么区别:
- IO是面向流(Stream)的,NIO是面向缓冲区(Buffer)的。
- IO是阻塞型的,NIO是非阻塞型的。
缓冲区Buffer:是一个用来存储基本数据类型的容器。
按照其存储的数据类型不同,缓冲区有着不同的分类:(没有boolean)
ByteBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer、CharBuffer
以上,这些缓冲区有着相同的方法来进行获取和数据的管理。因为所有以上的缓冲区都是继承自Buffer类的。
常用属性和方法:
1,获取缓冲区:不是通过new的方式,而是通过静态方法 allocate(int capacity) 来获取缓冲区。
2,属性:
- capacity: 容量。表示缓冲区最多可以存储多少数据。一旦设置后,将不能改变。
- limit: 界限。表示缓冲区可以操作的数据数量。(实际上存储了多少数据)。
- position: 位置。缓冲区中正在进行操作的数据的位置。
- mark: 使用mark()方法标记的位置。
- mark <= position <= limit <= capacity
3,常用方法:
put():将数据放入缓冲区
get():从缓冲区中获取数据
flip():切换成读模式
rewind():重新读取(position重置为0)
clear():清空缓冲区。将缓冲区中limit和position重置为allocate之后的状态。
clear方法只是重置了一下标记,缓冲区中的数据还在。
mark():在指定的position做一个标记
~~~java
public class FileDemo{
public static void main(String[] args) throws IOException {
// 设置输入源 & 输出目的 = 文件
String infile = "a.txt";
String outfile = "b.txt";
// 1. 获取数据源 和 目标传输地的输入输出流(此处以数据源 = 文件为例)
FileInputStream fin = new FileInputStream(infile);
FileOutputStream fout = new FileOutputStream(outfile);
// 2. 获取数据源的输入输出通道
FileChannel fcin = fin.getChannel();
FileChannel fcout = fout.getChannel();
// 3. 创建缓冲区对象
ByteBuffer buff = ByteBuffer.allocate(1024);
while (true) {
// 4. 从通道读取数据 & 写入到缓冲区
// 注:若 以读取到该通道数据的末尾,则返回-1
int r = fcin.read(buff);
if (r == -1) {
break;
}
// 5. 传出数据准备:调用flip()方法
buff.flip();
// 6. 从 Buffer 中读取数据 & 传出数据到通道
fcout.write(buff);
// 7. 重置缓冲区
buff.clear();
}
}
}
~~~
相关文章:
javaSE(1)基础语法
javaSE(2)面向对象
javaSE(3)常用类
javaSE(4)异常
javaSE(6)多线程
javaSE(7)网络编程