一文读懂《Effective Java》第19条:接口只用于定义类型

本文主要探讨Java接口的使用,指出类实现接口时,接口应充当引用类实例的类型。强调常量接口是对接口的不良使用,存在诸多弊端。同时给出合理导出常量的三种方案,总结接口应只定义类型,不用于导出常量。

点击上方蓝字关注我们!

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

接口使用误区:常量接口

常量接口模式是对接口的不良使用。

  1. 类实现常量接口,对于类的使用者没有任何价值。

  2. 后续发行版本中,如果类被修改而不需要这些常量了,但是该类必须实现这个接口,因为要确保二进制兼容性。

  3. 如果该类是final类,它的所有子类的命名空间都会被接口的常量所“污染”。

public interface PhysicalConstantsInterface {
  static final double AVOGADROS_NUMBER = 6.02214199e23;


  static final double BOLTZMANN_CONSTANT = 1.3806503e-23;


  static final double ELECTRON_MASS = 9.10938188e-31;
}

Java库其实也有反面教材,例如java.io.ObjectStreamConstants,我们不应该效仿:

/**
 * Constants written into the Object Serialization Stream.
 *
 * @author  unascribed
 * @since JDK 1.1
 */
public interface ObjectStreamConstants {


    /**
     * Magic number that is written to the stream header.
     */
    final static short STREAM_MAGIC = (short)0xaced;


    /**
     * Version number that is written to the stream header.
     */
    final static short STREAM_VERSION = 5;


    /* Each item in the stream is preceded by a tag
     */


    /**
     * First tag value.
     */
    final static byte TC_BASE = 0x70;
}

常量接口的优化方案

对于如何合理导出常量,有3种合理方案:

  • 第一、如果常量和现有类紧密相关,应该将这些常量添加到这个类中。例如:Integer 和 Double 类。

public final class Integer extends Number implements Comparable<Integer> {
    /**
     * A constant holding the minimum value an {@code int} can
     * have, -2<sup>31</sup>.
     */
    @Native public static final int   MIN_VALUE = 0x80000000;


    /**
     * A constant holding the maximum value an {@code int} can
     * have, 2<sup>31</sup>-1.
     */
    @Native public static final int   MAX_VALUE = 0x7fffffff;
}
  • 第二、如果常量被看作枚举类型的成员,那就应该使用枚举类型来导出这些常量。

  • 第三、最后一种是使用不可实例化的工具类(utility class)来导出这些常量。

public class PhysicalConstants {
  static final double AVOGADROS_NUMBER = 6.02214199e23;


  static final double BOLTZMANN_CONSTANT = 1.3806503e-23;


  static final double ELECTRON_MASS = 9.10938188e-31;
}


在jdk1.5之后,引入静态导入机制,我们可以避免使用类名来修饰常量名。

import static effectivejava.no19.PhysicalConstants.AVOGADROS_NUMBER;
public class Test {
  double atoms(double mols){
    return AVOGADROS_NUMBER * mols;
  }
}

总结

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

推荐

一文带你读懂:系统线程模型与实现原理

一文读懂《Effective Java》第54条:谨慎的使用本地方法

一文读懂《Effective Java》第53条:接口优先于反射机制

一文读懂《Effective Java》第52条:通过接口引用对象

一文读懂《Effective Java》第48条:如果需要精确答案,请避免使用float和double

一文读懂《Effective Java》第42条:慎用可变参数

一文读懂《Effective Java》第41条:慎用重载

一文读懂《Effective Java》第23条:不要在新代码中使用原生态类型

一文读懂《Effective Java》第7条:避免使用终结方法

一文读懂《Effective Java》第3条:用私有构造器或者枚举类型强化Singleton属性

—END—

扫描二维码

获取技术干货

后台技术汇

点个“在看”表示朕

已阅

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后台技术汇

对你的帮助,是对我的最好鼓励。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值