这种设计不是优秀的设计方式。若是属性直接暴露出去,若是须要修改返回值,那基本是不可能的,由于调用方散布在不少地方。若是是提供的访问方法,咱们只须要改方法自己便可。java
不可变对象的优势:
不可变对象是线程安全的。
不可变对象能够被自由地共享。
不可变对象也能够共享内部属性。
不可变对象能够被重复使用。
不可变对象提供了免费的原子失败机制。正则表达式
在 Java 中,经过 接口 和 抽象类 来容许多个实现。在 Java 8 中也引入了接口的默认方法实现,因此这两种机制都容许为某些实例方法提供实现。因为 Java 中只容许单一继承,经常使用的方式是接口定义了类型,可能提供了一些默认的方法,抽象类去实现多个接口并实现通用接口方法,具体的实现类去继承抽象类并实现抽象类中的抽象方法。数组
继承是实现代码重用的有效方式,但并不老是最好的工具。与方法调用不一样,继承打破了封装,一个子类依赖于其父类的实现细节来保证其正确的功能。若是父类发生了变化,即便子类并无作任何的改动也会致使子类被破坏。安全
不要继承一个现有的类,而应该给你的新类增长一个私有属性,该属性是现有类的实例引用,这种设计被称为组合。如今不依赖于现有类的实现细节,即便将新的方法添加到现有的类中,也不会对新类产生影响。微信
继承是强大的,也能够最大化代码重用,只有在子类和父类之间存在真正的子类型关系时才适用。 若是子类与父类不在同一个包中,而且父类不是为继承而设计的,那就可使用组合来代替继承。ide
接口不包含任何方法,它只包含静态 final 属性,每一个输出一个常量,这样的接口叫常量接口,这是对接口的糟糕使用方式。函数
若是常量跟类的关系密切,那么咱们能够把常量定义在类中。假如是公共的常量,咱们应该用枚举类型来定义它们。工具
接口只能用于定义类型,它们不该该仅用于定义常量。学习
一个集合对象中数据类型应该是一致的,若是不规定数据的具体类型,在编译期是没有任何问题的。但到程序运行时,若是类型不一致,就与可能抛出 ClassCastException 异常。所以,咱们须要使用泛型强制约束数据的类型,让问题暴露在编译期,而不是在运行期。线程
咱们用泛型强制规定了参数的类型,所以它很是的不灵活,使用场景很是少。相对于提供的不可变的类型,有时须要比此更多的灵活性咱们就须要使用通配符类型。
因此将类型从 List 更改成 List<? extends T>。在 API 中使用通配符类型,虽然棘手,但使得 API 更加灵活。 若是编写一个将被普遍使用的类库,请使用通配符类型来最大化该 API 的灵活性。
由于可变参数和泛型不能很友好的限制,泛型可变参数不是类型安全的,但它们是合法的。若是选择使用泛型可变参数编写方法,请首先确保该方法类型一致,而后使用 @SafeVarargs 注解对其进行标注,以避免形成使用不愉快。
一个类用 枚举声明,标签属性和 switch 语句来判断类型,会使代码可读性更差,容易出错的,并且效率低下。所以,带标签的类很应少最好别用。当遇到一个带有标签属性的现有类时,能够考虑将其重构为一个类层次中。
未经检查的警告是重要的,不要忽视他们。由于每一个未经检查的警告表明在运行时出现 ClassCastException 异常的可能性,尽可能消除这些警告。若是没法消除未经检查的警告,而且能够证实引起该警告的代码是安全类型的,则能够在尽量小的范围内使用 @SuppressWarnings(“unchecked”) 注解来禁止警告。 并注释为何是安全的。
数组和泛型具备很是不一样的类型规则。 数组是协变和具体化的, 泛型是不变和类型擦除的。
所以,数组能保证运行时类型的安全性,但不保证编译时类型的安全性,反之亦然。
通常来讲,数组和泛型不能很好地混合工做。若是你发现把它们混合在一块儿,获得编译时错误或者警告,首先应该使用列表来替换数组。
枚举的优势:
提供了编译时类型的安全性,可使用 == 运算符来比较不一样枚举类型的值。
具备相同名称常量的枚举类型能够和平共存,由于每种类型都有其本身的名称空间。
还容许添加任意方法和属性并实现任意接口,功能更强大。
枚举更具可读性,更安全,更强大。
此注解只能在方法声明上使用,它代表带此注解的方法声明重写了父类的声明。若是始终使用这个注解,它将避免产生大量的恶意 bug。
若是在每一个方法声明中使用 Override 注解,而且认为要重写父类声明,那么编译器能够保护免受不少错误的影响。
java.util.function 包提供了大量标准函数式接口供你使用。 若是其中一个标准函数式接口完成这项工做,则一般应该优先使用它,而不是专门构建的函数式接口。 这将使你的 API 更容易学习,经过减小其没必要要概念,并将提供重要的互操做性好处,由于许多标准函数式接口提供了有用的默认方法。
不要提供具备多个重载的方法,这些重载在相同的参数位置上使用不一样的函数式接口,若是这样作可能会在调用方中产生歧义。
在 Java 8 中添加了 Stream API,以简化顺序或并行执行批量操做的任务。
流 (Stream),表示有限或无限的数据元素序列。
流管道 (stream pipeline),表示对这些元素的多级计算。
Stream 中的元素能够来自任何地方。常见的源包括集合,数组,文件,正则表达式模式匹配器,伪随机数生成器和其余流。
流能够很容易地作一些事情:
统一转换元素序列。
过滤元素序列。
使用单个操做组合元素序列。
将元素序列累积到一个集合中,可能经过一些公共属性将它们分组。
在元素序列中搜索知足某些条件的元素。
遍历元素序列。
Stream 类提供了不少好用又简单的方法,能够多加使用。
PS:
清山绿水始于尘,博学多识贵于勤。
我有酒,你有故事吗?
微信公众号:「清尘闲聊」。
欢迎一块儿谈天说地,聊代码。