20145226夏艺华 《Java程序设计》第8周学习总结

教材学习内容总结

学习目标

  1. 了解NIO

  2. 会使用Channel、Buffer与NIO2

  3. 会使用日志API、国际化

  4. 会使用正则表达式

  5. 了解JDK8增强功能

第14章 NIO与NIO2

14.1 认识NIO

(1)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();
    }
}
}

(2)Channel架构与操作
Channel接口是AutoClosable的子接口,主要是增加了isOpen()方法来确认Channel是否开启,下图为Channel的继承架构:

ReadableByteChannel定义了read()方法负责将ReadableByteChannel中的数据读取至ByteBuffer;
WritableByteChannel定义了write()方法,负责将ByteBuffer的数据写到WritableByteChannel中;
ScatteringByteChannel定义了read()方法,负责将ScatteringByteChannel分配到ByteBuffer数组中;
GatheringByteChannel定义了write()方法,负责将ByteBuffer的数据写到GatheringByteChannel中。

要想取得Channel的操作对象,可以使用Channels类。

(3)Buffer架构与操作
Buffer是个抽象类,定义clear()、flip()、reset()、rewind()等对数据区域块的高级操作,操作的返回类型均为Buffer,所以在连续高级操作时,可形成管线操作风格。Buffer的类继承架构如下图所示:

可根据不同的数据类型处理需求来选择不同的的Buffer子类,他们都是抽象类,不能直接实例化。Buffer的所有直接子类们都有个allocate()静态方法,可以让你指定Buffer容量(Capacity)。Buffer是个容器,填装的数据不会超过它的容量。

14.2 NIO2文件系统

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

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

第15章 通用API

15.1 日志

(1)日志API简介

java.util.logging包提供了日志功能相关类与接口,Logger类的构造函数标示为protected,不是java.util.logging同包的类不能直接以new创建,要取得Logger实例,必修使用Logger的静态方法getLogger()。取得Logger实例后,可用log()方法输出信息,输出时可用Level的静态成员制定信息层级(Level)。具体的代码实例如下:

public class LoggerDemo {
	public static void main(String[] args) {
		Logger logger = Logger.getLogger(LoggerDemo.class.getName());
		
		logger.log(Level.WARNING, "WARNING信息");
		logger.log(Level.INFO, "INFO信息");
		logger.log(Level.CONFIG, "CONFIG信息");
		logger.log(Level.FINE, "FINE信息");
	}
}

运行结果如下:

(2)指定日志层级

Logger与Handler预设都会先依Level过滤信息,如果没有做任何修改,取得的Logger实例之父Logger组态,就是Logger.GLOBAL_LOGGER_NAME名称空间Logger实例的组态,这个实例的Level设定为INFO,可通过Logger实例的getParent()取得父Logger实例,可通过getLevel()取得设定的Level实例。

Logger可通过setLevel()来设定Level实例,若log()时指定的Lever实例内含的int值小于Logger设定的Lever实例内含的int值,Lever就不会记录信息。

在经过Logger过滤之后,还得再经过Handler的过滤,一个Logger可以拥有多个Handler,可通过Logger的addHandler()新增Handler实例。实际上进行信息输出时,目前Logger的Handler处理完,还会传播给父Logger的所有Handler处理,可通过getHandlers()方法取得目前已有的Handler实例数组。例如:

public class LoggerDemo2 {
	public static void main(String[] args) {
		Logger logger = Logger.getLogger(LoggerDemo2.class.getName());
		logger.setLevel(Level.FINE);
		for(Handler handler : logger.getParent().getHandlers()){
			handler.setLevel(Level.FINE);
		}
		
		logger.log(Level.WARNING, "WARNING信息");
		logger.log(Level.INFO, "INFO信息");
		logger.log(Level.CONFIG, "CONFIG信息");
		logger.log(Level.FINE, "FINE信息");
	}
}

运行结果如下:

这样FINE级及以上的log均能打印出来。

(3)使用Handler与Formatter

