为什么我们在Java接口中使用public static final
实例变量声明?
所有变量在Java接口中都是隐式public static final
。
在常量变量中使用public static final
是一种很好的编码实践,尽管它是在接口内声明的。
例如:
public interface TestInterface{
public static final String EX_CONSTANT = "ABC";
public static final int EX_INT_CONSTANT = 5;
public static final double EX_DOUBLE = 5.0;
public static final Integer EX_INTEGER = 10;
}
答案 0 :(得分:11)
在类和接口中使用统一语法简化了重构。
您可能希望将来将interface
转换为某个class
,或将这些字段移到一个类中,如果您忽略了一些没有{{{}的字段,您将获得语义差异。 1}}(当然,我们有重构的工具,但仍然如此)。
我认为对于在Java 6中引入的接口中声明的方法的实现支持public static final
注释是相同的 - 它在当前形式中是多余的,但在重构时可能会变得有用。
答案 1 :(得分:5)
我不这么认为。所有接口变量都是隐式公共静态最终变量,因此没有意义将它们标记为相同。
答案 2 :(得分:4)
来自JOshua Bloch的Effective java一书
第19项:仅使用界面来定义类型
当一个类实现一个接口时,该接口可以作为一种类型 用于指代类的实例。一个类实现了一个接口 因此,应该说一下客户可以用什么做的事情 类。为任何其他目的定义接口是不合适的。
一种未通过此测试的接口是所谓的常量接口。 这样的接口不包含任何方法;它仅由静态最终字段组成 导出常量。使用这些常量的类实现接口 避免使用类名限定常量名称。这是一个例子:
// Constant interface antipattern - do not use!
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;
}
常量接口模式是接口的不良使用。一个班级使用的 内部的一些常量是一个实现细节。实现常量 interface导致此实现细节泄漏到类的导出API中。它 对于类的用户而言,该类实现常量是无关紧要的 接口。事实上,它甚至可能使他们感到困惑。更糟糕的是,它代表了一种承诺:如果 在将来的版本中,类被修改,以便它不再需要使用常量, 它仍然必须实现接口以确保二进制兼容性。如果一个 非最终类实现一个常量接口,它的所有子类都有它们的 命名空间被界面中的常量污染。
Java平台库中有几个常量接口,例如 java.io.ObjectStreamConstants中。这些接口应该被视为 异常,不应该被模仿。
如果要导出常量,有几个合理的选择。如果 常量与现有类或接口紧密相关,您应该将它们添加到 类或接口。例如,所有盒装的数字原始类, 例如Integer和Double,导出MIN_VALUE和MAX_VALUE常量。如果 常量最好被视为枚举类型的成员,您应该导出 它们具有枚举类型(第30项)。否则,您应该导出常量 使用不可实例化的实用程序类(第4项)。这是一个实用程序类的版本 上面的PhysicalConstants示例:
// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
private PhysicalConstants() {
} // Prevents instantiation
public static final double AVOGADROS_NUMBER = 6.02214199e23;
public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
public static final double ELECTRON_MASS = 9.10938188e-31;
}
通常,实用程序类要求客户端使用类限定常量名称 name,例如,PhysicalConstants.AVOGADROS_NUMBER。如果你变重了 使用实用程序类导出的常量,可以避免需要进行限定 通过使用静态导入工具,具有类名的常量, 在1.5版中介绍:
// Use of static import to avoid qualifying constants
import static com.effectivejava.science.PhysicalConstants.*;
public class Test {
double atoms(double mols) {
return AVOGADROS_NUMBER * mols;
}
...
// Many more uses of PhysicalConstants justify static import
}
总之,接口应仅用于定义类型。他们不应该 用于导出常量。
答案 3 :(得分:3)
IMO,Interface是一份合同。一旦声明或定义了变量,它们就不会改变。这就是为什么我们通常会制作它们public static final
。
可读性是使声明多余的另一个因素。
答案 4 :(得分:2)
不可否认,这是多余的。通常人们只是不知道他们是隐含的public static final
并且无论如何都要声明它。与宣告:
public abstract interface Test { // Interfaces are always abstract
public void testMethod(); // Interface methods are always public
abstract void anotherTestMethod(); // Also redundant
}
通常它只是归结为这样一个事实:人们不知道他们没有 以某种方式宣布它。我曾经和某个人(他是一位经验丰富的程序员)谈过,他认为default
中的switch
案例是必需的,或者不会编译。
话虽这么说,添加它们的唯一理由是它们澄清了它们的实际可见性以及实际上的含义。这是一个可读性和澄清的问题,是否或包含它们的说明与它的实际行为无关。
答案 5 :(得分:2)
当您在程序员团队中工作时,您会发现初级程序员不知道默认情况下接口中的变量是 public static final ,并且看到变量声明了方式将为他们提供有关接口及其变量使用的额外信息。
答案 6 :(得分:1)
你是对的:这是多余的。我不喜欢随时添加冗余语法。然而,这种做法确实有其信徒。有些人还喜欢在返回表达式周围添加括号,这是因为它有点像'if'语句;额外的括号,以“澄清”三年级学生会理解的算术表达式;它是生活丰富多彩的一部分。