Java第四周学习日记(绪)

1.静态导入

作用:简化书写
静态导入可以作用一个类的所有静态成员
静态导入格式:import static 包名.类名
静态导入要注意的事项:
如果静态导入的成员与本类的成员存在同名的情况下,那么默认使用本类的静态成员,如果需要制定使用静态导入的成员,那么需要在静态成员前面加上类名。


2.增强for循环
增强for循环的作用,简化迭代器的书写格式
增强for循环的适用范围:如果是实现了Iterabl接口的对象或者是数组对象,,都可以使用增强for循环
增强for循环的格式:
for(变量类型 变量名:遍历的目标){

}
增强for循环要注意的事项:
1.增强for循环的底层还是使用了迭代器遍历,只不过不需要我们去获取这个迭代器,所以在使用增强for循环变量元素的过程中不准使用集合对象对集合的元素个数进行修改。
2.迭代器遍历元素与增强for循环遍历元素的区别:使用迭代器遍历集合的元素时可以删除集合的元素,而增强for循环遍历集合的元素时,不能调用迭代器的remove方法删除素。
3.普通for循环与增强for循环的区别:普通for循环可以没有遍历的目标,而增强for循环一定要有遍历的目标。
4.Map集合没有实现Iterable接口,所以map集合不能直接使用增强for循环,如果需要使用增强for循环,需要借助与collection的集合遍历。凡是一个数组对象,内存地址都是以中括号开头的。


3.可变参数
可变参数的格式是:
    数据类型...变量名
可变参数要注意的细节:
    1.如果一个函数的形参使用上了可变参数之后,那么调用该方法的时候可以传递参数也可以不传递参数。
    2.可变参数实际上是一个数组对象。
    3.可变参数必须位于形参中的最后一个。
    4.一个函数最多只能有一个可变参数,因为可变参数要位于形参中的最后一个的位置

4.自动装箱和拆箱
自动装箱:自动把java中的基本数据类型转换成对象类型的数据。
java是面向对象的语言,任何事物都可以使用类进行描述,sun就使用了一些类
自动拆箱:把引用类型的数据转换成基本类型的数据。
描述java中八种基本数据类型标准。
基本数据类型    包装类型
byte                Byte
short              Short
int                  Integer
long                Long
float                Float
double            Double
boolean           Boolean
char               Character

小知识点:Integer类内部维护了缓冲数组,该缓冲数组存储了-127~128这些数据在一个数组中,如果你获取的数据是落入到这个范围之内的,那么就直接从该缓冲区中获取对应的数据。


5.枚举值

  问题:某些方法所接收的数据必须是在固定范围之内的。

  解决方案:自定义一个类,然后私有化构造函数,在自定义类中创建本类的对象来解决。

JDK1.5对以上问题提出了新的解决方案,就是使用枚举类解决。一些方法在运行时,他需要的数据不是任意的,而必须是一定范围内的值,JDK1.5后采用枚举类予以解决。

枚举类的定义格式:

  enum 类名{

      //枚举值

  }

枚举要注意的细节:

  1.枚举类也是一个特殊的类。

  2.枚举值默认的修饰符是public ststic final 。

  3.枚举值的数据类型是枚举值所属的类的数据类型,枚举值是指向了本类的对象的,其实枚举值就是枚举类的对象。

  4.枚举类的构造方法默认的修饰符是private。

  5.枚举类可以定义自己的成员变量与成员函数。

  6.枚举类可以自定义构造函数,但是构造函数的修饰符必须是private,否则就可以随意创建枚举类的对象了,失去了枚举类的存在意义。

  7.枚举类可以存在抽象的方法,但是枚举值必须要实现抽象的方法。

  8.枚举值必须要位于枚举类的第一个语句,否则报错。

 

枚举类的应用:

针对情况:

一些方法在运行时,他需要的数据不是任意的,而必须是一定范围内的值。

  比如:方向  性别  季节  星期

switch语句使用的类型:

  byte  char  short  int  String  枚举类型

enum Season{
    spring,summer,autumn,winter;
}

enum Person2{
    student,worker;
}

public eclass Demo8 {
    public static void main(String[] args) {
        Season season = Season.summer;
        switch(season){
            case spring://只需要写枚举值即可,不需要再声明是该枚举值是属于哪个类的。
                System.out.println("春天...");
                break;
            case summer:
                System.out.println("夏天...");
                break;
            case autumn:
                System.out.println("秋天...");
                break;
            case winter:
                System.out.println("冬天...");
                break;        
        }
    }
}

 

