Java性能优化(13):支持非可变性
一个非可变类是一个简单的类,它的实例不能被修改。每个实例中包含的所有信息都必须在该实例被创建的时候就提出来,并且在对象的整个生存期内固定不变。Java平台库包含许多非可变类,其中有String、原语类型的包装—BigInteger和BigDecimal。非可变类的存在有许多理由:非可变类比可变类更加易于设计、实现和使用。它们不容易出错,更加安全。
一个非可变类是一个简单的类,它的实例不能被修改。每个实例中包含的所有信息都必须在该实例被创建的时候就提出来,并且在对象的整个生存期内固定不变。Java平台库包含许多非可变类,其中有String、原语类型的包装—BigInteger和BigDecimal。非可变类的存在有许多理由:非可变类比可变类更加易于设计、实现和使用。它们不容易出错,更加安全。
类和接口是Java程序设计语言的核心,它们也是Java语言的基本抽象单元。Java语言提供了许多强大的基本元素,供程序猿来设计类和接口。
OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH是安全的。oAuth是Open Authorization的简写。
Cloneable接口的目的是作为对象的一个mixin接口,表明这样的对象允许克隆。不幸的是,它并没有成功达到这个目的。其主要的缺陷在于它缺少一个clone方法,Object的clone方法是被保护的,如果不借助于反射机制,则不能仅仅因为一个对象实现了Cloneable,就可以调用clone方法。即使在反射调用也可能会失败,因为并不保证该对象一定具有可访问性的clone方法。尽管存在这样那样的不足,这项设施仍然被广泛地使用着,值得我们进一步了解它。接下来,将告诉你如何实现一个行为良好的clone方法,并讨论何时这样做是恰当的,同时也简单地讨论了其他可替换做法。
虽然java.lang.Object提供了toString方法的一个实现,但是,它返回的字符串通常并不是类的用户所期望看到的,它包含类的名字,以及一个“@”符号,接着是散列码的无符号十六进制表示,例如“phoneNumber@163b91”。toString的通用约定指出,被返回的字符串应该是一个”简洁的,且信息丰富,并且易于阅读的表达形式”。尽管“phoneNumber@163b91”算得上是简洁的和易于阅读的,但是与”(408)867-5309”比较起来,它不是信息丰富的。toString的约定进一步指出,“建议所有的子类都改写这个方法”
一个很常见的错误源于没有改写hashCode方法。在每个改写了equals方法的类中,你必须也要改写hashCode方法。如果不这样做到话,就会违反Object.hashCode的通用约定,从而导致该类无法与所有基于散列值(hash)的集合类结合在一起正常运作,这样的集合类包括hashMap、HashSet和Hashtable。
尽管Object是一个具体类,但是设计它主要是为了扩展。它的所有非final方法都有明确的通用约定。因为它们都是为了遵守这些通用约定;如果不能做到这一点,则其他一些依赖于这些约定的类就无法与这些类结合在一起正常工作。
终结函数通常是不可预测的,常常也是很危险的,一般情况下是不必要的。使用终结函数会导致不稳定的行为、更差的性能,以及带来移植性问题。当然,终结函数也有其可用之处的但是作为一个优秀的programer,应当避免使用终结函数。
C++程序员被告知“不要把终结函数当做C++中析构函数的对应物”。在C++中,析构函数是回收一个对象所占资源的常规方法,是构造函数所必须的对应物。在Java语言中,当一个对象变得不可到达的时候,垃圾回收器会回收与该对象相关联的存储空间,并不需要程序员做专门的工作。C++的析构函数也可以被用来回收其他的非内存资源。在Java程序语言设计中,一般用try-finally块来完成类似的工作。
当你从一种手工管理内存的语言(比如C/C++)转换到一种具有垃圾回收功能的语言的时候,作为一个苦逼的程序猿,工作这时候变得更加容易。因为当你用完了对象后,它们会自动被回收(现实中的对象可不能这样啊(ฅ>ω<*ฅ))。当你第一次经历对象回收功能的时候,你回觉得这样有点不可思议。这很容易会让你留下这样的印象,认为自己再需要考虑内存管理的事情。然而,其实你想多了。
不信来看下面简单的栈实现例子: