您的位置:首页 > 编程语言 > Java开发

Thinking in Java 笔记11-20

2015-07-09 16:40 495 查看
12 Java的基本理念是 “结构不佳的代码不能运行”

12.2.1 异常参数

所有标准异常类都有两个构造器:一个默认构造器,一个接受字符串作为参数

能够抛出任意类型的Throwable对象,是异常类型的根基。

12.3.2

异常处理理论有两种基本模型:

终止模型:这种错误非常关键,以至于无法恢复。

恢复模型:修正错误

12.4 System.err不会被重定向

12.5 异常说明

throws语句用于说明方法可能会抛出的所有异常

如果方法里产生了异常却没有处理,那么编译器将会提示你:

处理这个异常

或在异常说明里表明方法会产生异常

这种在编译时被强制检查的异常被称作被检查的异常

12.6 重新抛出异常

重抛异常会把异常抛给上一级环境中的异常处理程序

12.7

RuntimeException如果没有被捕获而直达main,那么程序退出前将调用异常的printStackTrack方法

12.9 异常的限制

当覆盖方法的时候,只能抛出基类方法的异常说明里列出的那些异常。

异常限制对构造器不起作用

派生类构造器不能捕获基类构造器抛出的异常

12.12 其他可选方式

异常代表了当前方法不能继续执行的情形

重要原则 — 只有在你知道如何处理的情况下才捕获异常

一个目的 — 把错误代码和错误发生代码分离

12.13 异常使用指南

在下列情况使用异常:

在恰当级别处理问题(在知道如何处理情况下才捕获异常)

解决问题并重新调用产生异常的方法

进行少许修补,然后绕过异常发生的地方继续进行

用别的数据进行计算,以替代方法预计会返回的值

把当前环境能做的事尽量做完,然后把相同/不同的异常抛向更高层

终止程序

进行简化

让类库和程序更加安全

13.3

如果想要打印出对象的内存地址,应该调用Objects.toString方法

不应该使用this,而应该调用super.toString方法

13.5.3 Formatter类

Java所有新的格式化功能都由java.util.Formatter类处理。

当创建一个Formatter时,需要对其构造器传递一些信息,告诉它最终结果的输出位置

13.5.6 String.format方法

返回一个String

实际也是创建了一个Formatter对象

更加清晰易懂

13.6 正则表达式

String类内建功能

match方法

split方法

13.6.3 量词

贪婪型 — 尽可能多的匹配

勉强型 — 尽可能少的匹配

占有性(Java仅有)— 防止回溯,常用于正则表达式失控,可使正则表达式执行起来更加有效

13.6.4 Pattern和Matcher — 以后研究API

13.7.1 Scanner定界符

useDelimiter方法 — 传入一个正则表达式

hasnext方法也可以传入正则表达式来扫描

14.2 Class对象

包含了类有关的信息

每当编写并编译一个新类,就会产生一个Class对象

为了生成这个类的对象,运行这个程序的JVM将会使用类加载器这个子系统

包含一条类加载器链,但只有一个原生类加载器 — JVM实现一个部分

原生类加载器加载所谓的可信类

包括Java API类

当程序创建第一个对类的静态成员的引用时,就会加载这个类。

动态加载使能在C++这样的静态加载语言中是很难实现的活着根本不可能复制

类加载器首先检查Class对象是否加载。

如果尚未加载,默认的类加载器就会根据类名查找.class文件

这个类的字节码被加载时,会接受验证,确保其没有被破坏,并不包含不良Java代码

一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象。

Class.forName方法是取得Class对象的引用的一种方法。

副作用 — 如果要求加载的类还没加载就加载,在加载中,其static字句就被执行

如果找不到类则抛出ClassNotFoundException

Class.forName不需要你有一个对象引用就能创建Class对象

getClass方法通过该类型对象引用返回Class对象

属于Object类一部分。

14.2.1 类字面常量 — XXX.class

第三种获得Class对象的引用的方法

安全,简单,高效

编译时受到检查

