美文网首页Effective Java
第19条 接口只用于定义类型

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

作者: 真爱也枉然 | 来源:发表于2017-05-22 17:55 被阅读0次

当类实现接口时,接口就充当可以引用这个类的实例的类型。因此,类实现了接口,就表明客户端对这个类的实例可以实施某些动作。为了任何其他目的而定义的接口是不恰当的。

      有一种接口被称为常量接口(constant interface),这种接口没有包含任何方法,它只包含静态的final域,每个域都导出一个常量。下面是一个例子

public interface PhysicalConstants {
   static final double AVOGADROS_NUMBER  = 6.23156412e23; //阿伏伽德罗数
   static final double BOLTZMANN_CONSTANT  = 1.12588456e-23; //玻尔兹曼常数
   static final double ELECTRON_MASS = 9.10938188e-31; //电子质量
}

      常量接口模式是对接口的不良使用。类在内部使用某些常量,纯粹是实现细节,实现常量接口,会导致把这样的实现细节泄露到该类的导出API中,因为接口中所有的域及方法都是public的。类实现常量接口,代表了一种承诺:如果在将来的发行版本中,这个类被修改了,它不再需要使用这些常量了,依然必须实现这个接口,以确保二进制兼容性。如果非final类实现了常量接口,它的所有子类的命名空间都受到了污染。

那既然不适合存在全部都是导出常量的常量接口,那么如果需要导出常量,它们应该放在哪里呢?

1.如果这些常量与某些现有的类或者接口紧密相关,就应该把这些常量添加到这个类或者接口中(如Integer和Double),注意,这里说添加到接口中并不是指的常量接口。在Java平台类库中所有的数值包装类都导出MIN_VALUE和MAX_VALUE常量。如果这些常量最好被看作是枚举类型成员,那就应该用枚举类型来导出。

如:int类型的取值范围是多少?

这就应该去查 Integer -- Integer.MAX_VALUE;

public enum PhysicalConstants {
       AVOGADROS_NUMBER(6.23156412e23),BOLTZMANN_CONSTANT(1.12588456e-23),ELECTRON_MASS(9.10938188e-31);
       private final Double constant;
       PhysicalConstants(Double number) {
             thie.constant = number;
       }
       public Double constant() {
             return constant;
       }
}

2.应该使用不可实例化的工具类来导出这些常量。

public class PhysicalConstants {
   private PhysicalConstants() {}
   public static final double AVOGADROS_NUMBER = 6.23156412e23;
   public static final double BOLTZMANN_CONSTANT = 1.12588456e-23;
   ...
}

工具类通常要求客户端要用类名来修饰这些常量名。例如PhysicalConstants.AVOGADROS_NUMBER。如果大量利用工具类导出的常量,那么可以通过静态导入(static import)机制来避免用类名来修饰常量名。静态导入的作用是把PhysicalConstants类中的AVOGADROS_NUMBER 、BOLTZMANN_CONSTANT 等常量引入到本类中,这会使程序更简单,更容易阅读,只要看到AVOGADROS_NUMBER就知道这是阿伏伽德罗常数,不用每次都要把类名写全了。但是,滥用静态导入会使程序更难阅读,更难维护。

// Use of static import to avoid qualifying constants  
import static effectivejava.PhysicalConstants.*;  
 
public class Test {  
   double atoms(double mols) {  
       return AVOGADROS_NUMBER * mols;  
   }  
   ...  
   // Many more uses of PhysicalConstants justify static import  
}

PS:在Java程序中,是不允许定义独立的函数和常量(准确的说,只是被final修饰、只能赋值一次的变量)的。即使从它们本身的功能来看,完全不需要依附于什么东西,也要找个类或接口作为挂靠单位才行(在类里可以挂靠各种成员,而接口里则只能挂靠常量)。

       挂靠的方法,是把它们加上static修饰符,定义为这个类或接口的静态成员。这方面的典型例子是java.lang.Math类——包含了大量的sin、cos这样的“函数”和PI、E这样的“常量”。

       传统上,在访问这些挂靠了的函数、变量和常量的时候,需要在前面加上它们挂靠单位的名称。如果只是偶尔访问这些东西一下,这样的写法可以工作得很好;但是如果要频繁访问这些成员的话,这样的写法就显得比较罗嗦了。

简而言之,接口应该只用来定义类型,它不应该被用来导出常量。

相关文章

  • 接口只用于定义类型

    当类实现接口时,接口就充当可以引用这个类的实例的类型。因此,类实现了接口,就表明可以对这个类的实例实施某些动作。那...

  • 第19条-接口只用于定义类型

    当类实现接口时,接口就充当可以引用这个类的实例的类型(type)。因此类实现了接口,就表明客户端可以对这个类的实例...

  • 第19条 接口只用于定义类型

    当类实现接口时,接口就充当可以引用这个类的实例的类型。因此,类实现了接口,就表明客户端对这个类的实例可以实施某些动...

  • 记录

    各种声明记得加类型,函数要加返回类型,也可以写成一个接口形式的返回类型。 接口用于在外定义类型包,也可以设置可选值...

  • [axios] Cancel 类实现及 axios 的扩展

    接口定义 其中 Cancel 是实例类型的接口定义,CancelStatic 是类类型的接口定义,并且我们给 ax...

  • 第22项:只使用接口来定义类型

    ITEM 22: USE INTERFACES ONLY TO DEFINE TYPES  当一个类实现一个接口时...

  • TypeScript接口

    属性类型接口 函数类型接口 定义了函数的参数。包括入参和出参。 可索引类型接口 类类型接口

  • java11(接口与多实现)

    接口: interface 用于定义接口 1 接口中常见定义:常量,抽象方法 2 接口中的...

  • Java 特殊作用的接口

    Comparable Comparable接口用于自定义比较规则。对于Java的原生类型,他们之间的大小比较是依照...

  • iOS inline 、define 、typedef 的区别

    define:定义预编译时处理的宏; 只进行简单的字符替换,无类型检测 typedef:定义类型别名 用于处理复杂...

网友评论

    本文标题:第19条 接口只用于定义类型

    本文链接:https://www.haomeiwen.com/subject/mgcbxxtx.html