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


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

第14条:在公有类中使用访问方法而非公有域
尽量使用getter()/setter()方法来获取和设置成员变量的值,而不要使成员变量声明为public!

第15条:使非可变性最小化
坚决不要为每个get方法编写一个相应的set方法。除非有很好的理由也要让类成为可变的类,否则就应该是不可变的。
对于有些类而言,其不可变性是不切实际的。如果类不能被做成是不可变的,仍然应该是尽可能地限制它的可变性。降低对象可以存在的状态数,可以更容易地分析该对象的行为,同时降低出错的可能性。因此,除非有令人信服的理由要使域变成是非final的,否则要使每个域都是final的。

第16条:复合优先于继承
继承的功能非常强大,但是也存在诸多问题,因为它违反了封装原则。只有当子类和超类之间确实存在子类型的关系时,使用继承才是恰当的。即使如此,如果子类和超类处在不同的包中,并且超类并不是为了继承而设计的,那么继承将会导致脆弱性。为了避免这种情况,可以使用复合和转发机制来代替继承,尤其是当存在适当的接口可以实现包装类的时候。包装类不仅比子类更加健壮,而且功能也更强大。

第17条:要么为继承而设计,并提供文档说明,要么就禁止继承
对于专门为了继承而设计并且具有良好文档说明的类而言,该类的文档必须精确地描述覆盖每个方法所带来的影响。该类必须有文档说明它可覆盖的方法的自用性。对于每个公有的或受保护的方法或者构造器,它的文档必须指明该方法或者构造器调用了哪些可覆盖的方法,是以什么顺序调用的,每个调用的结果又是如何影响后续的处理过程的。更一般的,类必须在文档中说明,在哪些情况下它会调用可覆盖的方法。

第18条:接口优于抽象类
(1)现有的类可以很容易的被更新,以实现新的接口。
如果你前期编写了一个类A,后期有在系统中加入了一个新的接口B,当你想让前期编写的类来实现这个接口,你只用加上一句implement B,然后在类A中实现里面的方法即可,不会影响到以前的类对类A的使用。
(2)接口是定义mixin(混合类型)的理想选择。
一个类可以实现多个接口。一个类除了可以实现一个它的主要类型接口之外,还可以加入一些辅助接口来实现一些新的功能。
(3)接口可以多继承。

(4)骨架类概念 (有代码)

第19条:接口只用于定义类型
接口应该只被用来定义类型,他不应该被用来导出常量。(如java.io.ObjectStreamConstants。这些接口应该被认为是反面的典型,不值得被效仿。)
类实现了接口,就表明客户端对这个类的实例可以实施某些动作。为了任何其他目的而定义的接口是不恰当的。

第20条:类层次优于标签类
标签类很少有适用的时候。当你想要编写一个包含显示的标签域的类时,应该考虑一下,这个标签是否可以被取消,这个类是否可以用类层次来代替,当你遇到一个包含标签域的现有类时,就要考虑将它重构到一个层次结构中去。 (有事例代码)

第21条:用函数对象表示策略
函数指针的主要用途就是实现策略模式。为了在java中实现这种模式,要声明一个接口来表示该策略,并且为每一个策略声明一个实现了该接口的类。当一个具体策略只被使用一次时,通常使用匿名类来声明和实例化这个具体策略类。当一个具体策略类时设计用来重复使用的时候,它的类通常就要被实现为私有的静态成员类,并通过公有的静态final域被导出,其类型为该策略接口。 (有事例代码,含C++,通过C++与Java的对比可以更加深入理解)

第22条:优先考虑静态成员类
内部类是为外部类服务的,当一个功能作为一个组件为类提供服务,并且这段功能逻辑很复杂,不适合放在方法里面的时候,可以考虑体现为静态内部类,如果不涉及到效率问题,并且每个内部类的实例都需要一个指向外部类的引用的话,可以考虑将其声明为非静态内部类,匿名内部类多用于代码简写,比如线程的创建。 (有事例代码)

(1)静态成员类(在类内部的类)

1public class MyClass{
2  public static class MyMember{
3     \\...
4  }
5}

(2)成员类(静态与非静态的区别在于static)

1public class MyClass{
2  public class MyMember{
3     \\...
4  }
5}

(3)局部类(在方法内的类)

1public class MyClass {
2    public void myMethod(){
3        //...
4        class Memeber{
5            //...
6        }
7    }
8}

(4)匿名类(在调用方法内的类)

1mBtn.setOnClickListener{
2    new OnClickListener(){
3        @Override
4        public void onClick(){
5            //...
6        }
7    }
8}


事例代码

猜你喜欢

转载自blog.csdn.net/charjay_lin/article/details/81033892
今日推荐