IO流(input output)

 

IO技术主要的作用是用于解决设备与设备之间的数据传输问题。比如说:键盘--->内存  内存的数据--->硬盘  

IO技术的应用场景:

  导出报表,上传大头照,下载,解释xml文件

数据保存到硬盘上,该数据就可以做到永久性的保存。数据一般是以文件的形式保存到硬盘上的。

所以sun就使用了一个File类描述了文件或文件夹的属性数据。

(1)File类的构造方法:

File(File parent, String child) (需要操作同一父文件夹下的不同文件时,使用此构造方法)
          根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
File(String pathname) 指定文件或文件夹的路径创建一个File对象。
          通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(String parent, String child)
          根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。

 目录分隔符:

  在Windows机器上的目录分隔符是\,在Linux机器上的目录分隔符是/。

  使用File下的separator,该常量返回系统默认的分隔符。

  注意:在Windows上,/和\都可以使用作为目录分隔符。而且,如果写/的时候,只需要写一个即可。

public class Demo1 {
    public static void main(String[] args) {
        File file = new File("F:"+File.separator+"a.txt"); //  
        File file = new File("F:/a.txt"); 
        File parentFile = new File("F:\\");
        File file = new File("F:\\","a.txt");
        System.out.println("存在吗 "+ file.exists());  // exists 判断该文件是否存在,存在返回true。否则返回false
        System.out.println("目录分隔符"+ File.separator);
    }
}

(2)File类的常用方法

路径问题:

  绝对路径:该文件在硬盘上的完整路径,绝对路径一般都是以盘符开头的。

  相对路径:资源文件相对于当前程序所在的路径。

  .当前路径

  ..上一级路径

  注意:如果程序当前所在的路径与资源文件不是在同一个盘下面,是没法写相对路径的。

File方法:

创建:
   createNewFile()    在指定位置创建一个空文件,成功就返回true,如果已存在就不创建然后返回false
        mkdir()            在指定位置创建目录(单级文件夹),这只会创建最后一级目录,如果上级目录不存在就抛异常。
        mkdirs()        在指定位置创建目录,这会创建路径中所有不存在的目录。
        renameTo(File dest)    重命名文件或文件夹,也可以操作非空的文件夹,文件不同时相当于文件的剪切,剪切时候不能操作非空的文件夹。移动/重命名成功则返回true,失败则返回false。

