1.概述 如果clone方法返回一个由构造器创建的对象,它就得到有错误的类.因此,如果覆盖了非final类中的clone方法,则应该返回一个通过调用super.clone得到的对象.如果类的所有超类都遵循这条规则,那么调用super.clone最终会调用Object的clone方法,从而创建出正确的实例.这种机制类似于自动的构造器调用链,只不过它不是强制要求的. 2.示例 需求: 为HashTable编写一个clone方法,它内部数据包含一个HashTable数组,每个HashTable都指向键…
一个类要想实现克隆,需要实现Cloneable接口,表明这个类的对象具有克隆的功能. Cloneable接口是一个mixin接口,它里面并没有任何的抽象方法,类似的接口有Serializable接口,表明该类的对象可以序列化. 首先应该明确通过一个对象克隆出另一个对象的概念:通过一个对象克隆出另一个对象,简称对象1和对象2,这两个对象就成为两个独立的对象, 那么对对象1做任何的修改,对象2应该不受影响:对对象2做任何的修改的,对象1就不应该受影响.这样就要求对象1与对象2的实例域各自是独立的.…
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. 13. 谨慎地重写 clone 方法 Cloneable接口的目的是作为一个mixin接口(条目 20),公布这样的类允许克隆.不幸的是,它没有达到这个目的.它的主要缺点是…
1.进行浅拷贝时,只是复制原始数据类型的值,则可以通过覆盖Clone方法来达到.另外,在进行浅拷贝的时候,还要注意,成员对象中不应该要有引用类型,如果有引用类型,那么,进行了浅拷贝之后,两个对象将会共享成员引用所指向的对象,这会出现问题.所以,在这种情况下,干脆直接使用深拷贝,避免问题出现.2.对于深拷贝,也就是完全将对象的内容复制一份,则使用序列化来实现,也是为了避免覆盖Clone.   浅拷贝的例子: 这个例子,只是复制成员的值,成员的类型都是原始数据类型,不包含引用类型: public c…
Clone提供一种语言之外的机制:无需调用构造器就可以创建对象. 它的通用约定非常弱: 创建和返回该对象的一个拷贝.这个拷贝的精确含义取决于该对象的类.一般含义是,对于任何对象x,表达式x.clone() != x 将会是true,并且,表达式x.clone().getClass() == x.getClass() 将会是true,但这些不是绝对的要求,通常情况下,表达式 x.clone().equals(x) 将会是true,这也不是一个绝对的要求,拷贝对象往往是创建它的类的一个新实例,但它同…
38.检查参数的有效性 绝大多数方法和构造器对于传递给它们的参数值都会有限制.如,对象引用不能为null,数组索引有范围限制等.应该在文档中指明所有这些限制,并在方法的开头处检查参数,以强制施加这些限制. 对于公有的方法,使用异常检查参数,并在Javadoc的@throws标签中说明违反参数限制时会抛出的异常. 对于非公有的方法,使用断言来检查参数.断言如果失败,将会抛出AssertionError.若它们没起作用,本质上不会有成本开销. 断言仅用于代码调试,不要在公有的API方法中使用断言,因…
No38 检查参数的有效性 对于公有的方法,要用Javadoc的@throws标签(tag)在文档中说明违反参数值时会抛出的异常.这样的异常通常为IllegalArgumentException.IndexOutOfBoundsException或NullPointerException. /** * ... * @throws ArithmeticException if m is less than or equal to 0 */ public BigInteger mod(BigInte…
1.实现Cloneable接口表明该类的对象是允许克隆的. 2.允许克隆的意思是:可以调用clone()方法. 3.深拷贝还是浅拷贝,取决于如何重写Object的clone()方法. 4.原对象和克隆对象的关系: 深拷贝:阳关道和独木桥: 浅拷贝:藕断丝连. 上面的第二点解释一下,如果没有实现Cloneable就调用clone()方法,会抛出异常.看下Object源码就知道了: protected Object clone() throws CloneNotSupportedException…
目录 第38条 检查参数的有效性 第39条 必要时进行保护性拷贝 第40条 谨慎设计方法签名 第41条 慎用重载 第42条 慎用可变参数 第43条 返回零长度的数组或集合,而不是null 第44条 为所有导出的API元素编写文档注释 关注点:可用性.健壮性.灵活性 第38条 检查参数的有效性 在编写方法或者构造器的时候,应该考虑参数有哪些限制,并显式检查 第39条 必要时进行保护性拷贝 如果类具有从客户端得到或者返回到客户端的可变组件,为了维持不可变性,必要时进行保护性拷贝. 否则,在文档中写明…
第39条 必要时进行保护性拷贝 对于可变类,如果作为参数传入到自己的类里,并作为自己类的数据使用存储时,需要进行保护性拷贝,比如Date是可变的,如果传入一个Date类,最好做一个保护性拷贝,以免在调用完Period后,外面将传入的参数start进行更改,影响自己类的this.start: public Period(Date start) { this.start = new Date(start.getTime()); } 同理,如果是作为返回对象,也需要做返回的保护性拷贝 public D…
package cn.xf.cp.ch02.item9; import java.util.HashMap; import java.util.Map; public class PhoneNumber { private final short areaCode; private final short prefix; private final short lineNumber; public PhoneNumber(int areaCode, int prefix, int lineNum…
package cn.xf.cp.ch02.item8.transitivity; public class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object obj) { if(!(obj instanceof Point)) { return false;…
尽管Object是一个具体的类,但设计它主要是为了扩展.它的所有非final方法都有明确的通用约定.任何一个类在override时,必须遵守这些通用约定. 一.覆盖equals时请遵守通用的约定 1.Object中默认的equals方法约定是:类的每个实例都只与它自身相等.当类有自己特有的“逻辑相等”的概念时,就应该覆盖equals方法. 2.Timestamp对Date进行了扩展,Timestamp的equals实现确实违反了对称性.如果Timestamp和Date混合一起使用,可能导致不正确…
一.覆盖equals时请遵守通用约定 1.满足下列任何一个条件时,不需要覆盖equals方法 a.类的每个实例本质上都是唯一的.此时就是Object中equals方法所表达的含义. b.不关心类是否提供了“逻辑相等”的测试功能 c.超类中覆盖的equals方法,使用于子类,不需要自己再覆盖了. d.类是私有或者包级私有,并确定equals方法永远不会被调用,可以不覆盖.或者覆盖equals方法,内容为抛出异常. 2.高质量equals方法的诀窍: a.使用==操作符检测“参数是否为这个对象的引用…
想成为更优秀,更高效程序员,请阅读此书.总计78个条目,每个对应一个规则. 第二章 创建和销毁对象 一,考虑用静态工厂方法代替构造器 二, 遇到多个构造器参数时要考虑用builder模式 /** * 1.直接传参阅读性差,2.JavaBean多线程下存在安全问题,3.builder适用于大于5个参数并且参数是可选得情况 建造者(builder) 模式 * @author fancy */ public class Person implements Serializable { private…
覆盖clone时需要实现Cloneable接口,Cloneable并没有定义任何方法. 那Cloneable的意义是什么? 如果一个类实现了Clonable,Object的clone方法就可以返回该对象的逐域拷贝,否则会抛出CloneNotSupportedException. 通常,实现接口是为了表明类的行为. 而Cloneable接口改变了超类中protected方法的行为. 这是种非典型用法,不值得仿效. 好了,既然覆盖了clone方法,我们需要遵守一些约定: x.clone() != x…
Object类的所有非final方法(equals.hashCode.toString.clone.finalize)都要遵守通用约定(general contract),否则其它依赖于这些约定的类(HashMap,HashSet等)将不能正常工作. 8.覆盖equals时请遵守通用约定 无需覆盖equals的情形: 类的每个实例本质上是唯一的.类代表的是活动实体而不是值的概念.(例如,类Thread) 不关心类"逻辑相等"的功能,从Object继承的equals实现已经足够.(例如,…
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4255581.html 第三章      对所有对象都通用的方法 8.            覆盖equals时请遵守通用约定 如果类具有自己特定的"逻辑相等"概念(不同于对象等同概念)…
第8条:覆盖equals时请遵守通用约定 覆盖equals方法看起来似乎很简单,但是有许多覆盖方式会导致错误,并且后果非常严重.最容易避免这类问题的办法就是不覆盖equals方法,在这种情况下,类的每个实例都只与它自身相等. 那么,什么时候应该覆盖Object.equals呢?如果类具有自己特有的"逻辑相等"概念(不同于对象等同的概念),而且超类还没有覆盖equals以实现期望的行为,这时我们就需要覆盖 equals方法.这通常属于"值类(value class)"…
第10条:覆盖equals时,请遵守通用约定 1.使用==来比较两个对象的时候,比较的是两个对象在内存中的地址是否相同(两个引用指向的是否为同一个对象):Object中定义的equals方法也是这样比较的: 2.当我们自定义类的时候,如果不覆盖equals方法,那么就会使用默认的equals方法(Object中已经定义了),这样的话,只有当对象与对象自身比较才会返回true(指定同一个对象): // Object中的equals,只有对象与对象自身比较才会返回true public boolea…
第 10 条:覆盖equals时请遵守通用约定 在不覆盖equals方法下,类的每个实例都只与它自身相等. 类的每个实例本质上都是唯一的. 类不需要提供一个”逻辑相等(logical equality)”的测试功能. 父类已经重写了 equals 方法,并且父类的行为完全适合于该子类. 类是私有的或包级私有的,并且可以确定它的 equals 方法永远不会被调用. 什么时候需要覆盖equals方法?  如果一个类包含一个逻辑相等( logical equality)的概念——此概念有别于对象同一性…
1.覆盖equals请遵守通用规定.不需要覆写equals的场景:a.类的每个实例都是唯一的.b.类不需要提供"逻辑相等"的测试功能.c.超类已经覆盖了equals的方法.d.类是私有,or包私有,保证equals方法用不被调用.覆写场景:有独特的"逻辑相等".实现要求:a.自反,对称,传递,一致(多次比较得一样),对于任何非null值和null比较必须返回false.一致:不要使equals依赖不可靠的资源.(比如java.net.URL的equals依赖于URL…
本节主要涉及Object中通用的一些方法,比如equals,hashCode,toString,clone,finalize等等 覆盖equals时请遵守通用约定 equals方法实现的等价关系: 自反性:对于所有的非null,a=a 对称性:a=b,则b=a 传递性:a=b,b=c,则a=c 一致性:对于没有被修改的ab,如果a=b,则一直a=b 非空性:对于任何非Null,a!=null 高质量equals方法的诀窍: 使用==操作符检查--"参数是否为这个对象的引用" 使用ins…
第八条:覆盖equals时请遵守通用约定 什么时候需要覆盖equals方法?类具有自己的逻辑相等概念,并且父类的equals方法不能满足需要.重写equals时需要遵循一下约定: 自反性:非null x,x.equals(x)必须是true 对称性:非null x和y,y.equals(x)和x.equals(y)的结果必须一致 传递性:非null x.y.z,如果x.equals(y)和x.equals(z)的结果为true,那么y.equals(z)也必须为true 一致性:非null x.…
详解Java中的clone方法 参考:http://blog.csdn.net/zhangjg_blog/article/details/18369201/ 所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那么在java语言中,下面两种方式创建对象有什么区别呢? 使用new操作符创建一个对象 使用clone方法复制一个对象 那么这两种方式有什么相同和不同呢? new操作符的本意是分配内存.程序执行到new操作符时, 首先去看new操作符后面的类型,因为知道了类…
第8条:覆盖equals时请遵守通用的约定 设计Object类的目的就是用来覆盖的,它全部的非final方法都是用来被覆盖的(equals.hashcode.clone.finalize)都有通用约定. 首先看看equals方法: 若满足以下的这些情况中的某一个,您能够直接使用Object类中的equals方法而不用覆盖: 类的每个实例本质上是唯一的.对于那些代表实例而不是值的类来说能够不用覆盖equals方法.比方Thread类.由于每个Thread类的实例都表示一个线程,这与Thread某些…
什么是clone 在实际编程过程中,我们常常要遇到这种情况:有一个对象object1,在某一时刻object1中已经包含了一些有效值,此时可能会需要一个和object1完全相同新对象object2,并且此后对object2任何改动都不会影响到object1中的值,也就是说,object1与object2是两个独立的对象,但object2的初始值是由object1对象确定的.在Java语言中,用简单的赋值语句是不能满足这种需 求的.要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单…
这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约会持续1个月左右. 第1条:考虑用静态工厂方法代替构造器 通常情况下我们会利用类的构造器对其进行实例化,这似乎毫无疑问.但“静态工厂方法”也需要引起我们的高度注意. 什么是“静态工厂方法”?这不同于设计模式中的工厂方法,我们可以理解它为“在一个类中用一个静态方法来返回这个类的实例”,例如: public st…
<Effective Java(中文第二版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382186 Java(中文第二版)>[PDF]"  TITLE="<Effective Java(中文第二版)>[PDF]" /> 编辑推荐 <Sun 公司核心技术丛书:EffectiveJava中文版(第2版)>内容全面,结构清晰,讲解详细.可作为技术人员的参考用书.编码平添乐…
说明 这里是阅读<Effective Java中文版第二版>的读书笔记,这里会记录一些个人感觉稍微有些重要的内容,方便以后查阅,可能会因为个人实力原因导致理解有误,若有发现欢迎指出.一些个人还不理解的会用斜线标注. 第一章是引言,所以跳过. 第二章 创建和销毁对象 第1条:考虑用静态工厂方法代替构造器 含义 静态工厂方法是指一个返回类的实例的静态方法,例如: public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE :…