Effective java读书笔记(3)

【RK3588 NPU性能调优实战】多线程异步推理YOLOv5,榨干6TOPS算力 本文详细解析了如何在RK3588 NPU上通过多线程异步推理优化YOLOv5目标检测性能,实现6TOPS算力的最大化利用。通过线程池设计、流水线化帧处理及避开内存带宽瓶颈等技巧,将NPU利用率从30%提升至82%,帧率显著提高至61.2FPS。文章还提供了环境配置、代码实现及性能对比数据,助力开发者高效部署AI模型。 阅读详情

第三章节

13)使类和成员的可访问性最小化

首先,“信息隐藏(information hiding)”或“封装(encapsulation)”是软件设计的基本原则之一。
我们提出几天规则:
1. 尽可能地使每个类或者成员不被外界访问。
2. 实例域决不能是公有的

类具有公有的静态final数组与,或者返回这种域的访问方式,这几乎总是错误的
public static final Thing[] VALUES = { ... };
这是常见的安全漏洞根源。

我们推荐将这行代码改成

private static final Thing[] VALUES = { ... };
public static list<Thing> =
    Collections.unmodifiableList(Arrays.asList(VALUES));

或者是

private static final Thing[] VALUES = { ... };
public static Thing[] values() {
    return VALUES.clone();
}

总结:你应该始终尽可能地降低可访问性。

14)在公有类中使用访问方法而非公有域

//effective java例子
class Point {
    private double x;
    private double y;
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    public void setX(double x) {
        this.x = x;
    }

    public void setY(double y) {
        this.y = y;
    }
}

总而言之,不要直接访问类的数据域。

15)使可变性最小化

我们更应该去设计不可变的类,因为它更加易于设计,实现和使用。并且还不容易出错,更加安全。
为了使类成为不可变,要遵循下面五条规则:
1. 不要提供任何会修改对象状态的方法
2. 保证类不会被扩展
3. 使所有的域都是final的
4. 使所有的域都成为私有的
5. 确保对于任何可变组件的互斥访问
我们根据上面这5条规则,设计了一个类:

//com.insanus.Goods.java
package com.insanus;
public final class Goods {
    private final int id;
    private final String name;
    private final double price;
    private final int num;
    private final String firstSuppliers;
    private final String secondSuppliers;

    private Goods(GoodsBuilder i) {
        id = i.id;
        name = i.name;
        price = i.price;
        num = i.num;
        firstSuppliers = i.firstSuppliers;
        secondSuppliers = i.secondSuppliers;
    }
    private Goods(Goods i, Goods o) {
        id = i.id;
        name = i.name;
        price = i.price;
        num = i.num + o.num;
        firstSuppliers = i.firstSuppliers;
        secondSuppliers = i.secondSuppliers;
    }

    public Goods updata(Goods i) {
        if (i.id == this.id && i.name.equals(this.name))
            return new Goods(i, this);
        else
            return null;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Goods))
            return false;
        if (((Goods) obj).id == this.id && ((Goods) obj).name.equals(this.name)) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = name.length() * 31 + result;
        result = id * 31 + result;
        return result;
    }

    @Override
    public String toString() {
        return String.format("这个商品id为:%d, 名称为:%s, 价格为:%.2f, 数量为:%d, 第一供应商是:%s, 第二供应商是%s", id, name, price, num, firstSuppliers, secondSuppliers);
    }

    public static class GoodsBuilder {
        private int id = 0;
        private String name;
        private double price;
        private int num = 0;
        private String firstSuppliers = null;
        private String secondSuppliers = null;
        public GoodsBuilder(String name, double price) {
            this.name = name;
            this.price = price;
        }
        public GoodsBuilder setId(int id) {
            this.id = id;
            return this;
        }
        public GoodsBuilder setNum(int num) {
            this.num = num;
            return this;
        }
        public GoodsBuilder setFirstSuppliers(String firstSuppliers) {
            this.firstSuppliers = firstSuppliers;
            return this;
        }
        public GoodsBuilder setSecondSuppliers(String secondSuppliers) {
            this.secondSuppliers = secondSuppliers;
            return this;
        }
        public Goods valueOf() {
            return new Goods(this);
        }
    }

    public static void main(String[] args) {
        Goods i = new GoodsBuilder("哇哈哈", 998).setId(110).setNum(9).setFirstSuppliers("人民大会堂").setSecondSuppliers("中南海").valueOf();
        Goods t = new GoodsBuilder("哇哈哈", 998).setId(110).setNum(10).setFirstSuppliers("人民大会堂").setSecondSuppliers("中南海").valueOf();
        System.out.format("哈希测试, i = %d, t = %d\neqlues测试:%s\ntoString测试:\n%s\n", i.hashCode(), t.hashCode(), i.equals(t), i);
        Goods n = i.updata(t);
        System.out.println(n);
    }
}/* Output:
哈希测试, i = 3520, t = 3520
eqlues测试:true
toString测试:
这个商品id为:110, 名称为:哇哈哈, 价格为:998.00, 数量为:9, 第一供应商是:人民大会堂, 第二供应商是中南海
这个商品id为:110, 名称为:哇哈哈, 价格为:998.00, 数量为:19, 第一供应商是:人民大会堂, 第二供应商是中南海
*///:~

16)复合优先于继承

继承打破了封装性

复合在java编程思想称为组合
导致子类脆弱的一个相关的原因是:它们的超类在后续的发行版本中可以获得新的方法。
我们可以通过转发方法来转发它的结果。提高类的稳固性。

//com.insanus.SupperClass.java
package com.insanus;
public class SupperClass {
    private final FatherClass fatherClass;
    public SupperClass(FatherClass i) {
        fatherClass = i;
    }
    //转发方法
    public String getData() {
    //转发
        return fatherClass.getData();
    }
}

17)要么为继承而设计,并提供文档说明,要么就禁止继承

18)接口优于抽象类

  1. 现有的类可以很容易被更新,以实现新的接口。
  2. 接口是定义mixin(混合类型)的理想选择。
  3. 接口允许我们构造非层次结构的类型框架。

mixin演示

//com.insanus.MixinClass.java
package com.insanus;
public interface MixinClass {
    public void view();
}
class Mixin1 implements MixinClass {
    public void view() {
        System.out.println("From Mixin1");
    }
}

class Mixin2 implements MixinClass {
    private MixinClass i;
    Mixin2() {
        i = new Mixin1();
    }
    public void view() {
        System.out.println("From Mixin2");
        i.view();
    }
}

非层次结构演示

//com.insanus.Structure.java
package com.insanus;
public interface Structure extends Singer, Performer {
    //现实中有些人是演员同时也是歌手
}

interface Singer {

}

interface Performer {

}

我们可以利用abstract来编写骨架实现类,但是因为骨架实现类是为了继承的目的而设计的,所以我们应该遵守17条的知道原则。

同时,设计公有的接口要非常的谨慎。接口一旦被公开发行,并且已被广泛实现,再想改变这个接口几乎是不可能的。
尽可能谨慎地设计所有的公有接口,并通过编写多个实现对它们进行全面的测试。

19)接口只用于定义类型

有一种接口被称为常量接口。常量接口模式是对接口的不良使用。

//do not use!
public interface Test {
    static final double A = 6.666;
}

我们可以通过设置一个这样的方式

public class TestClass {
    private TestClass() { }
    public static final double A = 6.6666;
}

总结:接口应该只是被用来定义类型,它们不应该被用来导出常量。

20)类层次优于标签类

标签类

//com.insanus.Figure.java
package com.insanus;
public class Figure {
    enum Shape {
        RECTANGLE, CIRCLE
    };
    final Shape shape;
    double area() {
        swith(shape) {
            case RECTANGLE:
                //...
            case CIRCLE:
                //...
        }
    }
}

标签类过于冗长,容易出错,并且效率低下。
我们可以通过把他改成类层次。

//com.insanus.Figure.java
package com.insanus;
public abstract class Figure {
    double area();
}
class Circle extends Figure {
    double area() {
        //....
    }
}
class Rectangle extends Figure {
    double area() {
        //...
    }
}

21)用函数对象表示策略

策略接口

public interface Comparator<T> {
    public int compare(T t1, T t2);
}

具体的策略类往往使用匿名类声明

Arrays.sort(stringArrays, new Comparator<String> {
    public int compare(String s1, String s2) {
        return s1.length() - s2.lenght();
    }
});

我们还可以把函数对象储存到一个私有的静态final域中,并重用它。

22)优先使用静态成员类

嵌套类

嵌套类有四种:
1. 静态成员类
2. 非静态成员类
3. 匿名类
4. 局部类

如果声明成员类不要要求访问外围实例,就要始终把static修饰符放在它的声明中,使他变成静态成员类,而不是非静态成员类。

//com.insanus.OutClas.java
package com.insanus;
public class OutClass {
    public static class InClass {
    }
}
C++跨平台Word文档处理库DuckX实战指南:从原理到项目集成 在C++开发中,处理Office文档,尤其是Word文件,常因缺乏原生易用的库而面临挑战。Office Open XML(OOXML)作为.docx文件的基础标准,其本质是包含XML文件的ZIP压缩包。理解这一原理,开发者便能通过解析和操作XML来实现文档的读写。DuckX库正是基于此,为C++提供了轻量级的解决方案。它封装了底层的ZIP处理和XML解析,提供了简洁的面向对象API,其技术价值在于实现了跨平台、无外部依赖的Word文档自动化生成与处理。这尤其适用于服务器端、嵌入式环境或需要脱离Office软 阅读详情

相关推荐

【Unity】【模型】【AI建模】如何将AI生成的GLB格式3D模型文件导入Unity

本文介绍了一个将AI工具自动生成的GLB格式3D模型文件转换成fbx模型文件导入Unity的步骤。

O青草O的博客 Unity和游戏制作知识分享 1360

【effective java】13~22.类和接口

第13条:使类和成员的可访问性最小化Java通过封装和修饰符等手段限制访问权限,尽量降低类的可访问性,可以降低风险,应成员变量和成员方法的访问权限降低,尤其是成员变量,尽量使用private修饰,如果不是很有必要,不要使用成员变量,成员变量在并发条件下容易引发线程安全问题,为了防止出现这种问题,使用同步等方式会增加开销。第14条:在公有类中使用访问方法而非公有域尽量使用getter()/sette...

左耳听风的博客 293

OnlyOffice Docker部署踩坑实录:解决Nginx反向代理导致的editor.bin下载失败

本文详细解析了在Docker中部署OnlyOffice时,因Nginx反向代理配置不当导致editor.bin下载失败的常见问题。通过分析问题根源,提供了从Nginx代理配置、Docker网络设置到OnlyOffice容器内部调整的完整解决方案,并分享了实战调试技巧与性能优化建议,帮助用户彻底解决这一部署难题。

wine的专栏 524

java高效编程_Java高效编程之三【类和接口】

本部分包含的一些指导原则,可以帮助哦我们更好滴利用这些语言元素,以便让设计出来的类更加有用、健壮和灵活。十二、使类和成员的访问能力最小化三个关键词访问修饰符:private(私有的=类级别的)、未指定(包级私有的)、protected(受保护的=继承级别的+包级别的访问)、pulbic(共有的)备注:其中未指定,使用的是默认的访问级别,包内部的任何类都可以访问这个成员。如果类或者接口是包级私有的,...

weixin_34312149的博客 184

STM32+OpenCV云台PID调参实战:从震荡到丝滑跟踪的进阶之路

本文详细介绍了基于STM32和OpenCV的跟踪云台PID调参实战经验。从硬件搭建、PID控制原理到调参技巧,系统讲解了如何通过调整比例、积分和微分参数解决系统震荡问题,实现从震荡到丝滑跟踪的进阶过程,特别适合电赛和嵌入式视觉控制开发者参考。

tgb3456789的博客 717

用LightRAG+Ollama搭建本地知识库:从文档上传到智能问答的完整流程

本文详细介绍了如何利用LightRAG与Ollama构建企业级本地知识库,涵盖从文档预处理到智能问答的完整流程。通过实战案例展示,该方案能高效处理海量文档,实现语义搜索与知识图谱关联分析,显著提升信息检索效率。特别适合金融、医疗等领域的技术团队快速搭建智能知识管理系统。

weixin_42535461的博客 215

【第16条】接口优于抽象类

    Java语言提供了两种机制,可以用来定义一个允许多个实现的类型:接口和抽象类。如果对它们的基本定义还不是很清楚请参考其它书籍。       接口和抽象类这二者比较起来,从特征来说,最明显的区别在于抽象类允许包含某些方法的实现,但是接口是不允许的。但是在使用方面还有一个更为突出的区别,就是抽象类是通过被子类继承来使用的;而接口是通过被实现来使用的。而Java是一种单继承机制的语言,所以就...

从Java看编程 389

FPGA AXI DDR3读写时序调试与FIFO缓存实战解析

本文深入解析FPGA中AXI协议与DDR3的读写时序调试,重点探讨FIFO缓存在数据流控制中的关键作用。通过实战案例详细讲解突发传输中的地址对齐、数据分片等常见问题,并提供状态机设计、仿真波形分析和性能优化技巧,帮助开发者高效解决高速数据存储场景下的时序同步与数据一致性问题。

blockchain9miner的博客 1120

【Effective Java】第3章 读书笔记

第3章 对所有对象都通用的方法 10,重写 equals 时请遵守通用规定 10.1 在以下情况,类的每个实例都与它自身相等,不重写 equals 方法 类的每个实例都是唯一的。 类没有提供逻辑相等的测试功能。 超类已经重写了 equals 。超类的行为对于这个类也是合适的。 类是私有的,或者是包级私有的,可以确定它的 equals 方法永远不会被调用。 10.2 equals 通用约定 自反性 对称性 传递性 一致性 非空性:对于任何非null的引用值x,x.equals(null) 必须返回fal

qq_45050687的博客 1206

手把手教你学GPU的KMD专栏--3.1 设备初始化流程深度解析

本文深入解析了KMD(内核模式驱动)设备初始化流程,这是GPU驱动开发最基础且关键的环节。初始化流程包括6个核心阶段:KMD模块加载、PCIe设备探测匹配、GPU硬件初始化、显存分配映射、中断系统配置和设备注册。每个阶段都有详细步骤解析,涉及关键数据结构和错误处理机制。文章还分析了常见问题(驱动加载失败、显存分配失败、中断配置失败)的解决方案,并指出未来趋势将向动态初始化、安全增强和AI优化方向发展。正确高效的初始化流程是确保GPU被操作系统安全使用的前提,也是后续内存管理、任务调度等功能的基础。

MHD0815的博客 262

第10集:AIOps 平台架构设计!画出面试官最想看的系统全景图

本文介绍了如何将AIOps平台的六大功能模块整合为四层架构设计,并生成专业系统全景图。文章首先指出面试中架构设计能力的重要性,强调一张清晰的架构图能直观展现全局观。随后指导读者检查项目结构,准备绘图环境。核心部分详细拆解了四层架构:数据采集层(Prometheus、ELK等)、AI分析层(巡检、告警、预测等)、决策执行层(工作流引擎、自愈Agent)和展示交互层(API、控制台)。通过Python代码自动生成模块依赖关系图,并提供了面试讲解技巧。全文旨在帮助开发者在面试中系统性地展示项目架构设计能力。

qq_2937655951的博客 94

Effective Java读书笔记-3

如果这种用法是在一个循环中,或者是在一个被频繁调用的方法中,就会创建出成千上万不必要的String实例。但是这个程序中隐藏着一个问题,不严格地讲,这段程序有一个“内存泄漏”,随着垃圾回收器活动的增加,或者由于内存占用的不断增加,程序性能的降低会逐渐表现出来。" , 相反,由于小对象的构造器只做很少量的显式工作,所以小对象的创建和回收动作是非常廉价的,特别是在现代的JVM实现上更是如此。**反之,通过维护自己的对象池(object pool)来避免创建对象并不是一种好的做法,除非池中的对象是非常重量级的。

weixin_42583701的博客 156

Agentic RL: 大模型后训练 SFT、PPO和GRPO

本文介绍了从LLM训练到Agentic RL的发展过程。传统LLM训练包括预训练和后训练两个阶段,其中后训练通过监督微调、奖励建模和强化学习等技术优化模型表现。针对智能体在复杂任务中的不足,提出了Agentic RL新范式,将LLM嵌入强化学习框架,通过多步交互、工具使用和环境反馈来优化长期目标。相比传统单轮对话优化(PBRFT),Agentic RL具有状态包含历史上下文、行动类型多样、动态状态转移等特点,更适合解决需要多步推理和规划的任务。这种新方法为开发更强大的智能体系统提供了可能。

Cachel Wood的博客 700

Effective java 3th-读书笔记

第二章 创建和销毁对象 第1条、用静态工厂方法替代构造器 它只是一个返回类实例的静态方法,不同于设计模式的工厂模式。 优点:1.静态工厂方法有名称,易读、易用 一个类只能有一个带有指定签名的构造器,由于静态工厂方法有名称,所以它们不受上述限制。 public static Boolean valueOf(boolean b) { return b? Boolean.TRUE...

y_shi的专栏 348

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

《Effective Java 3rd》读书笔记——泛型

不要使用原生类型 声明中具有一个或多个类型参数的类或者接口就是泛型类或接口。泛型类和接口统称为泛型。 每一种泛型都定义一个原生(态)类型,即不带任何实际类型参数的泛型名称。例如,与List<E>相对应的原生类型是List。 private final Collection<Stamp> stamps = ...; 通过这条声明,编译器知道stamps应该只包含Stamp实...

日积月累,天道酬勤 833

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Effective Java读书笔记3

package chape8; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * 第八章 通用程序设计 * 第45条: 将局部变量的作用域减小到最小 * 将局部变量的作用域最小化。可以增强代码的可读和可维护性,并降低出错的可能性 * 要使作用...

wwwwap2008的专栏 137

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

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

《Effective Java》中文版第3版 读书笔记

人真的不必逼自己去做不像自己的那种人,强大固然是好,但脆弱和柔软也没有什么过错。一个人不用活得像一支队伍,一个人只要活得像一个人就行了,有尊严,有追求,有梦想,也有软弱和颓废的时候。 -- 知乎

山河已无恙 2685

《Effective Java 3rd》读书笔记——创建和销毁对象

用静态工厂方法代替构造器 类可以提供一个静态工厂方法(static factory method) :一个返回类的实例的静态方法。 下面是来自Boolean的简单示例: public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; } 注意这与工厂方法设计模式不同 静态工厂方法与...

日积月累,天道酬勤 667

《Effective Java》读书笔记3

rule 9:覆盖equals总是覆盖hashcode   如果不这样做,会导致该类无法和所有基本散列的结合一起正常运作。   规则:相等的对象必须具有相同的散列码   如hashcode方法设计不当,导致分桶非常不均匀,会使容器的性能急剧下降。   hashcode方法的设计目标:为不相等的对象产生不同的散列码。 转载于:https://www.cnblogs.com/ykcul/...

weixin_30905133的博客 60

《Effective Java 3rd》读书笔记——对于所有对象都通用的方法

覆盖equals方法时遵守通用约定 覆盖equals()方法看起来似乎简单,但是许多覆盖方式会导致错误,并且后果非常严重。最能避免这些问题的办法就是不覆盖equals()方法,在这种情况下,类的每个实例都只与它自己相等。如果满足了以下任意一个条件,那可以不覆盖equals()方法: 类的每个实例本质上都是唯一的 类没有必要提供逻辑相等的功能 超类已经覆盖了equals(),超类的行为对于子类也是...

日积月累,天道酬勤 602

《Effective Java 3rd》读书笔记——类和接口

使类和成员的可访问性最小化 区分一个组件设计得好不好,唯一重要的因素在于,它对于外部的其他组件而言,是否隐藏了其内部数据和其他实现细节。 尽可能地使每个类或成员不被外界访问。 对于顶层的(非嵌套的)类和接口,能做成包级私有的,就应该被做成包级私有(即不加任何修饰符)。这样就可以随心所欲的对其进行修改或删除。 如果一个包级私有的顶层类(或接口)只是在某一个类的内部被用到,那就应该考虑使它成为唯一使用...

日积月累,天道酬勤 634

Effective Java读书笔记(3)—— 类与接口

第四章:类与接口 第一条:使类和成员的可访问性最小化 一个设计良好的组件应该隐藏所有实现细节,只把必须要提供的功能通过API暴露出来,组件之间通过API进行通信。 组件与组件之间的耦合越低越好,一个组件对于其他组件,除了API通信,应该一无所知。所以每个类或成员应该尽可能的不可访问。 对于顶层的类和接口,不加任何修饰符则默认为包级私有,public修饰则为公共的,不能用其他修饰符修饰。 包级私有...

Aviato 282

【读书笔记】《Effective Java》(3)-- 类和接口

这一章的笔记时隔略久,因为开学了,有事情要做了。现在正值中秋佳节,放假了,有时间补完这篇笔记。 现在正在看下一章——泛型,发现难度更高一点,估计更新下一篇读书笔记的时间会更长。

lqadam的博客 1082

《Effective java》读书笔记3——覆盖equals方法的通用约定

满足下列四个条件之一的就不需要覆盖equals方法: (1).类的每个实例本质上都是唯一的,如枚举等。 (2).不关心类是否提供了“逻辑相等”的测试功能。 (3).超类已经覆盖了equals方法,从超类集成过来的行为对于子类也是合适的。 (4).类是私有的或者包访问权限的,可以确定它的equals方法永远不会被调用。 当类具有自己特有的“逻辑相等”概念(不同于对象等同的概念),而且超类还

Tony Chen的专栏 3223

Effective Java读书笔记(3对于所有对象都通用的方法)

3.1覆盖equals时请遵守通用约定

bear_huangzhen的专栏 1483

Effective Java 读书笔记(3)

13,最小化类和成员的可访问性。这也没什么好说的,高内聚,低耦合,暴露出去的东西越少越好。类只有两种访问级别:public和package private。成员有四种访问级别, public, private, protected, package private。以前还没学Java的时候,就在《程序员》杂志上看过一个C++的文章说protected是鸡肋,成员应该要么private要么p...

swordinhand的专栏 121
上一篇: 利用enum实现图
下一篇: Effective java读书笔记(4)
insanuscsdn
博客等级 码龄11年 1粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值