《Effective Java》(17~22)阅读笔记

来源:互联网 发布:淘宝电子发票如何下载 编辑:程序博客网 时间:2024/06/09 15:02

接着上期继续看本书高质量编码建议12~16条的阅读笔记

17.要么为继承而设计,并提供文档说明,要么禁止使用继承不要过度设计。

  面向对象编程,从一开始被洗脑难免在上手写代码时都会首先思考有没有公共方法啊,能不能把两个类抽象成一个父类再继承啊等,慎重使用继承,当要使用继承时一定要在文档注释中写明重写这个方法会给其他方法带来什么影响。书中给出建议如果类并不是为了继承而生,那么这个类应该用final修饰禁止子类化。

18.接口优先于抽象类

接口和抽象类的异同这是Java基础中的基础。我们不妨来回顾下接口和抽象类的区别:

  接口不能被实例化不能有构造器,抽象类也不能被实例化但可以有构造器;

  接口中不能有实现方法(JDK8在接口中可以有实现方法,称“默认方法”),抽象类中可以有实现方法,也可以没有;

  接口方法的默认修饰符就是public,不可以用其他修饰符,抽象类可以有public、protected、default。

  回到“接口优于抽象类”的问题上来,原因就是Java只支持单继承,但可以实现多个接口。有抽象类的地方基本上都可以看到其中的方法很多是模板方法

19.接口只用于定义类型

这个条目中建议接口不要只用于定义常量使之成为常量接口,如果一个类只有常量应该使用枚举类型或者不可实例化的工具类。JDK中的反例就是java.io.ObjectStreamConstant。

20.类层次优先于标签类

        标签类是指在类中定义了一个变量,使用该变量的值来控制该做什么动作。

  书中举例:定义一个Figure类,使用Shapre变量,可以传入“长方形”或者“圆形”,根据传入的类型不同调用共同的方法。这个就是一个标签类,如果新增一个“三角形”的话,就得修改这个标签类的代码。

  更好的方法就是利用继承,合理利用继承能更好的体现面向对象的多态性。

21.用函数对象表示策略

什么是函数对象?实际上这是在JDK8之前没有Java不支持lamda表达式,方法参数不能传递一个方法只能通过传递对象的方式“曲线救国”,例如Arrays.sort(T[] a, Comparator<? super T> c)方法,第一个参数传递数组,根据传入第二个自定义的比较类中的比较方法进行排序。如果能传入函数指针、Lambda表达式等,那就自然不用传递一个类。

  从JDK8开始Java已经支持了lambda表达式,不妨简单了解下JDK8的lambda表达式。

  广义上来讲JDK8中lambda表达式有两个部分组成:一是lambda表达式本身,二是函数式接口。函数式接口实际上就是指只包含一个抽象方法的接口,比如Runnable接口只包含run抽象方法。而lambda表达式本身实际上则是对抽象方法的实现。

22.优先使用静态成员类

一般情况下我们可能提到最多的是“内部类”这个名词,实际上在类“内部”的类叫做“嵌套类”。嵌套类分为四种:静态成员类、非静态成员类、匿名类和局部类。除了静态成员类,其余三种才被称之为内部类。

静态成员类相比较于非静态成员类就是多了一个static关键字修饰类,另外一个更重要的区别在于非静态成员类的每个实例都包含一个额外的指向外围对象的引用,保存这份引用要耗费时间和空间。

  举个例子,在JDK7中,HashMap内部使用Entry类表示每个键-值对,这个类是static静态的,如果将static去掉仍然可以工作,但每个entry中将会包含一个指向该Map的引用,这样就浪费了空间和时间。

  那么什么时候使用静态什么时候使用非静态呢?

  书中给出了比较明确的原则:如果声明成员类不要求访问外围实例,就要始终把static修饰符放在它的声明中。也就是说如果成员类和外围实例类有交互,那这个类就应该是非静态的,如果没有交互而是作为外围类的一个组件存在在应使用静态的。

  最后一个是局部类,只要是在任何“可以声明局部变量的地方”,都可以声明局部类,用得最少,如果要使用那也必须非常简短。






原创粉丝点击