自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(108)
  • 资源 (4)
  • 问答 (1)
  • 收藏
  • 关注

原创 Effective Java 第三版 中文翻译

effective-java-third-edition介绍Effective Java 第三版全文翻译,纯属个人业余翻译,不合理的地方,望指正,感激不尽!目录推荐序前言致谢第一章 引言第二章 创建和销毁对象  本章涉及创建和销毁对象,包括何时以及如何创建它们,何时以及如何避免创建它们,如何确保它们被及时销毁,以及如何管理在销毁之前必须进行的清理操作。第1项:考虑静态工...

2019-05-25 08:46:28 3301 1

原创 第90项:考虑用序列化代理代替序列化实例

  正如第85项和第86项中提到以及本章中所讨论的,决定实现Serializable接口,会增加bug和出现安全问题的可能性,因为它导致实例要利用语言之外的机制来创建,而不是用普通的构造器。然而,有一种方法可以极大地减少这些风险。这种方法就是序列化代理模式(serialization proxy pattern)。  序列化代理模式相当简单。首先,为可序列化的类设计一个私有的静态嵌套类,精确地表...

2019-09-08 19:28:26 304

原创 第89项:对于实例控制,枚举类型优先于readResolve

  第三项讲述了*单例(singleton)*模式,并且给出了以下这个Singleton类的示例。这个类限制了对其构造器的访问,以确保永远只创建一个实例:public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public void lea...

2019-09-08 19:27:55 307

原创 第88项:保护性地编写readObject方法

  第50项介绍了一个不可变的日期范围类,它包含可变的私有Date域。该类通过在其构造器和访问方法(accessor)中保护性地拷贝Date对象,极力地维护其约束条件和不可变性。下面就是这个类:// Immutable class that uses defensive copyingpublic final class Period { private final Date star...

2019-09-08 19:27:21 477

原创 第87项:考虑使用自定义的序列化形式

  当你在时间紧迫的情况下设计一个类时,一般合理的做法是把工作重心几种在设计最佳的API上。有时候,这意味着要发行一个“用完后即丢弃”的实现,因为你知道以后会在新版本中将它替换掉。正常情况下,这不成问题,但是,如果这个类实现了Serializable接口,并且使用了默认的序列化形式,你就无法彻底摆脱那个应该丢弃的实现了。它将永远牵制住这个类的序列化形式。这不只是一个纯理论的问题,在Java平台类库...

2019-09-08 19:26:48 295 3

原创 第86项:谨慎地实现Serializable接口

  要想使一个类的实例可被序列化,非常简单,只要在它的声明中假如“implemants Serializable”字样即可。正因为太容易了,所以普遍存在这样一种误解,认为程序猿可以毫不费力就可以实现序列化。实际情形要复杂得多。虽然使一个类可序列化的直接成本可以忽略不计,但长期的成本通常是很高的。  实现Serializable接口而付出的最大代价是,一旦一个类被发布,就大大降低了“改变这个类的实...

2019-09-08 19:25:07 507

原创 第85项:其他序列化优先于Java序列化

  当序列化在1997年被添加到Java时,它被认为有点风险的。该方法已经在一种研究语言(Modula-3)中尝试过,但在生产中的语言从未用过。虽然程序猿承诺在分布式对象上付出点努力得到的成果是很有吸引力的,代价是构造函数是不可见的而且它的API和实现之间的界限很模糊,可能存在正确性、性能、安全性和维护方面的问题。支持者认为这些好处【前面的成果】超过了风险,但历史已经证明并不是这样的。  本书前...

2019-09-08 19:23:06 225

原创 第84项:不要依赖于线程调度器

  当有多个线程可以运行时,由线程调度器(therad scheduler)决定哪些线程将会运行,以及运行多长实践。任何一个合理的操作系统在做出这样的决定时,都会努力做到公正,但是所采用的策略却大相径庭。因此,编写良好的程序不应该依赖于这种策略的细节。任何依赖于线程调度器来达到正确性或者性能要求的程序,很有可能都是不可移植的 。  编写健壮,响应迅速的可移植程序的最佳方法是确保可运行线程的平均数...

2019-09-08 19:22:25 308

原创 第83项:慎用延迟初始化

  *延迟初始化(Lazy initialization)*是延迟到需要域的值时才将它初始化的行为。如果永远不需要这个值,这个域就永远不会被初始化。这种方法既适用于静态域,也适用于实例域。虽然延迟初始化主要是一种优化,但它也可以用来打破类和实例初始化中的有害循环[Bloch05, Puzzle 51]。  就像大多数的优化一样,对于延迟初始化,最好的建议就是“除非绝对必要,否则就不要这么做”(第...

2019-09-08 19:21:57 285

原创 第82项:线程安全性文档化

  当并发使用一个类的方法时,类的行为方式是该类与其客户端建立的约定的重要组成部分。如果这方面的内容你没有在类的文档中记录下来,使用这个类的用户将被迫做出假设。如果这些假设是错误的,这样得到的程序就可能缺少足够的同步(第78项)或者过度同步(第79项)。无论哪种情况,都可能导致严重的错误。  你可能听到过这样的说法:通过查看文档中是否出现synchronized修饰符,你可以确定一个方法是否是线...

2019-09-08 19:21:24 377

原创 第81项:并发工具优先于wait和notify

  本书的第一版专门用一项来【说明如何】正确使用wait和notify[Bloch01, 第50项]。它的建议仍然有效,并在本项末尾进行了总结,但这个建议远不如以前那么重要。这是因为几乎没有理由再使用wait和notify了。自从Java 5以来,该平台提供了更高级别的并发工具,它们可以做一些你之前必须在wait和notify上手写代码来完成的各项工作。鉴于正确地使用wait和notify比较困难...

2019-09-08 19:20:55 366

原创 第80项:executor、task和stream优先于线程

  本书的第一版包含简单的*工作队列(work queue)*的代码[Bloch01, Item 49]。这个类允许客户端将后台线程的异步处理工作排入队列。当不再需要这个工作队列时,客户端可以调用一个方法,让后台线程完成了已经在队列中的所有工作之后,优雅地终止自己。这个实现几乎就想件玩具,但即使如此,它还是需要一整页微妙、精致的代码,一不小心,就容易出现安全问题或者导致活性失败(liveness ...

2019-09-08 19:20:20 238

原创 第79项:避免过度同步

  第78项告诫我们缺少同步的危险性。本项则关注相反的问题。依据情况的不同,过度同步可能会导致性能降低、死锁,甚至不确定的行为。  为了避免活性失败和安全性失败,在一个被同步的方法或者代码块中,永远不要放弃对客户端的控制 。换句话说,在一个被同步的区域内部,不要调用设计成要被覆盖的方法,或者是由客户端以函数对象的形式提供的方法(第24项)。从包含该同步区域的类的角度来看,这样的方法是外来的(al...

2019-09-07 16:19:24 248

原创 第78项:同步访问共享的可变数据

  关键字synchronized可以保证在同一时刻,只有一个线程可以执行某一个方法,或者某一个代码块。许多程序猿把同步的概念仅仅理解为一种互斥的方式(mutual exclusion),即,当一个对象被一个线程修改的时候,可以阻止另一个线程观察到对象内部不一致的状态。按照这种观点,对象被创建的时候处于一致的状态(第17项),当有方法访问它的时候,它就被锁定了。这些方法观察到对象的状态,并且可能会...

2019-09-07 16:18:44 180

原创 第77项:不要忽略异常

  尽管这条建议看上去是显而易见的,但是它却常常被违反,因而值得重复提出来。当API的设计者声明一个方法将抛出某个异常的时候,它们是在试图告诉你某些事情。所以,不要忽略它!要忽略一个异常非常容易,只需要将方法调用通过try语句包围起来,并包含一个空的catch块:// Empty catch block ignores exception - Highly suspect!try { ...

2019-09-07 16:17:49 467

原创 第76项:努力使失败保持原子性

  当对象抛出异常之后,通常我们期望这个对象仍然保持在一种定义良好的可用状态之中,即使失败是发生在执行某个操作的过程中间。对于受检的异常而言,这尤为重要,因为调用者期望能从这种异常中进行恢复。一般而言,失败的方法调用应该使对象保持在被调用之前的状态 。具有这种属性的方法被称为具有失败的原子性(failure atomic)。  有几种途径可以实现这种效果。最简单的办法莫过于设计一个不可变的对象(...

2019-09-07 16:12:43 250

原创 第75项:在详细信息中包含捕获的失败信息

  当程序由于未被捕获的异常而失败的时候,系统会自动地打印出该异常的栈跟踪信息。在栈跟踪信息中包含该异常的字符串表示法(string represention),即它的toString方法的调用结果。它通常包含该异常的类名,紧随其后的是详细信息(detail message)。通常,这只是程序猿或者站点可靠性工程师【运维工程师?】(field service personnel,检查软件失败的人)...

2019-09-07 16:04:49 174

原创 第74项:每个方法抛出的所有异常都要建立文档

  描述一个方法所抛出的异常,是正确使用这个方法时所需文档的重要组成部分。因此,花点实践仔细地为每个方法抛出的异常建立文档是特别重要的(第56项)。  始终要单独地声明受检的异常,并且利用Javadoc的@throws标记,准确地记录下抛出每个异常的条件 。如果一个方法可能抛出多个异常类,则不要使用“快捷方式(shortcut)”声明它会抛出这些异常类的某个超类。永远不要声明一个方法“throw...

2019-09-07 16:04:01 178

原创 第73项:抛出与抽象相对应的异常

  如果方法抛出的异常与它所执行的任务没有明显的联系,这种情形将会使人不知所措。当方法传递由低层抽象抛出的异常时,往往会发生这种情况。除了使人感到困惑之外,这也让实现细节污染了更高层的API。如果高层的实现在后续的发行版本中发生了变化,它所抛出的异常也可能会梗着发生变化,从而潜在地破坏现有的客户端程序。  为了避免这个问题,更高层的实现应该捕获低层的异常,同时抛出可以按照高层抽象进行解释的异常 ...

2019-09-07 16:02:01 646

原创 第72项:优先使用标准的异常

  专家级程序猿与缺乏经验的程序猿【菜猿】一个最主要的区别在于,专家追求并且通常也能够实现高度的代码重用。代码重用是值得提倡的,这是一条规则,异常也不例外。Java平台的类库提供了一组基本的未受检异常,它们满足了绝大多数API抛出的所需要的异常。  重用现有的异常有多方面的好处。其中最主要的好处是,它使你的API更加易于学习和使用,因为它与程序猿已经熟悉的习惯用法是一致的。第二个好处是,对于用到...

2019-09-07 16:01:16 218

原创 第71项:避免不必要地使用受检异常

  很多Java程序猿不喜欢受检异常,但是使用得当的话,它们可以改善API和程序。与返回代码和未受检异常不同,它们强迫程序猿处理问题,提高了可靠性。也就是说,过分使用受检的异常会使API使用起来非常不方便。如果方法抛出一个或者多个受检的异常,调用该方法的代码就必须在一个或者多个catch块中处理这些异常,或者它必须声明它抛出这些异常,并让它们传播出去。无论哪种方法,它都会给使用API的用户带来负担...

2019-09-07 15:44:06 234

原创 第70项:对可恢复的情况使用受检异常,对编程错误使用运行时异常

  Java程序设计语言提供了是三种可抛出结构(throwable):受检异常(checked exceptions),运行时异常( runtime exceptions)和错误(error)。在程序猿之间就存在一些困惑:什么时候适合使用哪种可抛出结构。虽然做决定的界限并不总是那么清晰,但还是有一些一般性的原则提供了强有力的指导。  在决定使用受检的异常或者未受检的异常时,主要的原则是:如果期望...

2019-09-07 15:43:37 649

原创 第69项:只针对异常的情况才使用异常

  总有一天,如果你运气不好,你可能偶然发现一段看起来像这样的代码:// Horrible abuse of exceptions. Don't ever do this!try { int i = 0; while(true) range[i++].climb();} catch (ArrayIndexOutOfBoundsException e) {}...

2019-09-07 15:28:11 582

原创 第68项:遵守普遍接受的命名惯例

  Java平台建立了一整套很好的命名惯例(naming convention),其中有许多命名惯例包含在了《The Java Language Specification》[JLS, 6.1]中。不严格地讲,这些命名惯例分为两大类:字面的(typographical)和语法的(grammatical)。  字面的命名惯例比较少,涉及包、类、接口、方法、域和类型变量。应该尽量不违反这些惯例,没有...

2019-08-03 15:46:54 247

原创 第67项:谨慎地进行优化

  有三条与优化有关的格言是每个人都应该知道的:很多计算上的过失都被归咎于效率(没有必要达到的效率),而不是任何其他原因——甚至包括盲目地做傻事。——William A. Wulf [Wulf72] 不要去计算效率上的一些小小的得失,在97%的情况下,不成熟的优化才是一切问题的根源。——Donald E. Knuth [Knuth74] 在优化方面,我们应该遵守两条规则:规则1:不...

2019-08-03 15:46:23 207

原创 第66项:谨慎地使用本地方法

  Java Native Interface (JNI) 允许Java应用程序可以调用本地方法(native method),所谓本地方法是指使用本地程序设计语言(native programming languages)(比如C或者C++)来编写的方法。从历史上看,本地方法主要有三种用途。它们提供了“访问特定于平台的机制”的能力,比如【访问】注册表。它们还提供了访问遗留代码库的能力,从而可以访...

2019-08-03 15:45:44 185

原创 第65项:接口优先于反射机制

  核心反射机制:java.lang.reflect,提供对任意类的编程访问(The core reflection facility, java.lang.reflect, offers programmatic access to arbitrary classes.)。给定一个Class对象,你可以获得Constructor、Mtehod和Field实例,分别代表了该Class实例所表示的类...

2019-08-03 15:45:08 210

原创 第64项:通过接口引用对象

  第51项建议:应该使用接口而不是类作为参数的类型。更一般的讲,应该优先使用接口而不是类来引用对象。如果有合适的接口类型存在,那么对于参数、返回值、变量和域来说,就都应该使用接口类型进行声明 。只有当你利用构造器创建某个对象的时候,才真正需要引用这个对象的类。为了更具体地说明这一点,我们来考虑 LinkedHashSet的情形,它是Set接口的一个实现。在声明变量的时候应该养成这样的习惯://...

2019-08-03 15:44:36 204

原创 第63项:注意字符串拼接的性能

  字符串拼接操作符(+,string concatenation operator)是把多个字符串组合为一个字符串的便利途径。产生单独一行的输出,或者构造一个字符串来表示一个较小的、大小固定的对象,使用字符串拼接操作符是非常好的,但它不能缩放(but it does not scale)。重复地使用字符串拼接操作符来拼接n个字符串,需要n的平方级的时间 【意思是时间复杂度为n^2 ?】。由于字符...

2019-08-03 15:44:07 180

原创 第62项:如果其他类型更适合,则尽量避免使用字符串

  字符串被用来表示文本,它在这方面也确实做得很好。因为字符串很通用,并且Java语言也支持得很好,因此将字符串用于除设计字符串之外的其他目的的自然倾向【也就是说,设计字符串本来是用来做某些事情的,但是除了这些事情之外,人们也会使用字符串】。本项就是讨论一些不应该使用字符串的情形。  字符串不适合代替其他的值类型 。当一段数据从文件、网络、或者键盘设备,输入到程序的时候,它通常以字符串的形式存在...

2019-08-03 15:43:33 230

原创 第61项:基本类型优先于装箱基本类型

  Java有一个类型系统由两部分组成,包含基本类型(primitives),比如int,double和boolean和引用类型(reference type),例如String和List。每个基本类型都有一个对应的引用类型,称作装箱基本类型(boxed primitive)。装箱基本类型中对应于int、double和boolean的是Integer、Double和Boolean。  如第6项所...

2019-08-03 15:43:01 262

原创 第60项:如果需要精确的答案,请避免使用float和double

  float和double类型主要是为了科学计算和工程计算而设计的。它们执行二进制浮点运算(binary floating-point arithmetic),这是为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们并没有提供完全精确的结果,所以不应该被用于需要精确结果的场合。float和double类型尤其不适合用于货币计算 ,因为要让一个float或者double精确地表...

2019-08-03 15:42:26 285

原创 第59项:了解和使用类库

  假设你希望产生位于0和某个上界之间的随机整数。面对这个常见的惹怒我,许多程序猿会编写如下所示的方法:// Common but deeply flawed!static Random rnd = new Random();static int random(int n) { return Math.abs(rnd.nextInt()) % n;}  这个方法看起来可能不错,...

2019-08-03 15:41:39 220

原创 第58项:for-each循环优先于传统的for循环

  如第45项所述,某些任务最好用流(stream)完成,其他任务最好用迭代完成。这是一个传统的for循环迭代集合:// Not the best way to iterate over a collection!for (Iterator<Element> i = c.iterator(); i.hasNext(); ) { Element e = i.next(); ...

2019-07-13 07:08:52 243

原创 第57项:将局部变量的作用域最小化

  本项与第15项(使类和成员的可访问性最小化)本质上是类似的。将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性。  较早的程序设计语言(如C语言)要求局部变量必须在一个代码块的开头处进行声明,出于习惯,有些程序猿们目前还是继续这样做。这是个值得打破的习惯。在此提醒Java允许你在任何可以出现语句的地方声明变量(与C一样,自C99起)。  要使局部变量的作用于最小化...

2019-07-13 07:08:17 267

原创 第56项:为所有导出的API元素编写文档注释

  如果要想使一个API真正可用,就必须为其编写文档。传统意义上的API文档是手工生成的,所以保持文档与代码同步是一件很繁琐的事情。Java编程环境提供了一种被成为Javadoc的实用工具。Javadoc使用特殊格式的文档注释(documentation comments)(通常称为doc注释(doc comments))从源代码自动生成API文档。  虽然这些文档注释规范不是Java语言正式的...

2019-07-13 07:07:39 224

原创 第55项:谨慎返回optional

  在Java 8之前,在编写在某些情况下无法返回值的方法时,可以采用两种方法。 你可以抛出异常,也可以返回null(假设返回类型是对象引用类型)。这些方法都不完美。【出现】特殊的情况才应该保留异常(第69项),抛出异常【的成本】是很昂贵的,因为在创建异常时会捕获整个堆栈【的】跟踪【信息】。返回null没有这些缺点,但它有自己的缺点。如果方法返回null,则客户端必须包含(include【使用】)...

2019-07-13 07:07:07 1136

原创 第54项:返回长度为零的数组或者集合,而不是null

  像下面这样的方法并不少见:// Returns null to indicate an empty collection. Don’t do this!private final List<Cheese> cheesesInStock = ...;/** * @return a list containing all of the cheeses in the shop,...

2019-07-13 07:06:13 674

原创 第53项:慎用可变参数

  可变参数方法,一般称作可匹配不同长度的变量的方法(variable arity methods)[JLS, 8.4.1],可接受零个或者多个指定类型的参数。可变参数机制通过先创建一个数组,数组的大小为在调用位置所传递的参数数量,然后将参数值传递到数组中,最后将数组传递给方法。  例如,下面就是一个可变参数方法,带有int参数的一个序列,并返回它们的总合。正如你所期望的,sum(1, 2, 3...

2019-07-13 07:05:32 245

原创 第52项:慎用重载

  下面这个程序的意图是好的,它试图根据一个集合(collection)是Set、List,还是其他的集合类型,对它进行分类:// Broken! - What does this program print?public class CollectionClassifier { public static String classify(Set<?> s) { ...

2019-07-13 07:04:58 301

安卓sdk 离线文档 API 23 Part4

将剩下的三个rar文件放在一个文件夹之下,解压后,打开docs下的index.html即可使用。还有三个rar文件,请考虑后下载:android_sdk_docs_offline_23.part01.rar、android_sdk_docs_offline_23.part02.rar、android_sdk_docs_offline_23.part03.rar。

2017-11-08

安卓sdk 离线文档 API 23 Part3

将剩下的三个rar文件放在一个文件夹之下,解压后,打开docs下的index.html即可使用。还有三个rar文件,请考虑后下载:android_sdk_docs_offline_23.part01.rar、android_sdk_docs_offline_23.part02.rar、android_sdk_docs_offline_23.part04.rar。

2017-11-08

安卓sdk 离线文档 API 23 Part2

将剩下的三个rar文件放在一个文件夹之下,解压后,打开docs下的index.html即可使用。还有三个rar文件,请考虑后下载:android_sdk_docs_offline_23.part01.rar、android_sdk_docs_offline_23.part03.rar、android_sdk_docs_offline_23.part04.rar。

2017-11-08

安卓sdk 离线文档 API 23 Part1

将剩下的三个rar文件放在一个文件夹之下,解压后,打开docs下的index.html即可使用。还有三个rar文件,请考虑后下载:android_sdk_docs_offline_23.part02.rar、android_sdk_docs_offline_23.part03.rar、android_sdk_docs_offline_23.part04.rar。

2017-11-08

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除