Handler负责日志输出。Logger可以使用addHandler()新增Handler实例,使用removeHandler()移除Handler。

Logger与Handler默认只会根据层级过滤信息。Logger与Handler都有setFilter()方法,可以指定Filter操作对象,当然也可以添加额外的过滤条件来操作Filter接口。

15.2 国际化基础

在不修改应用程序情况下,根据不同用户直接采用不同语言、日期格式等,这样的设计考虑称为国际化,简称i18n。

(1)使用ResourceBundle

对于以后可能变动的文字信息,可考虑将信息移至程序外,方法是使用ResourceBundle来完成信息绑定。

ResourceBundle的静态getBundle()方法会取得一个ResourceBundle的实例,所给定的自变量名称是信息文档的主文件名,getBundle()会自动找到对应的.properties文档,取得ResourceBundle实例后,可以使用getString()指定键来取得。

(2)使用Locale

国际化的三个标准是地区(Locale)信息、资源包(Resource bundle)与基础名称(Base name)。

地区信息的对应类是Locale,在建立Locale实例时,可指定语言编码与地区编码,例如,建立代表台湾繁体中文的Locale,例如:

Locale locale = new Locale("zh","TW");

资源包中包括了特定地区的相关信息。

15.3 规则表达式

(1)规则表示式简介

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

例如使用String的split()方法返回切割后各字符串组成的String数组。

  • 字面意义字符

字母和数字在规则表示式中都是按照字面意义比较的,有些字符之前加上\之后会被当做元字符。
元字符在规则表示式中有特殊意义,比较标点时可以在每个符号前加上\。

  • 字符类

规则表示式中,多个字符可以分归在一起,成为一个字符类,会比较文字中是否有任一个字符符合字符类中某个字符。
归类字符的方式之一是将字符放于[]中。

  • 贪婪、逐步、独吐量词

{n}是贪婪量词表示法的一种,表示前面的量词出现n次,会尽可能找出长度最长的符合文字。
在贪婪量词表示法后加上?,将会成为逐步量词,会尽可能找出长度最短的符合文字。
在贪婪量词表示法后加上+,将会成为独吐量词,没有任何文字符合。

  • 边界比较

边界比较用来表示文字必须符合指定的边界条件,也就是定位点,因此这类表示式也常称为锚点。

  • 分组与参考

可以使用()来将规则表示式分组,除了作为子规则表示式之外,还可以搭配量词使用。
分组回头参考时,是在\后加上分组计数,表示参考第几个分组的比对结果 。

(2)Pattern与Matcher

在程序中使用表示式,必须先针对规则表示式做剖析、验证等动作,确定规则表示式语法无误,对字符串进行比较。

java.util.regex.Pattern实例是规则表示式在JVM中的代表对象,Pattern的构造函数被标示为private,必须通过Pattern的静态方法compile()来取得。

15.4 JDK8 API增强功能

(1)StringJoiner、Arrays新增API

String新增join()静态方法可以指定每个字符串间以逗号分隔进行连接。

Arrays上新增parallelPrefix()、parallelSetAll()与parallelSort()方法.

(2)Stream相关API

若想对数组进行管线化操作,方法一是使用Arrays的asList()方法返回List,而后调用stream()方法取得Stream实例;另一个方法是使用Arrays的stream()方法,可以指定数组后返回Stream实例。

CharSequence上新增了chars()和codePoints()方法,都是返回intStream。

Math在JDK8中也新增了不少数学运行相关API。

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

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

在本次代码运行中没有发现什么问题。

本周代码托管截图

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第二周 200/400 1/3 12/52
预备作业 0/400 1/4 15/67
第三周 500/900 1/5 10/77
第四周 500/1500 1/6 15/92
第五周 500/2000 1/7 20/112
第六周 500/2500 2/9 20/132
第七周 500/3000 2/11 30/162
第八周 500/2000 2/13 20/182
posted @ 2017-02-10 22:54  夏艺华20145226  阅读(302)  评论(4编辑  收藏  举报