EffectiveJava-3-类和接口

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

- 封装(信息隐藏):隐藏实现细节,将它的API与内部实现隔离,降低模块间的耦合性,易于独立开发,测试,优化等,提高软件的可重用性,

- 访问控制的方式:使用访问修饰符(private,public,protected)

- 尽可能的使每个类或者成员不能被外界访问

- 不能为了方便测试,而将类,接口或者成员变成包的导出API的一部分(即不要将权限大于package-private(default))

- 包含公有可变域的类不是线程安全的,即 public &&(非final || 引用可变对象),同样也适用于静态域

例如:

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

如果类可以在它所在的包外进行访问,就提供访问方法(getter)和设值方法(setter),以保留将来改变该类内部表示法的灵活性,而且方便对其添加限制条件

使可变性最小化

不可变类:其实例不能被修改,每个实例所有信息在创建实例时提供,并且在对象的整个生命周期内固定不变,如String,基本类型的包装类,BigInteger,BigDecimal,不可变类比可变类更易于设计,实现和使用,且更加不易出错,是线程安全,可以被自由的共享,充分利用现有实例;

使类不可变的五条规则:

1. 不提供任何修改对象状态的方法

2. 保证类不会被扩展:用final修饰或将所有构造方法私有化并提供公有的静态工厂方法

3. 使所有域都是final的(实际上只要没有方法能够对域产生外部可见的改变即可,如延迟初始化,懒汉单例等,都不能让该域是final的)

4. 使所有域都是私有的

5. 确保对于任何可变组件的互斥访问:对于指向可变对象的域,必须确保客户端无法获得指向这些对象的引用,并且永远不使用客户端提供的对象引用来初始化这样的域;在构造器,访问方法,readObject方法中使用保护性拷贝技术

如果一个类的安全性依赖于参数(来源于客户端)的不可变性,就必须进行检查,确保是真正的不可变类,而不是不可信任的子类实例,如果是后者,就必须进行保护性拷贝,例如:

除非有需要,不要为getter方法编写对应的setter方法,以保证类的不可变,getter方法可以返回保护性拷贝对象;

只有当确认有必要实现令人满意的性能时,才应该为不可变类提供公有的可变配套类,如String的可变配套类StringBuilder和StringBuffer;

构造器/静态工厂方法应该创建完全初始化的对象,并建立起所有的约束关系,不要再提供额外的公有初始化方法,或重新初始化方法;

复合优先于继承

继承是实现代码重用的有力手段,但并非永远是最佳方案(跨包边界的继承,可能处于不同程序员的控制下,是非常危险的,父类随着发行版本的不同可能发生变化,子类就有可能遭到破坏),例如下面代码中所提到的问题:

只有当A,B两个类之间存在"B is A"关系,且A类本身不存在缺陷时,才应该使用继承;

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

- 该类必须有文档说明它可覆盖方法的自用性,方法或构造器中调用了哪些可覆盖方法,每个调用如何影响后续处理过程

- 好的API文档应该描述一个给定方法做了什么工作,而不是描述它是如何做到的

- 可以使用受保护(protected)的方法或域,提供钩子(hook),以便子类能够获取更多的权限/功能

- 对于为了继承而设计的类,唯一的测试方法就是编写子类,以此查找遗漏,和判断是否应该私有,一般编写3个子类测试即可

- 构造器决不能调用可被覆盖的方法,无论直接或是间接(因为超类的构造方法先于子类构造方法执行,而可被覆盖的方法可能在子类重写时依赖子类构造方法初始化的数据,这时会导致执行该方法出现问题)(可将可覆盖方法代码体移到一个私有辅助方法中,可覆盖方法和构造器都调用这个私有辅助方法)

- 为继承而设计的类,最好不要实现Cloneable或Serializable接口,如果实现,请不要在clone或readObject方法中调用可覆盖的方法,原因同上

- 对于普通的具体类,若非为了安全的进行子类化而设计,要禁止其子类化(或者完全消除这个类中可覆盖方法的自用性,以确保安全的进行子类化)

接口优于抽象类

- 二者区别:

1. 抽象类允许包含某些方法的实现,接口则不允许

2. (重要)为了实现由抽象类定义的类型,类必须成为抽象类的一个子类,而java只允许单继承,使得抽象类作为类型定义收到类极大的限制

3. 抽象类的演变比接口容易的多,在后续发行中可以在抽象类中增加新的具体方法,并包含合理的默认实现,则该抽象类的所有实现都将具有这个新的方法,而接口则不行

- 现有类可以很容易被更新,以实现新的接口;而抽象类则需要放到类型层次的最高处,无论后续的其他子孙类是否需要

- 接口是定义mixin(混合类型)的理想选择,方便实现某些可供选择的行为

- 接口允许我们构造非层次结构的类型框架,如一个coder接口和一个gamer接口,然而一个人可能即是程序员又是游戏玩家

- 可以通过对重要接口提供一个抽象的骨架实现类,把接口和抽象类的优点结合起来,如常见的集合类中List接口和AbstractList抽象类等等(骨架实现类为例继承的目的而设计,有助于接口的实现,而又不是必须的)

- 接口一旦公开发行,并被广泛实现,再想改变这个接口几乎是不可能的,因此必须在设计之初就保证接口的正确性

接口只用于定义类型

- 当类实现接口时,接口就充当可以引用这个类的实例的类型,任何为了其他目的而定义的接口是不恰当的;

- 有一种常量接口,只包含静态final域,没有任何方法,需要这些常量的类实现这个接口,以避免用类名来修饰常量,这是对接口的不良使用:

1.常量接口暴露了类的实现细节;

2.后续子类的命名空间会被接口中的常量污染

- 常量接口的替代方案:

1.添加到类或接口中;

2.使用枚举类型导出常量;

3.使用不可实例化的工具类

类层次优先于标签类

- 标签类:可以有多种风格的实例的类,并包含表示实例风格的标签域

- 这种标签类中充斥着样板代码,包含枚举或静态域标签,以及条件语句,破坏可读性和单一职责原则,过于冗长,容易出错,效率底下,占用内存增加;

- 如一个形状类通过一个type字段来判断要创建出的实例是矩形,圆,还是三角形;最好是创建一个形状抽象类,再分别实现代表矩形,圆,三角形的不同子类;

用函数对象表示策略 (策略模式)

函数对象:如果一个类仅仅执行这样一个方法,此方法执行其他对象(这些对象被显示对传递给这些方法)上的操作,它的实例实际上等同于一个指向该方法的指针,这样的实例成为函数对象,如下:

优先考虑静态成员类

- 嵌套类:指被定义在另一个类的内部的类,嵌套类存在的目的应该只是为它的外围类提供服务;

如果嵌套类将来可能用于其他某个环境,它就应该是顶层类;

- 嵌套类分为:静态成员类,非静态成员类,匿名类,和局部类,后三种都称为内部类

- 静态成员类是最简单的嵌套类,把它看作普通类即可,常见的用法:

1. 公有静态成员类:作为公有的辅助类,仅当与它的外部类一起使用才有意义

2. 私有静态成员类:用来代表外围类所代表对象的部分组件,如汽车的轮子,Map中的Entry代表一组键值对

- 静态成员类(独立)与非静态成员类(依赖)的唯一区别是:内部类实例是否依赖外围类的实例

- 匿名类:只需要在一个地方创建实例时使用,使用时被声明和实例化,可以出现在任何允许存在表达式的地方,应尽量简短(10行左右)以维持可读性,常见用法:

1. 动态的创建函数对象,如Comparator比较器;

2. 创建过程对象,如进行接口回调,Runnable,Thread等;

3. 用在静态工厂方法内部返回匿名内部类创建的实例;

- 局部类:用的最少,在任何可以声明局部变量的地方

我是今阳,如果想要进阶和了解更多的干货,欢迎关注公众号”今阳说“接收我的最新文章

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Effective Java第三版》是由Joshua Bloch所著的一本Java编程指南。这本书是基于第二版的更新版本,目的是给Java程序员提供一些最佳实践和经验,以编写高效、可维护和可靠的Java代码。 这本书共分为15个章节,每个章节都讲解了一个与Java开发有关的重要主题。比如,章节一讲述了使用静态工厂方法代替构造器的优点,章节二则介绍了如何用Builder模式来构建复杂的对象。此外,书中还提及了Java对象的等价性、覆盖equals方法和hashCode方法、避免创建不必要的对象、使用泛型、枚举、lambda表达式等等。 《Effective Java第三版》通过具体的代码示例和清晰的解释来说明每个主题的关键概念,使读者能够更好地理解和应用。此外,书中还提供了一些实用的技巧和技术,例如避免使用原始型、尽量使用接口而非来定义型等。 总的来说,这本书提供了很多实用的建议和技巧,可以帮助Java开发者写出高质量的代码。无论是初学者还是有经验的开发者,都可以从中受益匪浅。无论你是打算从头开始学习Java编程,还是已经有一定经验的开发者,这本书都是值得推荐的读物。 ### 回答2: 《Effective Java 第三版》是由Joshua Bloch 所著的一本Java编程指南,是Java程序员必读的经典之作。该书共包含90个条目,涵盖了各种Java编程的最佳实践和常见问题的解决方法。 本书分为多个部分,每个部分都侧重于一个特定的主题。作者探讨了Java编程中的各种问题和挑战,并提供了解决方案和建议。这些建议包括如何选择和使用合适的数据结构和算法,如何设计高效的接口,如何处理异常和错误,以及如何编写可读性强的代码等等。 《Effective Java 第三版》还关注了Java编程中的性能优化和安全性问题。作者强调了遵循Java语言规范、使用标准库、防范常见安全漏洞等重要原则。此外,本书还介绍了Java 8及其后续版本的新特性和用法,如Lambda表达式、流式编程和Optional等。 这本书的特点之一是每个条目都独立于其他条目,可以单独阅读和理解。每个条目开头都有一个简洁的总结,让读者能够快速掌握主要观点。此外,书中还有大量的示例代码和解释,帮助读者更好地理解和运用所学知识。 总的来说,《Effective Java 第三版》是一本非常实用和全面的Java编程指南。它适用于各个层次的Java程序员,无论是初学者还是有经验的开发人员,都可以从中获得宝贵的经验和知识。无论是编写高质量的代码、优化性能还是确保安全性,这本书都是一本不可或缺的参考书籍。 ### 回答3: 《Effective Java 第3版(中文版)》是由 Joshua Bloch 所著的一本关于使用 Java 编程语言的指南书。该书是对 Java 语言的最佳实践的详尽描述,为中高级 Java 开发人员提供了许多实用的建议和技巧。 该书的主要内容包括Java 语言的优雅编程风格、接口的设计、Lambda 表达式和流的使用、泛型、异常和并发编程等方面的最佳实践。 在《Effective Java 第3版(中文版)》中,许多传统的 Java 开发中的陷阱、常见错误和不良习惯都得到了深入的剖析和解答。它不仅提供了可供开发人员参考的示例代码,还解释了为什么某种方式是有问题的,以及如何更好地进行改进。 该书的深度和广度非常适合正在努力提高 Java 编程技能的开发人员。它涵盖了多个关键领域,为读者提供了在实际项目中解决常见问题的方法和思路。 此外,《Effective Java 第3版(中文版)》还介绍了最新版本的一些特性和改进。例如,它详细说明了如何正确地使用 Java 8 中新增的 Lambda 表达式和流,以及如何充分利用 Java 9、10 和 11 中的新功能。 总之,这本书是 Java 开发人员必备的指南之一。通过深入理解和应用书中的实践建议,读者可以更加高效地编写、优化和维护 Java 代码。无论是想提升职业技能还是在项目中减少错误和问题,这本《Effective Java 第3版(中文版)》都是一本非常有帮助的参考书。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值