Android技术知识Android开发经验谈Android开发

Android基础进阶之EffectJava翻译系列(第三章:类

2019-01-09  本文已影响5人  青楼爱小生

3. 类和接口

类和接口是Java编程的核心

Item13 最小化类和成员变量的访问权限

信息隐藏与封装是程序设计的基本原则
通用经验是能让类或者变量不可访问就让它不可访问
四种访问权限:

公共类不应包含公共字段。确保static final引用的对象是不可变的。
绝不可以用private static final来声明一个数组对象

Item14 用公共方法提供公共字段
//bad
public class Point {
  public int x;
  public int y;
}

//good
class Point {
    private double x;
    private double y;
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
    public double getX() { return x; }
    public double getY() { return y; }
    public void setX(double x) { this.x = x; }
    public void setY(double y) { this.y = y; }
}
Item15 最小化可变性

对象始终不变的类比可变的更安全和好用,如String
我们设计不可变对象时应遵循如下准则:

Item16 组合和继承,优先使用组合

继承虽然有很多好处,但是违背了封装性,暴露了父类的实现细节

Item17 专用于继承的设计,否则禁止继承

未能理解,后续补充

Item18 接口和抽象类之间倾向于接口

Java提供了两种机制来提供多个类型定义的实现:接口和抽象类

最明显的区别在于抽象类允许某些方法的实现,更重要的区别在于一个类使用了抽象类的方式来定义,则这个类必须是抽象类的子类.因为Java只允许单一继承,因此对抽象类的这种限制严重影响了它们作为类型定义的使用

有一个特例是抽象类比接口更加易用,如果注重程序的易用性而不是灵活性则可以考虑抽象类

Item19 仅使用接口定义类型

当一个类实现了一个接口,这个接口是为类的实例服务的而不是为了其他目的

所以有一种常量接口尽量不要使用

//bad
public interface PhysicalConstants {
    // Avogadro's number (1/mol)
    static final double AVOGADROS_NUMBER = 6.02214199e23;
    // Boltzmann constant (J/K)
    static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    // Mass of the electron (kg)
    static final double ELECTRON_MASS = 9.10938188e-31;
}

如果有这种常量需要使用,可以把它定义在与之关联的类里面

Item20 用继承来替代复合类(原单词: tagged classes)

偶尔会遇到一个类的实例包含了多种不同的类别,如下

// bad Tagged class - vastly inferior to a class hierarchy!
class Figure {
    enum Shape { RECTANGLE, CIRCLE };
    // Tag field - the shape of this figure
    final Shape shape;
    // These fields are used only if shape is RECTANGLE
    double length;
    double width;
    // This field is used only if shape is CIRCLE
    double radius;
    // Constructor for circle
    Figure(double radius) {
        shape = Shape.CIRCLE;
        this.radius = radius;
    }
    // Constructor for rectangle
    Figure(double length, double width) {
        shape = Shape.RECTANGLE;
        this.length = length;
        this.width = width;
    }
    double area() {
        switch(shape) {
        case RECTANGLE:
            return length * width;
        case CIRCLE:
            return Math.PI * (radius * radius);
        default:
            throw new AssertionError();
        }
    }
}  

优化如下

//Class hierarchy replacement for a tagged class
abstract class Figure {
    abstract double area();
}
class Circle extends Figure {
    final double radius;
    Circle(double radius) { this.radius = radius; }
    double area() { return Math.PI * (radius * radius); }
}

class Rectangle extends Figure {
    final double length;
    final double width;
    Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }
    double area() { return length * width; }
} 
Item21 使用函数对象表示策略

直译过来有点不好理解,大意是对于多个类都要使用的策略(或用方法表示),采用接口来实现

如一个类需要比较方法,另一个类也需要,则抽象出一个Comparable接口来给各个类通用

Item22 嵌套类的使用

有四种嵌套类,分别是静态成员类、非静态成员类、匿名内部类和本地类
除了第一个都是内部类

public class MySet<E> extends AbstractSet<E> {
    public Iterator<E> iterator() {
        return new MyIterator();
    }
    //典型用法
    private class MyIterator implements Iterator<E> {
    ...
    }
}

如果成员类需要外部类的引用,则使用非静态成员类,否则使用静态成员类


上一篇 下一篇

猜你喜欢

热点阅读