我正在编写一个代码,其中一个类实现两个接口,恰好有两个具有相同名称的抽象方法,以及两个具有相同标识符的常量:
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字段,编译器就不会抱怨。当我取消注释打印语句时,它会这样做。
怎么样?这是正常的行为吗?只有在我访问这些成员时才会出错?
编辑我的意思是,当我尝试实现接口时,编译器为什么不警告我的歧义呢?
答案 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。