今天接口中的字段有一个很好的用例吗?

时间:2013-06-19 21:30:16

标签: java interface ambiguity

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";
}

3 个答案:

答案 0 :(得分:6)

接口用于定义合同,而常量是实现细节。如果有许多实现将共享一个常量是有意义的,您可以在一个抽象类中定义它,该类将用作层次结构的基类。如果只有一个类真的与常量相关联,那么你应该在那里声明它。

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

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
}

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

有效Java项目#19“仅使用接口来定义类型”中的更多信息,最后用:

  

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

总而言之,总是有一种更好的方法来定义常量而不是界面。

答案 1 :(得分:5)

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

事实上,这是我们多年前在Java的第一个版本中所做的事情。从那以后,接口中的常量被放弃了,而不是static imports,这也不是完美的常量类。

如Java文档中所述:

  

“那么什么时候应该使用静态导入?非常谨慎!只使用它   当你否则想要声明常量的本地副本时,   或滥用继承(Constant Interface Antipattern)。其他   单词,当您需要频繁访问静态成员时使用它   一两节课。“

根据Joshua Bloch(Bloch,Joshua,Effective Java,第2版,第98页),使用恒定界面模式的缺点如WikiPedia中所示:

  
      
  1. 它使用只读变量污染类命名空间   不能使用。
  2.   
  3. 与实现a的编译时战术效用相反   常量接口,偶然的运行时工件很少   实际目的(参见标记界面,也没有方法   但在运行时很有用)。
  4.   
  5. 如果在将来的版本中需要二进制代码兼容性,那么   常量接口必须永远保持一个接口(它不能   转换成一个类),即使它没有被用作   传统意义上的界面。
  6.   
  7. 如果没有IDE可以解决常量的来源,   跟踪它回到它的包含类或接口可能是时间   耗时。
  8.   
  9. 接口的变量(表示实例)   语法上没有比接口名称本身更有用(因为   它没有方法)。
  10.   

答案 2 :(得分:2)

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

正如@assylias所指出的,它可以被视为Java5之前enums的替代。