Java 实例化具有默认方法的接口
我遇到了一个问题: 下面的输出是什么Java 实例化具有默认方法的接口,java,object,interface,java-8,Java,Object,Interface,Java 8,我遇到了一个问题: 下面的输出是什么 1 public class A { 2 public static void main(String[] args){ 3 I i = new I() {}; 4 System.out.println(I.x + i.getValue() + "" + i); 5 } 6 } 7 8 interface I { 9 int x = 10; 10 11 pub
1 public class A {
2 public static void main(String[] args){
3 I i = new I() {};
4 System.out.println(I.x + i.getValue() + "" + i);
5 }
6 }
7
8 interface I {
9 int x = 10;
10
11 public default int getValue() {
12 return 5;
13 }
14
15 public default String toString() {
16 return "I";
17 }
18 }
我的想法:
我的第一本能告诉我-I=newi(){}?因此,我们无法实例化接口-问题1
然后我想公共默认字符串toString()?重写对象类方法?听起来不太好-问题2
可能的答案:
a) 10I
b) 15I
c) 第11行导致编译失败
d) 第15行导致编译失败
e) 由于多个错误,编译失败
在解释了我的想法之后,我选择了错误的答案E)。正确答案是D),我也答对了
我的问题-为什么下面的陈述是有效的
I i = new I() {};
由于添加了“{}”,该语句是否正在做一些我不理解的事情?据我所知,new
关键字的意思是:实例化
我不明白是因为它加了“{}”吗
您正在实例化匿名类
I i = new I() {};
I=新I(){};创建一个实现接口I的匿名类。由于接口I没有任何要实现的抽象方法,括号{}内的匿名类主体可以为空。该语句没有任何错误:
I i = new I() {};
它只是实例化一个实现I
接口的匿名类。由于I
接口只有默认方法,如果不是因为toString()
方法的问题,空的主体就足以实现它
声明接口不能有toString()方法的默认实现:
如果默认方法与类对象的非私有方法重写等效,则这是编译时错误,因为实现接口的任何类都将继承其自己的方法实现
禁止将其中一个对象方法声明为默认方法可能令人惊讶。毕竟,在java.util.List这样的情况下,toString和equals的行为是精确定义的。然而,当理解了一些更广泛的设计决策时,动机变得更加清晰:
- 首先,允许从超类继承的方法重写从超接口继承的方法(§8.4.8.1)。因此,每个实现类都会自动覆盖接口的toString默认值。这是Java编程语言中长期存在的行为。我们不希望在默认方法的设计中改变这一点,因为这将与允许接口不受干扰地发展的目标相冲突,只在类尚未通过类层次结构时提供默认行为
- 其次,接口不从对象继承,而是隐式声明许多与对象相同的方法(§9.2)。因此,对象中声明的toString和接口中声明的toString没有共同的祖先。充其量,如果两者都是类继承的候选对象,它们就会发生冲突。解决这个问题需要笨拙地混合类和接口继承树
- 第三,在接口中声明对象方法的用例通常采用线性接口层次结构;该特性不能很好地推广到多继承场景
- 第四,对象方法非常基本,允许任意超级接口以静默方式添加更改其行为的默认方法似乎很危险
toString()
是Object
类的方法,因此在任何接口中都不能有默认实现。默认方法不能覆盖java.lang.Object
中的方法,例如toString()
第11行和第15行?使用编译器编译它并自己查看结果。好的,D
意味着你在第二期中是正确的。那么您需要了解的是,I.x
是否有效x
不是I
@marstran中的静态变量:x
是静态的
和最终的
。由于所有接口字段都是public static final
,您无需明确指定。感谢一百万个Eran的回复,现在对我来说一切都很有意义。只是为了强调答案,摘自Brian Goetz的答案“违约应该是违约。将默认值添加到没有(层次结构中的任何位置)的接口不应影响具体实现类的语义。但如果默认值可以“覆盖”对象方法,那就不是真的。”