4

Java 允许在接口中使用字段。这在 java 5 之前有一些用处。他们今天有什么好的用例吗?

有人可以给我一些很好的用例,在接口中使用字段而不是许多其他方式来满足相同的设计要求吗?

事实上,接口在某些情况下允许歧义和混乱。举个例子。以下代码:

请注意,我承认之前已经讨论过并回答了歧义问题,但这不是我的问题。我的问题在上面用粗体标出。这只是接口中字段的一个潜在副作用的说明。

public class Sample implements Foo,Bar{

    public void print() {
        System.out.println("Hello"+name);//field name is ambiguous
    }

    public static void main(String[] args) {
        Sample mySample = new Sample();
        mySample.print();
    }

}

public interface Foo {
    String name = "foo";
}

public interface Bar{
    String name = "bar";
}
4

3 回答 3

6

接口用于定义契约,常量是实现细节。如果多个实现共享一个常量是有意义的,您可以在一个抽象类中定义它,该类将用作层次结构的基类。如果只有一个类真正与常量绑定,则应在此处声明它。

如果您只想将一定数量的常量组合在一起,您可以在 final 类中定义它们:

final class Constants { //non extendable
    public static final double PI = 3.14d;
    public static final double E = 2.13d; //Can't remember the real value!

    private Constants() {} //non instantiable
}

当它们是枚举(例如颜色)时,您也可以在枚举中声明它们。

在 Effective Java Item #19 “Use interfaces only to define types”中有更多关于它的信息,它的结尾是:

总之,接口应该只用于定义类型。它们不应该用于导出常量。

归根结底,总是有比在接口中定义常量更好的方法。

于 2013-06-19T22:07:59.763 回答
5

如果有人设法为您提供了一些在接口中使用字段而不是许多其他方式来满足相同设计要求的好案例,那么它会自动证明在接口中使用常量是合理的。

事实上,这是我们多年前在 Java 的第一个版本中经常做的事情。从那时起,接口中的常量就被放弃了,取而代之的是静态导入,这也不是完美的常量类。

如 Java 文档中所述:

“那么什么时候应该使用静态导入?非常谨慎!仅在您想要声明常量的本地副本或滥用继承(常量接口反模式)时才使用它。换句话说,当您需要频繁使用它时使用它从一两个类访问静态成员。”

根据WikiPedia中的 Joshua Bloch (Bloch, Joshua, Effective Java, 2nd Edition, p. 98),以下是使用常量接口模式的缺点:

  1. 它用可能没有用的只读变量污染了类名称空间。
  2. 与实现常量接口的编译时战术实用程序相反,附带的运行时工件几乎没有实际用途(参见标记接口,它也没有方法但在运行时有用)。
  3. 如果在将来的版本中需要二进制代码兼容性,则常量接口必须永远保持为接口(它不能转换为类),即使它没有被用作传统意义上的接口。
  4. 如果没有一个 IDE 可以解析常量的来源,那么将其跟踪回其包含的类或接口可能会很耗时。
  5. 接口的变量(表示实例)在语法上并不比接口名称本身有用(因为它没有方法)。
于 2013-06-19T21:55:07.537 回答
2

在java中,Interface字段是隐式的public static final。并且它们必须在声明期间在接口内初始化。这可用于创建可以在代码中的任何位置调用的通用常量(无需实现该接口)。在 java APIjavax.swing.SwingUtilities中是只包含常量但不包含方法声明的接口。在java中,为了方便的语法访问这些常量而实现这样的接口被称为常量接口模式,这确实是一种非常糟糕的做法。

正如@assylias 所指出的,它可以被认为是enumsJava5 之前的替代品。

于 2013-06-19T21:42:09.947 回答