• Java IO的flush


    Java的IO是一个大知识点,
    如果把它的知识点拆开来说的话估计能说一个星期,关于IO的体系可以看看下面这张图,
    (图片是网上找的,侵删)

    图片

    接下来我们从一段代码开始聊吧,先看看下面这段代码

    public class Test {
       public static void main(String[] args) throws Exception {
           File file = new File("text.txt");
           if(!file.exists()) {
               file.createNewFile();
           }
           FileOutputStream fos = new FileOutputStream(file);
           BufferedOutputStream bos = new BufferedOutputStream(fos);
           byte[] b = new byte[1024];
           bos.write(b);
           bos.flush();
       }
    }

    代码中构造了一个缓冲流,然后往流里写入一个KB长度的数据,最后调用 flush()方法。
    这是很简单的一段代码,最终的输出结果是会生成一个 1KB的 text.text文件。

    但如果我们把最后一行注释掉的话,

    //bos.flush();

    最终生成的 text.text大小会变成0.
    这个结果是很显然的,不过如果我们把 flush()换成 close()的话,结果是不是还会是 0呢?

    关于 flush

    flush()这个东西,其实在很久以前的网络传输中就有了,
    那个时候为了效率,服务器和客户端传输数据的时候不会每产生一段数据就传一段数据,
    而是会建一个缓冲区,在缓冲区满之后再往客户端传输数据,

    图片

    有时候会有这样的问题,当数据不足以填充缓冲区,而又需要往客户端传数据,
    为了解决这个问题,就有了 flush的概念,将缓冲区的数据强迫发送。

    回到上面的问题,如果把 flush换成 close是否可行呢,
    答案是可以的。
    如果看源码就知道 BufferedOutputStream的继承关系,

    public class BufferOutputStream extends FilterOutputStream

    BufferedOutputStream没有实现 close()方法,所以会直接调用 FilterOutputStream的 close(),
    而 FilterOutputStream的 close()方法会调用 flush()来输出缓冲区数据。
    实际开发中关于IO操作的,都强调最后要调用 close()方法,
    上面的例子就是其中一个原因了。

    关于Enum的再次理解

    问:enum 算不算基本数据类型
    答:不算,enum是引用类型。

    Java中的基本数据类型只有8种,分别是
    byte、short、int、long、float、double、char、boolean

    在 Java5之后新增的 Enum属于引用类型,跟 String一样也是属于类。
    好奇的同学可能有疑问,既然说 enum是引用类型,为何在使用的时候没有见到类呢?

    enum的使用场景

    我们先来看一个简单的enum使用场景,

    public class DayDemo {

       public enum Day {
         MONDAY,
         TUESDAY,
         WEDNESDAY,
         THURSDAY
       }

       public static void main(String[] args) {

       }
    }

    这里面只定义了一个枚举类型 Day,
    通过枚举定义了周一到周四四种类型,后续我们使用的时候就可以直接用 Day.MONDAY 这样的方式来使用枚举值了。

    为什么说枚举是类

    在这代码里没有声明类,也没用其他的引用,
    那么来看看编译后的结果

    $ ls
    'DayDemo$Day.class'   DayDemo.class   DayDemo.java

    可以看到多了一个叫 DayDemo$Day.class的类出来,
    从 class文件可以看出, 枚举 Day编译成了一个类,从这里可以断定虽然我们没有定义这个类,
    但是编译器会把枚举作为类进行编译,从某种角度上来说 enum是一种语法糖,
    现在来看一下 class文件的构造,

    public final class DayDemo$Day extends java.lang.Enum<DayDemo$Day> {
     public static final DayDemo$Day MONDAY;

     public static final DayDemo$Day TUESDAY;

     public static final DayDemo$Day WEDNESDAY;

     public static final DayDemo$Day THURSDAY;

     public static DayDemo$Day[] values();
       Code:
          0: getstatic     #1                  // Field $VALUES:[LDayDemo$Day;
          3: invokevirtual #2                  // Method "[LDayDemo$Day;".clone:()Ljava/lang/Object;
          6: checkcast     #3                  // class "[LDayDemo$Day;"
          9: areturn

     public static DayDemo$Day valueOf(java.lang.String);
       Code:
          0: ldc           #4                  // class DayDemo$Day
          2: aload_0
          3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
          6: checkcast     #4                  // class DayDemo$Day
          9: areturn

     static {};
       Code:
          0: new           #4                  // class DayDemo$Day
          3: dup
          4: ldc           #7                  // String MONDAY
          6: iconst_0
          7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
         10: putstatic     #9                  // Field MONDAY:LDayDemo$Day;
         13: new           #4                  // class DayDemo$Day
         16: dup
         17: ldc           #10                 // String TUESDAY
         19: iconst_1
         20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
         23: putstatic     #11                 // Field TUESDAY:LDayDemo$Day;
         26: new           #4                  // class DayDemo$Day
         29: dup
         30: ldc           #12                 // String WEDNESDAY
         32: iconst_2
         33: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
         36: putstatic     #13                 // Field WEDNESDAY:LDayDemo$Day;
         39: new           #4                  // class DayDemo$Day
         42: dup
         43: ldc           #14                 // String THURSDAY
         45: iconst_3
         46: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
         49: putstatic     #15                 // Field THURSDAY:LDayDemo$Day;
         52: iconst_4
         53: anewarray     #4                  // class DayDemo$Day
         56: dup
         57: iconst_0
         58: getstatic     #9                  // Field MONDAY:LDayDemo$Day;
         61: aastore
         62: dup
         63: iconst_1
         64: getstatic     #11                 // Field TUESDAY:LDayDemo$Day;
         67: aastore
         68: dup
         69: iconst_2
         70: getstatic     #13                 // Field WEDNESDAY:LDayDemo$Day;
         73: aastore
         74: dup
         75: iconst_3
         76: getstatic     #15                 // Field THURSDAY:LDayDemo$Day;
         79: aastore
         80: putstatic     #1                  // Field $VALUES:[LDayDemo$Day;
         83: return
    }

    如果上面的代码不够简洁易懂的话可以看看下面翻译后的代码,
    这只翻译 static代码段,其他的像 values和 valueOf都比较简单,

    static
       {
           //实例化枚举实例
           MONDAY = new Day("MONDAY", 0);
           TUESDAY = new Day("TUESDAY", 1);
           WEDNESDAY = new Day("WEDNESDAY", 2);
           THURSDAY = new Day("THURSDAY", 3);
           $VALUES = (new Day[] {
               MONDAY, TUESDAY, WEDNESDAY, THURSDAY
           });
       }

    总结

    把这段代码和上面反编译的结果一起看的话就可以明白,
    枚举类型在编译后会作为一个类生成,
    编译器会帮我们插入 values和 valueOf 两个方法,
    同时生成 final的常量,
    在生成的静态代码段里会实例化好对应的枚举实例,
    换句话说,我们所定义的每个枚举类,最终都会在它里面生成对应的静态常量,而常量的值就是我们所定义的值的String串。

    Java中如何操作超大数

  • 相关阅读:
    什么时候加上android.intent.category.DEFAULT和LAUNCHER
    android中跨进程通讯的4种方式
    Unix Sockets in Go
    android Service 跨进程通信
    Android Activity和Intent机制学习笔记
    AIR 移动设备上的存储控制
    AIR Android开发APK结构详解
    android 内存管理
    Android权限大全
    运营商登录付费接入ANE打包心得
  • 原文地址:https://www.cnblogs.com/Chary/p/16202167.html
Copyright © 2020-2023  润新知