Java 7接口和名称冲突

时间:2015-10-01 07:15:30

标签: java interface name-collision

我正在编写一个代码,其中一个类实现两个接口,恰好有两个具有相同名称的抽象方法,以及两个具有相同标识符的常量:

public class Test implements A,B {

  public void doStuff() {}

  public void make() {}

  public static void main(String[] args) {
    Test t=new Test();
    System.out.println(A.VALUE);
    System.out.println(B.VALUE);
    //System.out.println(Test.VALUE);
    //System.out.println(t.VALUE);
  }

}


interface A {              // implicitly abstract

  int VALUE=11;            // implicitly public static and final

  void doStuff();               // implicitly public and abstract

}


interface B {

  int VALUE=14;

  void make();

  void doStuff();

}

现在,我知道从Java 7开始,我不必担心名称冲突,就抽象方法而言(对吗?):我只提供一个合适的实现,我很好(所有覆盖相同名称的方法,所以我不会得到类似多重继承的问题或“钻石”(我猜想,当我进入Java 8时,我将要处理这些问题)。

但是,就常量而言,我注意到如果我实现了两个接口并且没有尝试访问VALUE字段,编译器就不会抱怨。当我取消注释打印语句时,它会这样做。

怎么样?这是正常的行为吗?只有在我访问这些成员时才会出错?

编辑我的意思是,当我尝试实现接口时,编译器为什么不警告我的歧义呢?

5 个答案:

答案 0 :(得分:1)

  

现在,我知道,就Java 7而言,我不必担心名称冲突,就抽象方法而言(对吗?)

这不是Java 7中的新功能。由于这两种方法在两个接口中具有相同的签名,因此当您在类中实现该方法时,它会为两个接口实现该方法。那里没有问题,因为没有歧义。

  

怎么样?这是正常的行为吗?只有在我访问这些成员时才会出错?

是的,当然是正常的行为;它根据Java编程语言的规则(它不是Java编译器中的错误)。只是从两个接口本身继承常量不会导致歧义,这就是为什么当你尝试这样做时不会出现错误的原因。

如果你试图在没有限定条件的情况下使用常量,那么编译器并不知道你指的是哪一个,所以它会给你一个错误。

您必须指定要使用常量的接口:

interface A {
    int VALUE = 11;
}

interface B {
    int VALUE = 14;
}

public class Example implements A, B {
    public void method() {
        // Use A.VALUE instead of just VALUE
        System.out.println(A.VALUE);
    }
}

答案 1 :(得分:1)

接口中的所有变量都是公共静态的。这就是为什么你可以从任何地方访问它们,如果你没有继承那些接口就会发生事件。

答案 2 :(得分:1)

  

我的意思是,当我尝试实现接口时,编译器为什么不警告我的歧义呢?

Java规范允许您使用相同的名称变量定义来自不同接口的继承。因此,在访问VALUE之前不会有任何歧义。 然后你尝试使用简单的名称访问它,编译器无法决定它应该使用哪个变量,只有那种情况是不明确的。 您可以在Java规范中找到详细信息 https://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html#d5e12665

引用:

  

接口可以继承多个字段   同名。这种情况本身并不会导致   编译时错误。但是,在体内的任何企图   通过简单名称引用任何此类字段的接口将导致   编译时错误,因为这样的引用是不明确的。

答案 3 :(得分:0)

虽然实现接口编译器不知道你将在哪里使用它们,但它无法警告。 考虑这种情况。有三个类继承这些接口...... “公共课测试实施A,B” “公共类Test1实现了A” “公共类Test2实现B” 在这里我们不能从任何接口跳过VALUE变量,因为它在三个类中是必需的。如果在创建接口时出错,则可能无法实现此方案。

答案 4 :(得分:0)

在你的例子中

interface A {              
  int VALUE=11;           
  void doStuff();               
}

interface B {
  int VALUE = 14;
  void make();
  void doStuff();
}

接口中定义的变量被视为公共静态最终变量。因此,静态变量是类级变量,它们可以在类中使用,并且可以通过类名本身访问。

在上面的示例中,接口A和B具有公共静态最终VALUE变量。并且A接口变量赋值为11,B接口赋值为14.

A和B接口的完整实现是类Test。

此类测试实现A,B

默认情况下,Test类中提供了所有属性和行为。但在这种情况下,VALUE变量是静态的,其余方法是实例方法。由于静态变量的范围是类级别,因此与实例变量和实例方法相比,静态变量的内存分配不同。

因此范围不同 (在课程级别) ,因此没有钻石问题的机会。代码编译精细,Out put分别为11 12。