import java.io.File;
import java.io.IOException;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        File file = new File("F:\\aa");
        System.out.println("创建成功?+file.createNewFile()); //createNewFile 在指定位置创建一个空文件,成功就返回true,如果已存在就不创建然后返回false
        File dir = new  File("F:\\a.txt");
        System.out.println("创建文件夹"+dir.mkdir()); // mkdir 创建一个文件夹
        dir = new File("F:\\aa\\bb");
        System.out.println("创建多级文件夹"+ dir.mkdirs());
        //renameTo()  如果目标文件与源文件是在同一路径下,那么rename作用是重命名,如果目标文件与源文件不是在同一个路径下,那么rename的作用就是剪切!而且不能操作文件夹,只能操作文件。
        File destFile = new File("F:\\aaaaaaw");
        System.out.println("重命名成功吗"+file.renameTo(destFile)) ; 


删除:
   delete()        删除文件或一个空文件夹,如果是文件夹且不为空,则不能删除,成功返回true,失败返回false。
       deleteOnExit()    在虚拟机终止时,请求删除此抽象路径名表示的文件或目录,保证程序异常时创建的临时文件也可以被删除一般用来删除临时文件,比如酷狗音乐的在线            试听文件。
       两者区别:delete方法会马上删除一个文件,deleteOnExit在jvm退出时才删除。
判断:
   exists()        文件或文件夹是否存在。
        isFile()        是否是一个文件,如果不存在,则始终为false。
        isDirectory()    是否是一个目录,如果不存在,则始终为false。
        isHidden()        是否是一个隐藏的文件或是否是隐藏的目录。
        isAbsolute()    测试此抽象路径名是否为绝对路径名。
 
获取:
  getName()        获取文件或文件夹的名称,不包含上级路径。
  getPath()       返回绝对路径,可以是相对路径,但是目录要指定
  getAbsolutePath()    获取文件的绝对路径,与文件是否存在没关系
  length()        获取文件的大小(字节数),如果文件不存在则返回0L,如果是文件夹也返回0L。
  getParent()        返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回null。
  lastModified()    获取最后一次被修改的时间。
文件夹相关:
  staic File[] listRoots()    列出所有的根目录(Window中就是所有系统的盘符)
  list()                        返回目录下的文件或者目录名,包含隐藏文件。对于文件这样操作会返回null。
  list(FilenameFilter filter)    返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。
  listFiles()                    返回目录下的文件或者目录对象(File类实例),包含隐藏文件。对于文件这样操作会返回null。
  listFiles(FilenameFilter filter)    返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。

IO流技术:

 

IO流分类:

  如果是按照数据的流向划分:

    判断使用输入流还是输出流的依据:以当前程序作为一个参照物,观察数据是流入还是流出,如果流出则使用输出流,如果数据是流入,则使用输入流。

    输入流

    输出流

  如果按照处理的单位划分:

    字节流:读取的都是文件中的二进制数据,读取到的二进制数据不会经过任何的处理。

    字符流:字符流读取的数据是以字符为单位的,字符流也是读取文件中的二进制数据,不过会把二进制数据转换成我们能识别的字符。

        字符流 = 字节流 +解码

字节流:

输入字节流:

————————| InputStream 所有输入字节流的基类 抽象类

——————————|FileInputStream 读取文件数据的输入字节流

使用FileInputStream读取文件数据的步骤:

  1.找到目标文件

  2.建立数据的输入通道(FileInputStream对象)  

  3.读取文件的数据,使用流对象的read()。

  4.关闭资源。

//读取方式一缺点:无法读取完整一个文件的数据
    public static void readTest1() throws IOException{
        //1.找到目标文件
        File file = new File("F:\\a.txt");
        //建立数据的输入通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //读取文件中的数据
        int content = fileInputStream.read(); // read() 读取一个字节的数据,把读取的数据返回。
        System.out.println("读到的内容是"+ (char)content);//若不用char强转,返回的是ascii码值
        //关闭资源,实际上就是释放资源
         fileInputStream.close();
    }

//方法二:使用循环读取文件的数据
    public static void readTest2() throws IOException{
        long startTime = System.currentTimeMillis();
        //找到目标文件
        File file = new File("F:\\1.txt");
        //建立数据的输入通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //读取文件的数据
        int content = 0; //
        while((content = fileInputStream.read())!=-1){
            System.out.print((char)content);
        } 
        //关闭资源
        fileInputStream.close();
    }

//方式三:使用缓冲数组读取    缺点:无法读取完整一个文件的数据,因为数组容量有限。
    public static void readTest3() throws IOException{
        //找到目标文件
        File file = new File("F:\\a.txt");
        //建立数据的输入通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //建立缓冲字节数组,读取文件数据
        byte[] buf = new byte[1024];  //相当于超市里面的购物车  缓冲数组的长度一般是1024的倍数,因为与计算机的处理单位相符
        int length = fileInputStream.read(buf); //如果使用read方法读取数据传入字节数组,那么数据是存储到字节数组中的,而这时候read的返回值表示的是本次读取了几个字节数据到字节数组中。
        System.out.println("length:"+ length);
        //使用字节数组构建字符串
        String content = new String(buf,0,length);
        System.out.println("内容"+ content);
        //关闭资源
        fileInputStream.close();
    }    

//方式四:使用缓冲数组配合循环一起读取
    public static void readTest4() throws IOException{
        long startTime = System.currentTimeMillis();
        //找到目标文件
        File file = new File("F:\1.jpg");
        //建立数据的输入通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //建立缓冲数组配合循环读取文件的数据
        int length = 0; //保存每次读取到的字节个数
        byte[] buf = new byte[1024]; //每次读取1024个,采取覆盖的方式  
        while((length = fileInputStream.read(buf))!=-1){ 
            System.out.print(new String(buf,0,length));
        }
        //关闭资源
        fileInputStream.close();
    }

一般使用第四种。

  问题一:读取完一个文件的数据的时候,是否需要立即释放资源?

  答案:资源文件一旦使用完毕应该马上释放,否则其他的程序无法对该资源进行操作。

 

输出字节流:

————————| OutputStream 是所有输出字节流的父类。抽象类。

——————————| FileOutputStream 向文件输出数据的输出字节流

 

FileOutputStream使用方法:

  1.找到目标文件

  2.建立数据的输出通道

  3.把数据写出

  4.关闭资源

    static void writeDate() throws IOException{
        File file = new File("F://1.txt");
        FileOutputStream fileoutputstream = new FileOutputStream(file);
        String a= "abc";
        byte date[] = a.getBytes();
        fileoutputstream.write(date);
    }

FileOutputStream需要注意的细节:

  1.使用FileOutputStream的时候,如果目标文件不存在,那么会自动创建目标文件对象。

  2.使用FileOutputStream写数据的时候,如果目标文件已经存在,那么会先清空目标文件中的数据,然后再写入数据。(调用另一构造方法即可,如下)

  3.使用FileOutputStream写数据的时候,如果目标文件已经存在,需要在原来数据基础上追加数据的时候应该使用newFileOutputStream(file,true)这一个构造函数

  4.使用FileOutputStream的write方法写数据的时候,虽然接收的是一个int类型的数据,但是真正写书的只是一个字节的数据,只是把低八位的二进制数据写出,其他二十四位数据全部丢弃。

 

IO异常处理

    public static void readTest() {
        FileInputStream fileInputStream = null;
        try {
            // 找到目标文件
            File file = new File("F:\\aaaaa.txt");
            // 建立数据输入通道
            fileInputStream = new FileInputStream(file);
            // 建立缓冲数组读取数据
            byte[] buf = new byte[1024];
            int length = 0;
            while ((length = fileInputStream.read(buf)) != -1) {
                System.out.print(new String(buf, 0, length));
            }
        } catch (IOException e) {
            /*
             * 处理的代码。首先你要组织后面的代码执行,而且需要通知调用者这里出错了
             * throw new RuntimeException(e);
             * 把IOException传递给RuntimeException包装一次,然后再抛出,这样做的目的是为了让调用者使用边的更加灵活。e-cause
             */
            System.out.println("读取文件出错");
            throw new RuntimeException(e);
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                    System.out.println("关闭资源成功");
                }
            } catch (IOException e) {
                System.out.println("关闭资源失败");
                throw new RuntimeException(e);
            }
        }
    }
}

 

缓冲输入字节流:

输入字节流体系:

————————| InputStream 输入字节流的基类,抽象。

——————————| FileInputStream 读取文件数据的输入字节流。

——————————| BufferedInputStream 缓冲输入字节流(凡是缓冲字节流都以Buffer开头)它的出现主要是为了提高读取文件数据的效率。

 

其实该类内部只不过是维护了一个8KB字节的数组。

背景:我们清楚读取文件数据使用缓冲数组读取效率更高,sun公司也知道使用缓冲数组读取效率更高,那么sunge给我们提供了一个——缓冲输入字节流对象,,让我们可以更高效率的读取文件。

效率提高的原因:不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低,而带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多。

使用BufferedInputStream步骤:

  1.找到目标文件

  2.建立数据的输入通道 FileInputStream对象

  3.建立缓冲输入字节流 BufferedInputStream对象,并把FileInputStream传入。

  4.读取文件数据

  5.关闭资源

注意:凡是缓冲流,都不具备读写文件的能力!!!

    static void readDate() throws IOException{
        FileInputStream fileinputStream = new FileInputStream("F:\\1.txt");
        BufferedInputStream bufferedinputstream = new BufferedInputStream(fileinputStream);
        int content = 0 ;
        while((content =  bufferedinputstream.read())!=-1){
            System.out.println((char)content);
        }
        bufferedinputstream.close();
    }

 

缓冲输出字节流

————————| OutputStream  所有输出字节流的基类 抽象类

——————————| FileOutputStream  向文件输出数据的输出字节流

——————————| BufferedOutputStream  缓冲输出字节流  内部也是维护了一个8KB的字节数组而已。

BufferedOutputStream出现的目的是为了提高写数据的效率

使用BufferedOutputStream的步骤:

  1.找到目标文件

  2.建立数据的输出通道

  3.建立缓冲输出字节流对象

  4.把数据写出

BufferedOutputStream要注意的细节:

  使用BufferedOutputStream写数据的时候,它的write方法是先把数据写到它内部维护的字节数组中。如果需要把数据真正的写到硬盘上面,如需要调用flush方法(刷新次缓冲的输出流)或close方法,或者是内部维护的字节数组已经填满数组的时候。

 

 

字符流

输入字符流

字节流:字节流读取的是文件中的二进制数据,读到的数据并不会帮你转换成你看得懂的字符。

字符流:字符流会把读取到的二进制数据进行对应的编码与解码工作,字符流=字节流+解码

输入字符流:

————————|  Reader 输入字符流的基类  抽象类

——————————|  FileReader 读取文件的输入字符流。

——————————|  BufferedReader 缓冲输入字符流。缓冲后输入字符流出现的目的是为了提高读取文件字符的效率和拓展了FileReader的功能。

FileReader的用法:

  1.找到目标文件。

  2.建立数据的输入通道。

  3.读取字符。

  4.关闭资源。

  但是效率低,使用缓冲数组,每次接受数组容量个数的字符。

    public static void readTest2() throws IOException{
        File file = new File("F:\\1208project\\day21\\src\\day21\\Demo1.java");
        FileReader fileReader = new FileReader(file);
        char[] buf = new char[1024];
        int length = 0 ; 
        while((length = fileReader.read(buf))!=-1){
            System.out.print(new String(buf,0,length));
        }
    }

    public static void readTest1() throws IOException{
        File file = new File("F:\\1208project\\day21\\src\\day21\\Demo1.java");
        FileReader fileReader = new FileReader(file);
        int content = 0 ;
        while((content = fileReader.read())!=-1){ 
            System.out.print((char)content);
        }
        fileReader.close();
    }

 

缓冲输入字符流

BufferedReader的使用步骤:

  1.找到目标文件。

  2.建立数据的输入通道。

  3.建立缓冲数组字符流。

  4.读取数据。

  记住:缓冲流都不具备读写文件的能力。

输出字符流

————————|  Write 输出字符流的基类  抽象类

——————————|  FileWriter 向文件输出数据的输出字符流

——————————|  BufferedWriter 缓冲输出字符流  缓冲输出字符流的作用:提高FileWriter的写数据效率与提高FileWriter的功能。

FileWriter的使用步骤:

  1.找到目标文件

  2.建立数据输出通道

  3.写出数据

  4.关闭通道

FileWriter要注意的事项:

  1.使用FileWriter写数据的时候,FileWriter内部是维护了一个1024个字符数组的,写数据的时候回先写入到它内部维护的字符数组中,如果把数据真正写到硬盘上,需要调用flush或者是close方法或者是填满了内部的字符数组。

  2.使用FileWriter的时候,如果目标文件不存在,那么会自动创建目标文件。

  3.使用FileWriter的时候,如果目标文件已经存在了,那么会默认先清空文件中的数据,然后再写入数据,;如果需要在原基础上追加数据,需要使用new FileWriter(File boolean),其中boolean为true。

  字符流具备了解码功能,方便很多。

    public static void  writeTest1() throws IOException{
        File file = new File("F:\\a.txt");
        FileWriter fileWriter = new FileWriter(file,true);
        String data = "大家好";
        fileWriter.write(data);  //
//        fileWriter.flush();
        fileWriter.close();
    }

 

FileReader需要注意的事项:

  使用FileReader字符流copy图片时,会先读取图片的每个值,然后去码表中查找对应的字符,然后在读取该字符,但是当码表中没有改值对应的字符时,会返回一个字节的未知字符对应的数据,会出现原数据与未知字符对应的数据字节长度不对应,这样就会造成照片损坏。

何时使用字符流,何时使用字节流?依据是什么?

  1.读写字符数据的时候使用字符流。

  2.如果读写的数据都不需要转换成字符的时候,使用字节流。

 

缓冲输出字符流

缓冲输出字符流的使用步骤:

  1.找到目标文件

  2.建立数据的输出通道

  3.建立缓冲输出流对象

  4.写出数据

BufferedWriter内部只不过是提供了一个8192长度的字符数据作为缓冲区而已,拓展了FileWriter功能(newLine)

虽然它的write方法形参是char,但是给字符串即可直接输出。

模拟注册登录界面

 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;


public class Welcome {
    static Scanner scanner = new Scanner(System.in);
    public static void main(String[] args) throws IOException {
        while(true){
            System.out.println("请键入指令,a为注册,b为登录");
            String option = scanner.next();
            if("a".equalsIgnoreCase(option)){
                //System.out.println("注册");
                reg();
            }
            else if("b".equalsIgnoreCase(option)){
                //System.out.println("登录");
                login();
            }
            else{
                System.out.println("输入有误,请重新输入");
            }
        }
    }
    
    public static void reg() throws IOException{
        System.out.println("请输入用户名");
        String userName = scanner.next();
        System.out.println("请输入密码");
        String password = scanner.next();
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("F:\\reg.txt"));
        String info = userName+ " " +password;
        bufferedWriter.write(info);
        bufferedWriter.newLine();
        bufferedWriter.close();
    }
    
    public static void login() throws IOException{
        System.out.println("请输入用户名");
        String loginName = scanner.next();
        System.out.println("请输入登录密码");
        String loginPassword = scanner.next();
        BufferedReader bufferedReader = new BufferedReader(new FileReader("F:\\reg.txt"));
        String info = loginName+ " " +loginPassword;
        String line = null;
        boolean isLogin= false;
        while((line=bufferedReader.readLine())!=null){
            if(line.equals(info)){
                isLogin = true;
                break;
            }
        }
        if(isLogin){
            System.out.println("欢迎登陆,登陆成功");
        }
        else{
            System.out.println("该用户名不存在,请重新注册");
        }
    }
}

 

 

对象的输入输出流

作用:用于写对象的信息和读取对象的信息,对象信息一旦写到文件上那么对象的信息就可以做到持久化了。

对象输出流(ObjectOutputStream)

 

对象输入输出流要注意的细节:

  1.如果对象需要被写出到文件上,那么对象所属的类必须要实现Serializable接口,Serializable接口没有任何的方法,只不过是一个标识接口而已。

  对象的序列化:定义方法把对象的信息写到硬盘上。注意,写出来的文件是为了JVM看的,不是给我们看的。

  对象的反序列化:把文件中的对象信息读取出来。

  2.注意:反序列化时创建对象并不会调用构造方法。(对象克隆也不会)所以,创建对象时一定会调用构造方法这句话是错的!

  3.serialVersionUID是用于记录class文件的版本信息打印的,serialVersionUID合格数字是通过一个类的类名,成员,包名,工程名算出的一个数字。

  4.使用ObjectInputStream反序列化的时候,ObjectInputStream会先读取文件中的serialVersionUID,然后与本地的class文件的serialVersionUIDemo进行对比,如果两个ID号不一致,那么反序列化就失败了。

  5.如果序列化与反序列化的时候可能会修改类的成员,那么最好一开始就给这个类指定一个serialVersionUID,如果一类已经指定了UID,那么在序列化和反序列化的时候,JVM就不会再算这个UID了。

  6.如果一个对象的某个数据不想被序列化到硬盘上,可以使用关键字transien修饰。

  7.如果一个类维护了另外一个类的引用,那么另外一个类也需要实现serialzable接口。

class Address implements Serializable{
    
    String country; 
    
    String city;
    
    public Address(String country,String city){
        this.country = country;
        this.city = city;
    }
    
}

class User implements Serializable{
    
    private static final long serialVersionUID = 1L;

    String userName ;
    
    String password;
    
    transient int age;  // transient 关键字
    
    Address address ;
    

    public User(String userName , String passwrod) {
        this.userName = userName;
        this.password = passwrod;
    }
    
    
    public User(String userName , String passwrod,int age,Address address) {
        this.userName = userName;
        this.password = passwrod;
        this.age = age;
        this.address = address;
    }
    
    @Override
    public String toString() {
        return "名字"+this.userName+ " 密码"+ this.password+" 年龄"+this.age+"地址"+this.address.city;
    }
}

public class Demo3 {
    
    public static void main(String[] args) throws IOException, Exception {
        writeObj();
//        readObj();
    }
    
    //把文件中的对象信息读取出来——>对象的反序列化
    public static void readObj() throws  IOException, ClassNotFoundException{
        //找到目标文件
        File file = new File("F:\\obj.txt");
        //建立数据的输入通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //建立对象的输入流对象
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        //读取对象信息
        User user = (User) objectInputStream.readObject(); //
        System.out.println("对象的信息"+ user);
    }
    
    //对象的序列化:定义方法把对象的信息写到硬盘上
    public static void writeObj() throws IOException{
        //
        Address address = new Address("","");
        User user = new User("admin","123",15,address);
        //找到目标文件
        File file = new File("F:\\obj.txt");
        //建立数据的输出通道
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        //建立对象的输入流对象
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        //写对象信息
        objectOutputStream.writeObject(user);
        //关闭通道
        objectOutputStream.close();
    }
}

 

posted @ 2016-09-14 22:10  stubbornnnnnnn  阅读(194)  评论(0编辑  收藏  举报