EffectiveJava(16)复合优先于继承】的更多相关文章

为什么复合优先于继承? 1.继承违反了封装原则,打破了封装性 2.继承会不必要的暴露API细节,称为隐患.比如通过直接访问底层使p.getProperty(K,V)的键值对可以不是String类型 3.继承限定了类的性能,它会把它的缺陷传递给子类 1.复合:不必扩展现有的Set类,而是在此类中加一个私有域,它引用现有类的一个实例 2.它的封装特性使得它更加健壮灵活 3.复合允许设计新的API隐藏父类的缺点 在继承中的例子 public class InstrumentedHashSet<E>…
继承时实现代码重用的重要手段,但它并非永远是完成这项工作的最佳工具,不恰当的使用会导致程序变得很脆弱,当然,在同一个程序员的控制下,使用继承会变的非常安全.想到了很有名的一句话,你永远不知道你的用户是如何使用你写的程序的,一个程序员继承另一个程序员写的类也是同样的危险. 于方法调用不同的是,继承打破的封装性.换句话说,子类依赖于其超类中特定功能的实现细节.超类的实现有可能随着发行版本的不同而变化,如果真的发生了变化,子类可能会遭到破坏,即使它的代码完全没有修改过.因而,子类有必要随着超类的更新而…
复合优于继承 继承打破了封装性(子类依赖父类中特定功能的实现细节) 合理的使用继承的情况: 在包内使用 父类专门为继承为设计,并且有很好的文档说明,存在is-a关系 只有当子类真正是父类的子类型时,才适合用继承. 对于两个类A和B,只有两者之间存在"is-a"关系,类B才能拓展类A. 继承机制会把父类API中的所有缺陷传播到子类中,而复合允许设计新的API来隐藏这些缺陷. 复合(composition):不扩展现有的类,而是在新的类中增加一个私有域,引用现有类的一个实例. 转发(fow…
这个,不管是什么书都会这样说,因为常常我们并不需要继承,而只是想把类进行一定的扩展,而我们想扩展的属性或方法对应的类都有,这个时候如果两者是is a的关系,这种关系是确实存在的,那么就可以使用继承,不然一般都是建议使用复合. 如果我们队一个类进行继承的时候,我们如果对其内部的逻辑并不十分了解的时候,直接继承的结果就是可能有些方法是类自己内部调用的,而我们在继承这个方法的时候,可能会覆盖某些方法,或者重载某些方法,或者加上了一些自己的逻辑,这样就会吧原来的逻辑和我们自己的逻辑混杂起来,并且如果继承…
继承是实现代码重用的方法之一,但使用不当则会导致诸多问题. 继承会破坏封装性,对一个具体类进行跨包访问级别的继承很危险. 即,子类依赖父类的实现细节. 如果父类的实现细节发生变化,子类则可能遭到破坏. 举个例子,扩展HashSet,记录HashSet实例创建以来一共进行了多少次添加元素的操作. HashSet有两个添加元素的方法——add(E e)和addAll(Collection<? extends E> c). 那就覆盖这两个方法,在添加操作执行前记录次数: public class I…
泛型类型比需要在客户端代码中强制转换的类型更安全,更易于使用. 当你设计新的类型时,确保它们可以在没有这种强制转换的情况下使用. 这通常意味着使类型泛型化. 如果你有任何现有的类型,应该是泛型的但实际上却不是,那么把它们泛型化. 这使这些类型的新用户的使用更容易,而不会破坏现有的客户端. 像泛型类型一样,泛型方法比需要客户端对输入参数和返回值进行显式强制转换的方法更安全,更易于使 用. 像类型一样,你应该确保你的方法可以不用强制转换,这通常意味着它们是泛型的.…
代码应该被重用,而不是被拷贝 同大多数学科一样,学习编程的艺术首先要学会基本的规则,然后才能知道什么时候可以打破这些规则   创建和销毁对象 1.考虑用静态工厂方法代替构造器. 优势:有名称.不必再每次调用他们的时候都创建一个对象.可以返回原类型的任何子类型的对象.代码变得更简洁 //抽象产品角色 public interface Car { public void drive(); } //具体产品角色 public class Benz implements Car { public voi…
第4章 类和接口 类和接口是Java程序设计语言的核心,它们也是Java语言的基本抽象单元.Java语言提供了许多强大的基本元素,供程序员用来设计类和接口. 13. 使类和成员的可访问性最小化 要区别设计良好的模块与设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节.设计良好的模块会隐藏所有的实现细节,把它的API与它的实现清晰隔离开来.然后,模块直接只通过他们的API进行通信.一个模块不需要知道其他模块的内部工作情况.这个概念被称为信息隐藏或封装…
1.考虑用静态工厂方法代替构造器 public static Boolean valueOf(boolean b){ return b?Boolean.TRUE:Boolean.FALSE; } 静态工厂方法与构造器不同的第一大优势在于,它们有名称,有名称可以更好地构建清晰的对象. 静态工厂方法与构造器不同的第二大优势在于,不必在每次调用它们的时候都创建一个新对象,实例受控的类. 静态工厂方法与构造器不同的第三大优势在于,它们可以返回原返回类型的任何子类型的对象,API可以返回对象,同时又不会使…
复合优先于继承,继承是实现代码重用的有力手段,并不是所有情况都适用,使用不当会导致软件变得很脆弱.与方法调用不同的是,继承打破了封装性. 总而言之,组合和继承,都能实现对类的扩展.但是要分具体情况用哪个实现,是Has-a,还是Is-a的关系. 两者区别如下表所示: 组合  继承 has-a关系 is-a关系 运行期决定 编译期决定 不破坏封装,整体和局部松耦合 破坏封装,子类依赖父类 支持扩展,随意增加组合类 只能继承一个父类,必须包含所有方法,增加系统复杂性 动态选择组合类方法 复用父类方法…
JAVA中使用到继承就会有两个无法回避的缺点: 打破了封装性,迫使开发者去了解超类的实现细节,子类和超类耦合. 超类更新后可能会导致错误. 继承打破了封装性 关于这一点,下面是一个详细的例子(来源于Effective Java第16条) public class MyHashSet<E> extends HashSet<E> { private int addCount = 0; public int getAddCount() { return addCount; } @Over…
为什么说JAVA中要慎重使用继承   这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两个无法回避的缺点: 打破了封装性,子类依赖于超类的实现细节,和超类耦合. 超类更新后可能会导致错误. 继承打破了封装性 关于这一点,下面是一个详细的例子(来源于Effective Java第16条) public class MyHashSet<E> extends HashSet<E>…
类与接口是Java语言的核心,设计出更加有用.健壮和灵活的类与接口很重要. 13.使类和成员的可访问性最小化 设计良好的模块会隐藏起所有的实现细节,仅使用API与其他模块进行通信.这个概念称为信息隐藏或封装,是软件设计的基本原则之一.信息隐藏可以是实现系统各模块的解耦,以使这些模块可以独立的开发.测试.优化.信息隐藏还提高了软件的可重用性,降低了构建大型系统的风险. java中实体的可访问性由实体声明的位置以及访问修饰符(private.不写.protected.public)共同决定.尽可能的…
目录: 一.创建和销毁对象 (1 ~ 7) 二.对于所有对象都通用的方法 (8 ~ 12) 三.类和接口 (13 ~ 22) 四.泛型 (23 ~ 29) 五.枚举和注解 (30 ~ 37) 六.方法 (38 ~ 44) 七.通用程序设计 (45 ~ 56) 八.异常 (57 ~ 65) 九.并发 (66 ~ 73) 十.序列化 (74 ~ 78)   正文:   第一章: 创建和销毁对象 1.考虑用静态工厂方法代替构造器 优: ① 有名称 ② 不必在每次调用它们的时候都创建一个对象 ③ 可以放…
第15条:使可变性最小化 通过一个复数类来看不可变类. public final class Complex { private final double re; private final double im; private Complex(double re, double im) { this.re = re; this.im = im; } public static Complex valueOf(double re, double im) { return new Complex(…
这篇博客是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版)>内容全面,结构清晰,讲解详细.可作为技术人员的参考用书.编码平添乐…
第二章——创建和销毁对象 第1条:考虑用静态工厂方法替代构造器 第2条:遇到多个构造器参数时要考虑用构建器 第3条:用私有构造器或者枚举类型强化Singleton属性 第4条:通过私有构造器强化不可实例化的能力 第5条:避免创建不必要的对象 第6条:消除过期的对象引用 第7条:避免使用终结方法 第三章——对于所有对象都通用的方法 第8条:覆盖equals时请遵守通用约定 第9条:覆盖equals时总要覆盖hashCode 第10条:始终要覆盖toString 第11条:谨慎地覆盖clone 第1…
第13条: 使类和成员的可访问性最小化 良好的模块设计能隐藏其内部数据和其他实现细节,模块之间只通过它们的API进行通信.java语言提供了许多机制来协助隐藏信息.访问控制机制决定了类.接口和成员的可访问性,实体的可访问性是由该实体申明所在的位置,以及该实体申明中所出现的访问修饰符共同决定.正确使用修饰符对于实现信息隐藏非常关键. 1.尽可能使每个类或成员不被外界访问.对于成员有四种可能的访问级别. a.私有的--只有在申明该成员的顶层类内部才可以访问这个成员. b.包级私有--申明该成员的包内…
这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约会持续1个月左右. 第1条:考虑用静态工厂方法代替构造器 通常情况下我们会利用类的构造器对其进行实例化,这似乎毫无疑问.但“静态工厂方法”也需要引起我们的高度注意. 什么是“静态工厂方法”?这不同于设计模式中的工厂方法,我们可以理解它为“在一个类中用一个静态方法来返回这个类的实例”,例如: public st…
目录 第13条: 使类和成员的可访问性最小化 第14条:在公有类中使用访问方法而非公有域 第15条:使可变性最小化 第16条:复合优先于继承 第17条:要么为继承而设计,并提供文档说明,要么就禁止继承 第18条:接口优先于抽象类 第19条:接口只用于定义类型 第20条:类层次优于标签类 第21条:用函数对象表示策略 第22条:优先考虑静态成员类   第4章 类和接口 第13条: 使类和成员的可访问性最小化 尽可能使每个类或者成员不被外界访问.提供尽可能小的访问级别. final维持字段不可变性,…
第1章 引言 第2章 创建和销毁对象 第1条:考虑用静态工厂方法代替构造器(Consider static factory methods instead of constructors) 第2条:遇到多个构造器参数时要考虑用构建器(Consider a builder when faced with many constructor parameters ) 第3条:用私有构造器或者枚举类型强化Singleton属性( Enforce the singleton property with a…
推荐序 前言 致谢 第一章 引言 第二章 创建和销毁对象 第1项:用静态工厂方法代替构造器 第2项:遇到多个构造器参数时要考虑使用构建器 第3项:用私有构造器或者枚举类型强化Singleton属性 第4项:通过私有构造器强化不可实例化的能力 第5项:优先考虑依赖注入来引用资源 第6项:避免创建不必要的对象 第7项:消除过期的对象引用 第8项:避免使用终结方法和清除方法 第9项:try-with-resources优先于try-finally 第三章 对于所有对象都通用的方法 第10项:覆盖equ…
第13条:使类和成员的可访问性最小化 第一规则很简单:尽可能地使每个类或者成员不被外界访问.换句话说.应该使用与你正在编写的软件的对应功能相一致的.尽可能最小的访问级别. 对于顶层的(非嵌套的)类和接口,只有两种可能的访问级别:包级私有的(package-private)和公有的(public).如果你用public修饰符声明了顶层类或者接口,那它就是公有.否则,它将是包级私有的.如果类或者接口能够被做成包级私有的,它就应该被做成包级私有的.通过把类或者接口做成包级私有,它实际上成了这个包的实现…
第8条:覆盖equals时请遵守通用约定 覆盖equals方法看起来似乎很简单,但是有许多覆盖方式会导致错误,并且后果非常严重.最容易避免这类问题的办法就是不覆盖equals方法,在这种情况下,类的每个实例都只与它自身相等. 那么,什么时候应该覆盖Object.equals呢?如果类具有自己特有的"逻辑相等"概念(不同于对象等同的概念),而且超类还没有覆盖equals以实现期望的行为,这时我们就需要覆盖 equals方法.这通常属于"值类(value class)"…
第1条:考虑用静态工厂方法代替构造器 通常我们会使用 构造方法 来实例化一个对象,例如: // 对象定义 public class Student{ // 姓名 private String name; // 性别 private String sex; public Student(String name,String sex){ this.name = name; this.sex = sex; } } // 实例化对象 Student student = neew Student("Mar…
读<Effect Java中文版> 译者序 序 前言 第1章引言 1   第2章创建和销毁对象 4 第1条:考虑用静态工厂方法代替构造函数 4 第2条:使用私有构造函数强化singleton属性 8 第3条:通过私有构造函数强化不可实例化的能力 10 第4条:避免创建重复的对象 11 第5条:消除过期的对象引用 14 第6条:避免使用终结函数 17   第3章对于所有对象都通用的方法 21 第7条:在改写equals的时候请遵守通用约定 21 第8条:改写equals时总是要改写hashCod…
面向对象 01.构造器参数太多怎么办? 如果参数很多,会导致构造方法非常多,拓展性差,代码难编写,且难以看懂. 用JavaBeans模式, get和set 一行构造编程多行代码实现,需要使用额外机制确保一致性和线程安全. 用builder模式, 1.5个或者5个以上的成员变量 2.参数不多,但是在未来,参数会增加 Builder模式: 属于对象的创建模式,一般有 1. 抽象建造者:一般来说是个接口,包含1)建造方法,建造部件的方法(不止一个),2)返回产品的方法 2. 具体建造者 3. 导演者,…
本系列Netty源码解析文章基于 4.1.56.Final版本,公众号:bin的技术小屋 前文回顾 在前边的系列文章中,我们从内核如何收发网络数据开始以一个C10K的问题作为主线详细从内核角度阐述了网络IO模型的演变,最终在此基础上引出了Netty的网络IO模型如下图所示: 详细内容可回看<从内核角度看IO模型的演变> 后续我们又围绕着Netty的主从Reactor网络IO线程模型,在<Reactor模型在Netty中的实现>一文中详细阐述了Netty的主从Reactor模型的创建…
Num1:使类和成员的可访问性最小化 要区别设计良好的模块与设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节.设计良好的模块会隐藏所有的实现细节,把它的API与它的实现清晰地隔离开来.也称呼为封装. 所以有这么一句话:尽可能地使每个类或者成员不被外界访问,可以包括实体声明中所出现的访问修饰符共同决定的,有四种访问级别,如下: 私有的,private 包级私有的,default 受保护的,protected 公有的,public Num2:在公有类…