20155208徐子涵 2016-2017-2 《Java程序设计》第8周学习总结

教材学习内容总结

第14章 NIO与NIO2

14.1 认识NIO

  • NIO概述 NIO使用频道(Channel)来衔接数据节点,在处理数据时,NIO可以设定缓冲区(Buffer)容量,在缓冲区中对感兴趣的数据区块进行标记,像是标记读取位置、数据有效位置,对于这些区块标记,提供了clear()、rewind()、flip()、compact()等高级操作。

  • 下面用NIO的方法来实现10.1.1中的dump()方法,代码如下:

public static void dump(ReadableByteChannel src,WritableByteChannel dest)throws IOException{
ByteBuffer buffer = ByteBuffer.allocate(1024);
try(ReadableByteChannel srcCH = src;WritableByteChannel destCH = dest){
    while(srcCH.read(buffer)!=-1){
        buffer.flip();
        destCH.write(buffer);
        buffer.clear();
    }
}
}

14.2 NIO2文件系统

  • NIO2文件系统API提供一组标准接口与类,应用程序开发者只要基于这些标准接口与类进行文件系统操作,底层实际如何进行文件系统操作,是由文件系统提供者负责(由厂商操作)。

  • 应用程式开发者可以通过java.nio.file套件中FileSystems、Paths、Files等类提供的静态方法,取得相关操作对象或进行各种文件系统操作,这些静态方法内部会运用FileSystemProvider来取得所需的操作对象,完成应有的操作。

第十五章 通用API

15.1 日志

java.util.logging 包提供了日志功能相关类与接口,不必额外配置日志组件,就可在标准Java平台使用是其好处。使用日志的起点是Logger类,要取得Logger实例,必须使用Logger的静态方法getLogger()。如:

Logger logger = Logger.getLogger("cc.openhome.Main"); 调用getLogger()时,必须指定Logger实例所属名称空间,名称空间以“.”作为层级区分,名称空间层级相同的Logger,其父Logger组态相同。

Logger是记录信息的起点,要输出的信息,必须先通过LoggerLevelFilter过滤,再通过HandlerLevelFilter过滤,格式化信息的动作交给Formatter,输出信息的动作实际上是Handler负责。

负责日志输出的是Handler实例,Handler的子类有MemoryHandlerStreamHandlerStreamHandler的子类有ConsoleHandler、FileHandler和SocketHandler

Formatter的子类有XMLFormatter和SimpleFormatter,FileHandler默认的Formatter是XMLFormatter,ConsoleHandler默认则使用SimpleFormatter。

如果要自定义Handler,可以继承Handler类,操作抽象方法publish()、flush()、close()。

如果要自定义Formatter,可以继承Formatter后操作抽象方法formatter(),这个方法会传入LogRecord,储存所有日志信息。例如,将ConsoleHandler的Formatter设定为自定义的Formatter:

import java.time.Instant;
import java.util.logging.*;

public class FormatterDemo {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(FormatterDemo.class.getName());
        logger.setLevel(Level.CONFIG);
        ConsoleHandler handler = new ConsoleHandler();
        handler.setLevel(Level.CONFIG);
        handler.setFormatter(new Formatter() {
            @Override
            public String format(LogRecord record) {
                return "日志来自 " + record.getSourceClassName() + "."
                        + record.getSourceMethodName() + "\n"
                        + "\t层级\t: " + record.getLevel() + "\n"
                        + "\t信息\t: " + record.getMessage() + "\n"
                        + "\t时间\t: "  + Instant.ofEpochMilli(record.getMillis())
                        + "\n";
            }
        });
        logger.addHandler(handler);
        logger.config("自定义 Formatter 信息");
    }
}

可以通过logging.properties来设定Logger组态,启动JVM时,指定java.util.logging.config.file系统属性为.properties名称。

15.2 国际化基础

  • 对于日后可能变动的文字信息,可以考虑将信息移至程序之外,方法是使用ResourceBundle来做信息绑定。首先要准备一个.properties文档,如messages.properties,而文档内容如下:
cc.openhome.welcome=Hello
cc.openhome.name=World
.properties文档必须放置在CLASSPATH的路径设定下,文档中撰写的是键/值配对,之后在程序中可以使用键来取得对应的值。例如:

import static java.lang.System.out;
import java.util.ResourceBundle;

public class Hello {
    public static void main(String[] args) {
        ResourceBundle res = ResourceBundle.getBundle("messages");
        out.print(res.getString("cc.openhome.welcome") + "!");
        out.println(res.getString("cc.openhome.name") + "!");
    }
}
  • 国际化的三个重要概念是地区信息、资源包与基础名称。地区信息的对应类是Locale,ResourceBundle对象是JVM中资源包的代表对象。代表同一组信息但不同地区的各个资源包会共享相同的基础名称,使用ResourceBundle的getBundle()时指定的名称,就是在指定基础名称。

  • 地区信息代表了特定的地理、政治或文化区,地区信息可由一个语言编码与可选的地区编码来指定。其中语言编码由两个小写字母代表,如zh表示中文;地区编码则由两个大写字母表示,如TW表示我国台湾。

  • 使用ResourceBundle时,如何根据基础名称取得对应的信息文档:

(1)使用指定的Locale对象取得信息文档。 (2)使用Locale.getDefault()取得的对象取得信息文档。 (3)使用基础名称取得信息文档。

15.3 规则表达式

规则表示式基本上包括两种字符:字面意义字符与元字符。字面意义字符是指按照字面意义比较的字符;元字符是不按照字面比较,在不同情境有不同意义的字符。

规则表示式主要用于字符、字符串格式比较,java.util.regex.Pattern实例是规则表示式在JVM中的代表对象,必须通过Pattern的静态方法compile()来取得,可以使用matcher()方法指定要比较的字符串,这会返回java.util.regex.Matcher实例,表示对指定字符串的比较器。

教材学习中的问题和解决过程

问题: 针对P481 Hello.java提出的问题(如下)有疑惑:

messages.properties放什么位置?

研究ResourceBundle类。

解决过程:

通过学习教材,得到如下解释:

properties文档必须放置在CLASSPATH的路径设定下。

ResourceBundle的静态getBundle()方法会取得一个ResourceBundle的实例,所给定的自变量名称是信息文档的主文件名,getBundle()会自动找到对应的.properties文档,取得ResourceBundle实例后,可以使用getString()指定键来取得文档中对应的值,如果日后想要改变现实的信息,只要改变.properties文档的内容就可以了。

代码调试中的问题和解决过程

本周无问题

代码托管截图

其他(感悟、思考等,可选)

这周的学习目标主要是第十五章,需要我们学会使用日志API、了解国际化基础、认识JDK8增强功能等。通过前面几周的学习,java的核心知识与难点之前都已经学完了,后面的章节大概都是介绍一些类的应用。在以后的学习中,将会把重点放在实验博客的撰写上面,感觉实验才是检验学习的真正方法和途径,希望自己能够认真的完成老师布置的每次实验。

上周错题总结

  • 错题1: 哪些Linux 命令可以ASCII码和16进制单字节方法输出Hello.java的内容?

    od -tcx1 Hello.java和od -tc -tx1 Hello.java

  • 错题2: JDK8中的(Stream API),可以用来实现管道操作

  • 错题3 JDK8 中新时间API中,用于度量时间的类有() A .Instant B .Duration C .Period D .LocalDateTime

    答案:BC

点评过的同学博客和代码

学号1

学号2

学号3

学号4

学号5

学习进度条

 代码行数(新增/积累)博客量(新增/积累学习时间(新增/累积)
目标 5000行 30篇 400小时
第一周 16/16 1/1 8/8
第二周 120/120 2/2 12/12
第三周 130/150 1/1 9/9
第四周 180/200 1/1 15/15
第五周 150/300 1/1 12/12
第六周 120/300 1/1 8/8
第七周 300/300 2/2 10/10
第八周 100/300 1/1 7/7

参考资料