Effective Java笔记(18)复合优先于继承

避坑指南:为什么你的conda环境装不上Mamba?从CUDA到ABI的深度排查 本文深入解析conda环境中安装Mamba架构时常见的CUDA版本冲突、ABI不匹配等问题,提供从基础检查到深度排查的系统化解决方案。针对`causal-conv1d`和`mamba-ssm`安装失败场景,详细讲解PyTorch版本绑定、编译器工具链兼容性等关键技术要点,并给出预编译wheel选择、动态链接库配置等实用修复方案。 阅读详情

        继承( inheritance)是实现代码重用的有力手段,但它并非永远是完成这项工作的最佳工具 。 使用不当会导致软件变得很脆弱 。 在包的内部使用继承是非常安全的,在那里子类和超类的实现都处在同一个程序员的控制之下 。 对于专门为了继承而设计并且具有很好的文档说明的类来说,使用继承也是非常安全的 。 然而,对普通的具体类( concrete class )进行跨越包边界的继承,则是非常危险的 。 提示一下,本文使用“继承”一词,含义是实现继承(当一个类扩展另一个类的时候) 。 本条目中讨论的问题并不适用于接口继承(当一个类实现一个接口的时候,或者当一个接口扩展另一个接口的时候) 。

        与方法调用不同的是,继承打破了封装性。 换句话说,子类依赖于其超类中特定功能的实现细节。 超类的实现有可能会随着发行版本的不同而有所变化,如果真的发生了变化,子类可能会遭到破坏,即使它的代码完全没有改变 。 因而,子类必须要跟着其超类的更新而演变,除非超类是专门为了扩展而设计的,并且具有很好的文挡说明 。

        为了说明得更加具体一点,我们假设有一个程序使用了 HashSet 。 为了调优该程序的性能,需要查询 HashSet ,看一看自从它被创建以来添加了多少个元素(不要与它当前的元素数目混淆起来, 它会随着元素的删除而递减) 。 为了提供这种功能,我们得编写一个HashSet 变体,定义记录试图插入的元素的数量 addCount ,并针对该计数值导出一个访问方法 。
        HashSet 类包含两个可以增加元素的方法:add 和 addAll ,因 此这两个方法都要被覆盖 :

public class InstrumentedHashSet<E> extends HashSet<E>
{
    private int addCount = 0;

    public InstrumentedHashSet() {
    }

    public InstrumentedHashSet(int initCap, float loadFactor) {
        super(initCap, loadFactor);
    }

    @Override public boolean add(E e) {
        addCount++;
        return super.add(e);
    }

    @Override public boolean addAll(Collection<? extends E> c) {
        addCount += c.size();
        return super.addA11(c);
    }

    public int getAddCount() {
        return addCount;
    }
}

        这个类看起来非常合理,但是它并不能正常工作 。 假设我们创建了一个实例,并利用addAll 方法添加了三个元素 。 顺便提一句,注意我们利用静态工厂方法 List.of 创建了一个列表,该方法是在 Java 9 中增加的 。 如果使用较早的版本,则用 Arrays.asList 代替 :

InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
s.addAll(List.of("Snap","Crackle", "Pop"));

        此时我们期 望 getAddCount 方法能返回 3 ,但是实际上它返回的是 6 。 哪里出错了呢?在 HashSet 的内部,addAll 方法是基于它的 add 方法来实现的,即使 HashSet的文档中并没有说明这样的实现细节,这也是合理的 。InstrumentedHashSet 中的addAll 方法首先给 addCount 增加 3,然后利用 supper.addAll 来调用 HashSet 的addAll 实现 。 然后又依次调用到被InstrumentedHashSet 覆盖了的 add 方法,每个元素调用一次 。 这三次调用又分别给 addCount 加了1 ,所以总共增加了 6: 通过 addAll方法增加的每个元素都被计算了两次 。

        我们只要去掉被覆盖的 addAll 方法就可以“修正”这个子类 。 虽然这样得到的类可以正常工作,但是它的功能正确性则需要依赖于这样的事实:HashSet 的 addAll 方法是在它的 add 方法上实现的。 这种“自用性”( self-use )是实现细节,不是承诺,不能保证在 Java 平台的所有实现中都保持不变,不能保证随着发行版本的不同而不发生变化 。因此,这样得到的 InstrumentedHashSet 类将是非常脆弱的 。

        问题都来源于覆盖( overriding )方法 。 你可能会认为在扩展一个类的时候,仅仅增加新的方法,而不覆盖现有的方法是安全的 。 虽然这种扩展方式比较安全一些,但是也并非完全没有风险。 如果超类在后续的发行版本中获得了一个新的方法,并且不幸的是,你给子类提供了一个签名相同但返回类型不同的方法 , 那么这样的子类将无法通过编译。 如果给子类提供的方法带有与新的超类方法完全相同的签名和返回类型,实际上就覆盖了超类中的方法,因此又回到了问题 。 此外,你的方法是否能够遵守新的超类方法的约定,这也是很值得怀疑的,因为当你在编写子类方法的时候,这个约定压根还没有面世 。

        幸运的是,有一种办法可以避免前面提到的所有问题 。 即不扩展现有的类,而是在新的类中增加一个私有域,它引用现有类的一个实例 。 这种设计被称为“复合”( composition),因为现有的类变成了新类的一个组件 。 新类中的每个实例方法都可以调用被包含的现有类实例中对应的方法,并返回它的结果 。 这被称为转发( forwarding ),新类中的方法被称为转发方法(forwarding method) 。 这样得到的类将会非常稳固,它不依赖于现有类的实现细节 。即使现有的类添加了新的方法,也不会影响新的类 。 为了进行更具体的说明,请看下面的例子,它用复合/转发的方法来代替 InstrumentedHashSet 类 。 注意这个实现分为两部分 : 类本身和可重用的转发类( forwarding class ),其中包含了所有的转发方法,没有任何其他的方法 :

// Wrapper class - uses composition in place of inheritance
public class InstrumentedSet<E> extends ForwardingSet<E>
{
    private int addCount = 0;

    public InstrumentedSet(Set<E> s) {
        super(s);
    }

    @Override
    public boolean add(E e) {
        addCount++;
        return super.add(e);
    }

    @Override
    public boolean addA11(Collection<? extends E> c) {
        addCount += c.size();
        return super.addA11(c);
    }

    public int getAddCount() {
        return addCount;
    }
}

// Reusable forwarding class
public class ForwardingSet<E> implements Set<E>
{
    private final Set<E> s;

    public ForwardingSet(Set<E> s) {
        this.s = s;
    }

    public void clear() {
        s.clear();
    }

    public boolean contains(Object o { return s. contains(o); }

    public boolean isEmpty() {
        return s.isEmpty();
    }

    public int size() {
        return s.size();
    }

    public Iterator<E> iterator() {
        return s.iterator();
    }

    public boolean add(E e) {
            return s.add(e);

    public boolean remove(Object o) {
        return s.remove(o);
    }

    public boolean containsA11(Collection<?> c) {
        return s.containsA11(c);
    }

    public boolean addAll(Collection<? extends E> c) {
        return s.addAll(c);
    }

    public boolean removeAll(Collection<?> c) {
        return s.removeAll(c);
    }

    public boolean retainAll(Collection<?> c) {
        return s.retainAll(c);
    }

    public Object[] toArray() {
        return S.toArray();
    }

    public <T> T[] toArray(T[] a) {
        return s.toArray(a);
    }

    @Override
    public boolean equals(Object o) {
        return s.equals(o);
    }

    @Override
    public int hashCode() {
        return s.hashCode();
    }

    @Override
    public String toString() {
        return s.toString();
    }
}

        Set 接口的存在使得 InstrumentedSet 类的设计成为可能,因为 Set 接口保存了 HashSet 类的功能特性 。 除了获得健壮性之外,这种设计也带来了更多的灵活性 。InstrumentedSet 类实现了 Set接口,并且拥有单个构造器,它的参数也是 Set 类型 。从本质上讲,这个类把一个 Set 转变成了另一个Set,同时增加了计数的功能 。 前面提到的基于继承的方法只适用于单个具体的类,并且对于超类中所支持的每个构造器都要求有一个单独的构造器,与此不同的是,这里的包装类(wrapper class)可以被用来包装任何Set实现,井且可以结合任何先前存在的构造器一起工作:

Set<Instant> times = new InstrumentedSet<>(new TreeSet<>(cmp));
Set<E> s = new InstrumentedSet<> (new HashSet<> (INIT_CAPACITY));

InstrumentedSet 类甚至也可以用来临时替换一个原本没有计数特性的 Set 实例:

static void walk(Set<Dog> dogs) {
    InstrumentedSet<Dog> iDogs = new InstrumentedSet<>(dogs) ;
    ...// Within this method use iDogs instead of dogs
}

        因为每一个 InstrumentedSet 实例都把另一个 Set 实例包装起来了,所以 Instru­mentedSet 类被称为包装类( wrapper class ) 。 这也正是 Decorator(修饰者)模式,因为 InstrumentedSet 类对一个集合进行了修饰,为它增加了计数特性 。 有时复合和转发的结合也被宽松地称为“委托” 。 从技术的角度而言 ,这不是委托 ,除非包装对象把自身传递给被包装的对象。

        包装类几乎没有什么缺点 。 需要注意的一点是, 包装类不适合用于回调框架( callback framework );在回调框架中,对象把自身的引用传递给其他的对象,用于后续的调用(“回调”) 。 因为被包装起来的对象并不知道它外面的包装对象,所以它传递一个指向自身的引
用( this ),回调时避开了外面的包装对象 。 这被称为 SELF 问题。 有些人担心转发方法调用所带来的性能影响,或者包装对象导致的内存占用 。 在实践中,这两者都不会造成很大的影响。 编写转发方法倒是有点琐碎,但是只需要给每个接口编写一次构造器,转发类则可以通过包含接口的包提供。 例如,Guava 就为所有的集合接口提供了转发类 。

        只有当子类真正是超类的子类型( subtype)时,才适合用继承 。 换句话说,对于两个类A 和 B,只有当两者之间确实存在“ is-a ”关系的时候,类 B 才应该扩展类 A 。 如果你打算让类 B 扩展类 A ,就应该问问自己:每个 B 确实也是 A 吗?如果你不能够确定这个问题的答案是肯定的,那么 B 就不应该扩展 A 。 如果答案是否定的,通常情况下,B 应该包含 A的一个私有实例,并且暴露一个较小的、较简单的 API:A 本质上不是 B 的一部分,只是它的实现细节而已 。

        在 Java 平 台类库中,有许多明显违反这条原则的地 方 。 例如,栈( stack )并不是向量( vector ),所以 Stack 不应该扩展 Vector 。 同样地,属性列表也不是散列表,所以Properties 不应该扩展 Hash table 。 在这两种情况下,复合模式才是恰当的 。

        如果在适合使用复合的地方使用了继承,则会不必要地暴露实现细节 。 这样得到的 API会把你限制在原始的实现上,永远限定了类的性能 。 更为严重的是,由于暴露了内部的细节,客户端就有可能直接访问这些内部细节 。 这样至少会导致语义上的混淆 。 例如,如果 p指向 Properties 实例,那么 p.getProperty(key )就有可能产生与 p.get( key )不同的结果 : 前一个方法考虑了默认的属性表,而后一个方法则继承自 Hash table ,没有考虑默认的属性列表 。 最严重的是,客户有可能直接修改超类,从而破坏子类的约束条件 。 在Properties 的情形中,设计者的目标是只允许字符串作为键( key )和值( value ),但是直接访问底层的 Hashtable 就允许违反这种约束条件。 一旦违反了约束条件 ,就不可能再使用Properties API 的其他部分( load 和 store )了 。 等到发现这个问题时, 要改正它已经太晚了,因为客户端依赖于使用非字符串的键和值了 。

        在决定使用继承而不是复合之前,还应该问自己最后一组问题 。 对于你正试图扩展的类,它的 API 中有没有缺陷呢?如果有,你是否愿意把那些缺陷传播到类的 API 中?继承机制会把超类 API 中的所有缺陷传播到子类中,而复合则允许设计新的 API 来隐藏这些缺陷 。

        简而言之,继承的功能非常强大,但是也存在诸多问题,因为它违背了封装原则。只有当子类和超类之间确实存在子类型关系时,使用继承才是恰当的 。 即使如此,如果子类和超类处在不同的包中,并且超类并不是为了继承而设计的,那么继承将会导致脆弱性( fragility )。为了避免这种脆弱性,可以用复合和转发机制来代替继承,尤其是当存在适当的接口可以实现包装类的时候。 包装类不仅比子类更加健壮,而且功能也更加强大。

保姆级教程:在Davinci Configurator里配置BswM的ECU状态机(附状态切换流程图) 本文提供了一份详细的AUTOSAR BswM模块配置指南,通过Davinci Configurator工具实现ECU状态机的构建与管理。内容涵盖从模式请求端口创建到状态切换规则定义的全流程,特别针对Ecu State Handling进行了深入解析,并附有状态切换流程图,帮助汽车电子工程师高效完成ECU状态管理配置。 阅读详情

相关推荐

STM32CubeMX和华为LiteOS Studio开发STM32

传统的STM32的开发通常使用Keil/IAR这类开发软件,随着物联网时代的到来,传统嵌入式的发展不断向物联网方向靠拢,而Keil/IAR这类开发软件无法满足IoT一站式的开发,华为LiteOS Studio结合STM32CubeMX可以快速,高效地进行物联网开发,本文提供一种开发思路及环境的配置方法。...

weixin_45680600的博客 2833

复合优于继承

问题 当通过子类继承父类并不是代码重用的最好手段,有这样的缺点: 与方法调用不同的是,继承打破封装性。子类依赖于父类,如果父类的具体实现细节改变,子类也会跟着相应改变。除非父类就是专门为扩展而设计的,并且有良好的文档说明; 父类方法中的”自用性“问题,导致的子类方法逻辑出错,比如统计HashSet自创建以来插入了多少个元素,需要覆盖add()方法和addAll()方法: public c...

ylx1066863710的博客 262

SFR算法实现详解:从边缘检测到MTF计算的完整流程

本文详细解析了SFR算法从边缘检测到MTF计算的完整流程,包括边缘检测、ESF超采样、LSF差分等关键步骤。通过代码示例和实战经验,帮助开发者高效实现成像系统解析力评估,优化MTF测量精度。适用于摄像头模组调试、工业检测等场景。

Black的专栏 1009

Java:Effective java学习笔记之 复合优先于继承

Java复合优先于继承复合优先于继承1、实现继承和接口继承2、在实际开发中继承的缺点2.1、子类依赖于其超类中特定功能的实现细节3、什么是复合?3.1、书上案例4、复合相比较于继承的优点和缺点5、何时使用继承,何时使用复合?参考 复合优先于继承 面向对象编程中,有一条非常经典的设计原则,那就是:组合优于继承,多用组合少用继承。同样地,在《阿里巴巴Java开发手册》中有一条规定:谨慎使用继承的方式进行扩展,优先使用组合的方式实现。 1、实现继承和接口继承 实现继承:当一个类扩展另一个类的时候 接口继承:当一

JMW1407的博客 1272

油气井管柱力学发展

油气井管柱力学发展 1 石油管柱力学问题的发复杂性 1)油气管柱动力学的非线性 钻井中钻柱在重力、钻压、扭矩、钻井液浮力和井壁约束等作用下,产生三维变形。一方面随井眼轴线的弯曲而弯曲,这一变形被称为管柱的初位移;另一方面,管柱在运动过程中相对井眼轴线也有变形,这种变形被称为计算位移。管柱大变形主要表现在初位移部分,计算位移相对很小。大曲率井眼中管柱产生大挠度,但管柱很长且柔软性较好,变形一般仍保持...

weixin_43831995的博客 950

动态对抗Zygisk-IL2CppDumper:Unity游戏安全新策略

本文深入探讨了对抗Zygisk-IL2CppDumper攻击的Unity游戏安全新策略。通过实时内存监控、动态混淆技术和异常行为检测体系,有效防止关键代码被动态提取。文章详细介绍了内存指纹系统、运行时混淆方案和五维特征模型等实用防御手段,帮助开发者提升游戏安全性。

weixin_29325955的博客 306

Effective Java第二版第4章

4 类和接口 第13条 使类和成员的可访问性最小化 当访问级别从default变成protected的时候,会大大增加可访问性。protected的成员是类导出的API的一部分,必须永远得到支持。导出的类的protected成员也代表了该类对于某个实现细节的公开承诺。受保护的成员应该尽量少用。 **实例域决不能是公有的。**如果域是非final的,或者是一个指向可变对象的final引用,那么一旦使这个域成为共有的,就放弃了对存储在这个域中的值进行限制的能力;这意味着,你也放弃了强制这个域不可变的能力。同时,

kaikai_sk的博客 2624

反激开关电源变压器设计实例讲解(定明芳)

内容来自《反激变压器的设计》(定明芳主讲)。 定名芳老师主要讲了10步,最后应该还有一步,线径的选择已经绕制方式。这里进行了记录整理,把一些公式来源进行了推导。所有的设计都是基于理论计算。 1.确定电源规格 2.确定工作频率和最大占空比 3.计算匝比(利用伏秒平衡原则) 此处插入解释一下伏秒平衡,根源是磁通量平衡。该原则可以用来检查MOS管耐压是否够。 4.计算初级线圈峰值电流 基于CCM模式计算的。ip1是开关管要关闭时的峰值电流,ip2是开关管开始导通时的起始电流。因为时CCM模式,所以,ip

ydgd118的博客 5万+

《Effective Java》 读书笔记

第2章 创建与销毁对象 第1条:考虑用静态方法代替构造器 获取实例的方法:公有构造器;公有的静态工厂方法 静态工厂方法优势: 有名称; 不必在每次调用它们时候第一创建一个新对象;可以返回原返回类型的任何子类型的对象。在创建参数化类型实例的时候,它们使代码更加简洁 静态工厂方法缺点: 类如果不含公有的或者受保护的构造器,就不能被子类化与其他的静态方法实际上没有任何区别

Take pains, and be perfect 414

摄像头读取出现VIDIOC_STREAMON: No space left on device 错误

先说下原因,linux中为usb camera提供了一个标准的V4L2的驱动以方便使用,只要符合驱动规范就可以实现即插即用usb camera设备,即免驱动安装。 但市面上的USB 摄像头都是2.0的。usb bus的 bandwidth是有限的,而V4L2驱动采用的是贪心原则,即camera会要求获取最大带宽;因此将两个camera接入一路usb bus,打开第二个camera(尤其是采用YUV...

houge101的博客 9290

智能车图像处理21-进阶篇13--正入十字补线2

这篇文章主要的正入十字补线与1基本相同,主要防止图像中双十字的问题。

taiyuezyh的博客 2033

类和接口——复合优先于继承

理由如下:当我们要扩展一个类时,特别是一个别人写好的类,一个类库的类,我们往往关心的仅仅是单个api的功能,而不关心他的实现,但是存在的一个问题就是,同一个类的各个方法直接可能存在联系,可能一个方法的实现依赖于另一个方法,这就意味着,当我们调用一个我们想要操作的方法时,“继承”会隐式的调用另一个方法,这就可能存在问题。因为,在hashSet的addAll()实现中,是循环调用add()方法的,所以导致3*2。需求:新建一个集合类,维护一个addCount变量,记录,一共添加了多少次新值。

GSON的博客 271

计算机网络实验报告实验七可靠传输TCP协议分析

计算机网络实验报告实验七可靠传输TCP协议分析

m0_56638814的博客 966

《Effective Java》解读第18条:复合优先于继承

本文探讨了面向对象设计中复合优先于继承的原则。继承在跨包使用时存在风险,会破坏封装性(子类依赖父类实现细节)、可能破坏子类(父类更新导致冲突)、且并非所有情况都符合"is-a"关系。复合通过在新类中持有现有类的实例并转发方法调用,提供了更安全的复用方式。虽然复合存在"丢失身份"引用和轻微性能开销等缺点,但在大多数情况下仍是更好的选择。只有当子类真正是父类的子类型且愿意继承父类所有API缺陷时,才应考虑使用继承。

Cosmoshhhyyy的博客 632

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Effective Java – Item 18 复合优先于继承

item18 · 复合优先于继承 此处继承不包括接口继承、包内部使用继承 继承打破了封装性 子类依赖于父类的实现,父类变化时子类会遭破坏 public class InstrumentedHashSet<E> extends HashSet<E> { private int addCount = 0; public InstrumentedHashSet...

AlbumenJ的博客 231

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

《Effective Java》第18条:复合优先于继承

原文P72:这样得到的类将会非常稳固,它不依赖于现有类的实现细节,即使现有的类添加了新的方法,也不会影响新的类。在 ForwardingSet 类中可以看到,该类 复合 了 Set 接口,将里面所有的方法进行了转发,而不是重写,同时又实现了Set类,这一点很重要,后续所有继承自 ForwardingSet 类的子类,都是Set的子类,即,InstrumentedHashSet 也是一个Set集合,同时拥有了计数的功能。上面的这些问题,都是因为子类覆盖了超类的方法而导致的,如果不覆盖现有的方法可不可以呢?

TD_FAlmK的博客 62

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Effective Java 【类和接口】第18条 复合优先于继承

目录前言如何解决问题什么是复合总结 前言 在包的内部使用继承是非常安全的,在那里子类和超类的实现都处在同一个程序员的控制之下。对于专门为了继承而设计并且具有很好的文档说明的类来说(详见第19条),使用继承也是非常安全的。 然而,对普通的具体类进行跨越包边界的继承,则是非常危险的。 其原因主要是因为: 与方法调用不同的是,继承打破了封装性。子类依赖于其超类中特定功能的实现细节。如果超类中的实现改变,就有可能给子类的逻辑带来很大的危害。因而,子类必须要跟着其超类的更新而演变,除非超类是专门为了扩展而设计的,并且

zhangxiaoxiao9527的博客 212

Effective Java 第三版 中文翻译

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

Coloured_Glaze的博客 3861

Effective Java 高效编码阅读 笔记

函数参数可以传入类似listener的对象,目的是使用listener中的方法。如果使用匿名的参数,每一次调用会创建新的对象。可以将listener声明为成员变量,每次都复用同一个对象,并且可以使用静态域(static变量)。比如String类的域。

程序员小刘 1927

Effective Java 读书笔记

读书笔记

white_while的博客 1648

Effective Java

Effective Java 由于书本内容太枯燥,看不下去,只能对着抄。。加油ヾ(◍°∇°◍)ノ゙ 文章目录第一章 引言第二章 创建和销毁对象第1条 用静态工厂方法代替构造器第2条 遇到多个构造器参数时要考虑构建器第3条 用私有构造器或者枚举类型强化Singleton属性第4条 通过私有构造器强化不可实例化的能力第5条 优先考虑依赖注入来引用子源第6条 避免创建不必要的对象第7条 消除过期的对象引用第8条 避免使用终结方法和清除方法第9条 try-with-resources优先于try-finally第

lyw4631的博客 471

《Effective Java》类和接口

第15条:使类和成员的可访问性最小化 参考学习:effective java(13) 之使类和成员的可访问性最小化 第16条:要在公有类而非公有域中使用访问方法 参考学习:effective java(14) 之在公有类中使用访问方法而非公有域 第17条:使可变性最小化 参考学习:effective java(15) 之使可变性最小化 第18条:复合优先于继承 参考学习:effective java(16) 之复合优先于继承 第19条:要么设计继承并提供文档说明,要么禁止继承 参考学习:effective

朱嫑膘的博客 253

《Effective Java》学习笔记15--25

本栏是博主根据如题教材进行Java进阶时所记的笔记,包括对原著的概括、理解,教材代码的报错和运行情况。十分建议看过原著遇到费解地方再来参考或与博主讨论。致敬作者Joshua Bloch和各路翻译者们,以及为我提供可参考博文的博主们。 复制粘贴改格式好累,这几篇全都给出git地址,大家自己download下来看好了。或者想直接在浏览器上看可以考虑用这个名叫OctoTree的插件。安装教程网上大把,...

欢迎访问 花落的速度 的博客 322

看完这本《Effective Java》,我悟了 —— 日更ing

文章目录创建和销毁对象篇1 静态工厂代替构造器对象通用方法篇类与接口篇泛型篇枚举和注解篇Lambda表达式与Stream篇方法篇通用编程篇异常篇并发篇序列化篇 豆瓣评分9.8的图书《Effective Java》,是当今世界顶尖高手Josh Bloch的著作,在我之前的文章里我也提到过,编程就像练武,既需要外在的武功招式(编程语言、工具、中间件等等),也需要修炼心法(设计模式、源码等等)学霸、学神OR开挂 我个人在Java领域也已经学习了近5年,在修炼“内功”的方面也通过各种途径接触到了一些编程规约,例如

如切如磋,如琢如磨 1460

Effective Java(第三版) 学习笔记 - 第四章 类和接口 Rule15~Rule19

Effective Java(第三版) 学习笔记 - 第四章 类和接口 Rule15~Rule19 本文主要介绍了类和接口相关的内容

weixin_44453385的博客 713

Effective Java 第三版读书笔记(类和接口)

第15条.使类和成员的可访问性最小化 对于成员有四种可访问级别: 1.私有的(private)----- 只有在声明该成员的顶层类内部才可以访问这个成员。 2.包级私有的(package-private)----- 声明该成员的包内部的任何类都可以访问这个成员,也是默认访问级别,接口成员除外,接口成员默认的访问级别是公有的。 3.受保护的(protected)----- 声明该成员的类...

qq_27707957的博客 340
上一篇: Effective Java笔记(17)使可变性最小化
下一篇: Effective Java笔记(19)要么设计继承并提供文档说明,要么禁止继承
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值