不仅可以应用于普通的类,还可以应用于接口,数组以及基本数据类型

对于基本数据类型的包装类,还有标准字段TYPE — 一个引用,指向对应数据类型的Class对象

原生数据类型.class == 对应包装类类型.TYPE

建议使用.class形式 保持一致性

为使用类而做的准备工作包含3个步骤

加载

类加载器执行

查找字节码

创建Class对象

链接

检验类的字节码,为静态域分配存储空间

如果必需,解析类创建的对其他类的所有引用

初始化

如果类有超类,则对其初始化

执行静态初始化器和静态初始化块

被延迟到对静态方法或者非常数静态域进行首次引用时执行

使用.class语法来获得类的引用不会引发初始化。

Class.forName方法立即进行初始化。

如果一个static final值是一个编译期常量,不需要初始化就可以读取

如果域设置为static和final,还不足以确保这种行为,因为它还不是一个编译期常量

如果是static而不是final的,那么对它进行访问时,就要进行链接和初始化

14.2.2 泛化的Class引用

普通的类应用不会进行类型检查,只要是Class类型就行

然而泛化的Class则能够进行类型检查

泛化的Class引用优于非泛化的

向Class引用添加泛化语法的原因仅仅是为了提供编译期类型检查

Class

final域在遭遇修改时是安全的。运行时系统会在不抛异常的情况下接受任何修改尝试,但是实际上不会发生任何修改

15.2 简单泛型

与其使用Object,我们更喜欢暂时不指定类型。

15.2.1 元组类库

元组 — 将一组对象直接打包存储于其中的一个单一对象。

允许读取其中元素

但不允许向其中存放新的对象

也称为数据传送对象或行使

15.3 泛型接口

泛型也可以应用于接口

可以在类中包含参数化方法 所在类也可以是泛型类,或不是。

指导原则:

无论何时,只要能做到,你就应该尽量使用泛型方法

如果使用泛型方法可以取代将整个类泛型化,那么就应该使用泛型方法,因为可以使事情更加清楚明白

对于static方法,无法访问泛型类的参数类型

如果要使static方法需要使用泛型能力,就必须使其成为泛型方法

要定义泛型方法,只需将泛型参数列表置于返回值之前

15.4.2 可变参数与泛型方法

泛型方法与可变参数列表很好共存

15.5 匿名内部类

泛型还可以应用于内部类以及匿名内部类

15.6 构建复杂模型

泛型的一个重要好处是能够简单而安全地创建复杂的模型

类型安全 可管理

15.7 擦除的神秘之处

不能声明泛型类实现后的类型的Class对象

getTypeParameters能够得到参数类型的信息,但只是参数占位符

在泛型代码内部,无法获得任何有关泛型参数类型的信息

Java的泛型是使用擦除实现的

任何具体的类型信息都被擦除了

运行时都被擦除为相同的类型

协助泛型类

给定泛型类的边界

泛型类型只有在静态类型检查期间才出现,在此之后,程序中的所有泛型类型都将被擦除,替换为它们的非泛型上界

擦除的核心动机是它使得泛化的客户端可以用非泛化的类库,vice versa — 迁移兼容性

15.7.3 擦除的问题

不能用于显式地引用运行时类型的操作

转型

instanceof

new

因为擦除在方法体中移除了类型信息,所以在运行时的问题就是边界

15.8 擦除的补偿

通过显示传递并保存Class。通过Class.isInstance方法动态比较

可以声明泛型数组 不过还是擦除了

15.9 边界

可以有多个上界 用& 连接

15.10 通配符

?unknown

extends

super 逆变

区别为通配符对于所持对象的表述差别

捕获转换

编译器可能会推断出实际的类型参数,使这个方法可以回转并调用另一个使用这个确切类型的方法

15.11 问题

任何基本类型都不能作为类型参数

实现参数化接口

一个类不能实现同一个泛型接口的两种变体

转型和警告

使用带有泛型类型参数的转型或instanceof不会有任何效果

要使用cast方法转型Class

重载

擦除原因

基类劫持了接口

15.12 自限定的类型 Class A extends SelfBounded{}

保证类型参数必须与正在被定义的类相同

15.12.3 参数协变

15.13 动态类型安全

将导出类型的对象放置到将要检查基类型的受检查容器是没问题的

15.14 异常

catch语句不能捕捉泛型类型的异常,因为在编译期和运行时都必须知道异常的确切类型

15.15 混型

泛型类不能直接继承自一个泛型参数

15.16 潜在类型机制

通过泛型(方法)来实现鸭子类型是可以的 接口,类也可以

补偿机制:

反射

将一个方法应用于序列

16 数组和其他种类的容器之内的区别

效率

效率最高的存储和随机访问对象引用序列的方式

访问非常快

代价是数组大小被固定

类型

可以持有基本类型

保存基本类型的能力

16.5 数组与泛型

数组与泛型不能很好结合,不能实例化具有参数化类型的数组

但是可以参数化本身的类型

16.6 创建测试数据

Arrays.fill()方法

数据生成器 Generator

16.7 Arrays功能

16.7.1 复制数组

System.arraycopy

比较

Arrays.equals

comparable/comparator

排序

正排序优化 — 对基本类型采取了Qsort

针对对象设计的“稳定归并排序”

在已排序的数组中查找

Arrays.binarySearch

17.2 填充容器

Collections.nCopies方法

Collections.fill方法

一种Generator解决方案

使用Abstract类

提供了容器的部分实现

17.3 Collection的功能方法

Map不是继承自Collection的

功能方法

add

addAll

clear — optional

contains

containsAll

isEmpty

iterator

remove

removeAll

retainAll

size

toArray

17.6.1 SortedSet

元素可以保持处于排序状态

17.7 队列

Queue

PriorityQueue

ArrayBlockingQueue

ConcurrentQueue

LinkedBlockingQueue

PriorityBlockingQueue

LinkedList

17.8理解Map

HashMap — 散列表实现

TreeMap — 红黑树

LinkedHashMap

WeakHashMap

ConcurrentHashMap

IdentityHashMap

17.9 散列与散列码

自反性

对称性

传递性

一致性

对不是null的x,x.equals(null)都应该等于 false

17.11 实用方法

查Collections API

unmodifiable系列方法生成只读Collection或Map

快速报错

17.12 持有引用

可获得性:

SoftReference > WeakReference > PhantomReference

User Case:

想继续持有对某个对象的引用,希望以后还能访问到该对象,但是也希望能够GC释放它

SoftReference 用以实现内存敏感的高速缓存

WeakReference 为实现“规范映射”而设计 不妨碍GC回收映射的Key或Value

规范映射中对象的实例可以在程序的多处被同时使用

PhantomReference用以调度回收前的清理工作,它比Java终止机制灵活

实用SR/WR时,可以选择是否要将它们放入ReferenceQueue

PR只能依赖于ReferenceQueue

18.1 File类

File既可以代表特定文件的名称,又能代表一个目录下的一组文件的名称

如果它指的是一个文件集,可以调用list方法返回一个字符数组

实际上FilePath应该是更好地名字

还可以搭配FileNameFilter接口使用

18.2 输入和输出

流 — 代表任何有能力产出数据的数据源对象或有能力接受数据的接受端对象。

屏蔽了实际IO设备处理数据的细节

可以通过叠合多个对象来提供所期望的功能

18.2.1 InputStream类型

用来表示那些从不同数据源产生输入的类

数据源:

字节数组 — ByteArrayInputStream

String对象 — StringBufferInputStream

文件 — FileInputStream

管道 — PipedInputStream

一个由其他种类的流组成的序列,以便把它们收集合并到一个流内

SequenceInputStream

将多个InputStream转换为一个InputStream

FilterInputStream

抽象类,做装饰器的接口

DataInputStream

BufferedInputStream

LineNumberInputStream

18.2.2 OutputStream类型

除了无StringBufferInputStream,其他类似

18.3.2 通过FilterOutPutStream向OutPutStream写入

DataOutputStream

可以将各种基本数据类型和String对象格式化输出到流

PrintStream

以初始化格式打印所有基本元素类型和String

BufferedOutPutStream

对数据流使用缓冲技术

输入/出的时候不是每次都进行实际的物理读写动作

18.4 Reader和Writer

兼容Unicode与面向字符的I/O功能

18.4.2 更改流的行为

PushbackReader

18.5 RamdomAccessFile

适用于大小已知的记录组成的文件

类似于把DataInputStream/DataOutPutStream结合起来,再加上一些方法

18.6.1 缓冲输入文件

BufferedReader支持readLine

18.10 NIO

具体查看NIO API

18.10.7

tryLock是非阻塞的

lock是阻塞的

fileLock可以实现对文件部分加锁

18.11 压缩

InputStreamReader/OutPutStreamWriter可以进行两种模式的切换

压缩类

CheckedInputStream

GetCheckSum方法为任何InputStream产生校验和(不仅压缩)

DeflaterOutputStream/InflateInputStream

基类

GZIP/ZipOutPutStream

将数据压缩成Zip/Gzip格式

了解API或第三方类库

JAR

了解jar

18.12

实现了Serializable接口的对象可以转化为一个字节序列

可以通过实现Externalizable接口代替实现Serializable

通过构造器构造然后执行extern方法

transient关键字

用于在序列化时关闭特定序列化字段

18.13 XML

自学第三方类库

18.14 Preference

和对象序列化相比对象持久性更密切

可以自动存储和读取信息

只能用于小的 受限的数据集合

基本类型和字符串

字符串不能超过8K

通常是创建以你的类名命名的单一节点,然后将信息存于其中

19.1 enum特性

ordinal方法返回声明时的次序

name方法返回enum特例声明时的名字

valueOf根据给定的名字返回enum实例 不存在则抛出异常

19.1.1 将静态导入用于enum

可以静态导入enum

19.2 向enum提交方法

enum元素也可以使用构造器

也可以覆盖enum的方法

19.3 switch语句中使用enum

19.4 values方法的神秘之处

enum都继承于Enum类

values方法是由编译器添加的static方法

同样的还有valueOf方法

如果把enum向上转型为Enum,就不能使用values方法了

Class.getEnumConstants方法依然可以获得所有enum实例

19.5 实现,而非继承

不能再继承enum了

但可以实现接口

19.7 用接口组织枚举

可以通过在构造器使用Class.getEnumConstants来得到枚举的枚举

也可以让一个enum镶嵌在另一个enum实现

19.8 使用EnumSet/EnumMap

自己看API

19.10 常量相关的方法

允许为enum编写方法

要为enum定义一个或多个抽象方法

20 Java内置注解

@Override

当前方法定义将覆盖超类中的方法

@Deprecated

如果程序员使用了注解为它的元素,会发出警告

@SuppressWarnings

关闭不当的编译器警告信息。

20.1.1 定义注解

@Target用来定义你的注解应该用于售卖地方

@Rectetion用来定义该注解在哪个级别可用

SOURCE

CLASS

RUNTIME

没有元素的注解被称为标记注解

注解的元素使用时表现为名-值对形式,

20.1.2 元注解

@Target

ElementType

CONSTRUCTOR

FIELD

LOCAL_VARIABLE

METHOD

PACKAGE

PARAMETER

TYPE — 类 接口(包括注解) enum

@Retention

RetentionPolicy

SOURCE — 注解被编译器抛弃

CLASS — 被VM抛弃

RUNTIME — 在运行期被保留

@Documented

此注解被包含在Javadoc中

@Inherited

允许子类继承父类中的注解

20.2

getAnnotation返回指定类型的注解对象

20.2.1 注解元素

注解元素可用的类型

基本类型

String

Class

enum

Annotation

以上类型的数组

注解可以为元素类型,注解也可以嵌套

20.2.2 默认值限制

元素必须要么有默认值,要么在使用注解时提供元素的值

对于非基本类型,都不能以null作为其值

20.2.4 注解不支持继承
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: