《Effective Java》阅读笔记-第四章

发布时间 2023-11-29 16:32:14作者: LuckyNeko

Effective Java 阅读笔记

第四章 类和接口

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

软件设计的基本原则之一:封装

第 16 条 使用 Getter/Setter 代替 public 字段

这书的翻译可真垃圾

第 17 条 使可变性最小化

标准库中有许多不可变类:String、基础类型的封装类、BigInteger、BigDecimal等,不可变类更容易设计、实现、使用,不容易出错并且更加安全。

设计不可变类时应遵循下面几条规则

  • 不提供可修改对象状态的方法
  • 保证类不会被扩展
  • 声明字段为 final
  • 声明字段为私有
  • 确保可变组件的访问为互斥(即防止外部获取到内部可变对象的引用)

第 18 条 组合优先于继承

简而言之,继承打破了封装性,并且只能单继承,一些新的语言甚至直接舍弃了继承(例如 Golang)。

可以使用组合&转发来代替继承。

第 19 条 要么设计继承并提供说明文档,要么禁止继承

个人感觉因噎废食了,见仁见智吧。

第 20 条 接口优于抽象类

因为只能单继承,但是可以实现多个接口,明显接口的灵活性是要大于抽象类的。
并且接口中已经可以提供默认实现,比抽象类更加方便。

  • 现有类可以很容易被更新,以实现新接口
  • 接口是定义 mixin(混合类型)的理想选择
  • 接口允许构造非层次接口的类型

第 21 条 为后代设计接口

Java 8 之前,接口不能添加默认实现,如果给一个接口添加了一个方法,那么所有实现这个接口的类都要去实现这个新方法。
Java 8 中,接口添加了默认实现,可以给现有接口添加新方法,但是这也是有一定风险的。

第 22 条 接口只用于定义类型

不要使用接口去定义常量,否则在添加了新的常量之后,实现了该接口的方法会出现不可预测的错误。

第 23 条 类层次优先于标签类

也就是使用类结构去实现,而不是使用注释去标记某个字段是什么类型下用的。

第 24 条 静态嵌套类优先于非静态嵌套类

嵌套类,是定义在类里面的类。

嵌套类分为以下四种:

  1. 静态嵌套类(Static Nested Class)

静态嵌套类是声明为静态的内部类。它与外部类关联,但没有隐含对外部类实例的引用。可以通过外部类的名称直接访问静态嵌套类。

public class OuterClass {
    static class StaticNestedClass {
        // 静态嵌套类的成员
    }
}
  1. 非静态嵌套类(Nonstatic Nested Class)又称成员内部类(Member Inner Class)

与静态嵌套类不同的是它不使用 static 修饰,它有一个隐含的对外部类实例的引用,可以访问外部类的成员。

public class OuterClass {
    class InnerClass {
        // 非静态嵌套类的成员
    }
}
  1. 局部类(Local Inner Class),同样也是内部类

声明在方法内部的内部类。局部内部类只能在声明它的方法中使用。

public class OuterClass {
    void someMethod() {
        class LocalInnerClass {
            // 局部内部类的成员
        }
    }
}
  1. 匿名内部类(Anonymous Inner Class),也是内部类

匿名内部类是一种没有命名的局部内部类,通常用于实现接口或继承一个类的匿名对象。

public class OuterClass {
    // 只是这种写法,定义在哪里都可以
    InterfaceName obj = new InterfaceName() {
        // 匿名内部类的成员
    };
}

如果内部类不需要引用外部实例,那么就把它声明为静态嵌套类。

第 25 条 限制源文件为单个顶级类

Java 允许在单个源文件中定义多个顶级类(或接口),但是这么做并没有什么好处,只会带来巨大风险。