当两个接口有冲突的 return 类型时,为什么一个方法成为默认方法?
When two interfaces have conflicting return types, why does one method become default?
在 Java 8 中,如果我有两个具有不同(但兼容)return 类型的接口,反射告诉我这两个方法之一是 default 方法,即使我实际上没有将该方法声明为默认方法或提供方法体。
例如,采用以下代码片段:
package com.company;
import java.lang.reflect.Method;
interface BarInterface {}
class Bar implements BarInterface {}
interface FooInterface {
public BarInterface getBar();
}
interface FooInterface2 extends FooInterface {
public Bar getBar();
}
class Foo implements FooInterface2 {
public Bar getBar(){
throw new UnsupportedOperationException();
}
}
public class Main {
public static void main(String[] args) {
for(Method m : FooInterface2.class.getMethods()){
System.out.println(m);
}
}
}
Java 1.8 产生以下输出:
public abstract com.company.Bar com.company.FooInterface2.getBar()
public default com.company.BarInterface com.company.FooInterface2.getBar()
这看起来很奇怪,不仅因为两种方法都存在,还因为其中一种方法突然莫名其妙地变成了默认方法。
运行 Java 7 中的相同代码会产生一些不太出乎意料的结果,尽管仍然令人困惑,因为这两种方法具有相同的签名:
public abstract com.company.Bar com.company.FooInterface2.getBar()
public abstract com.company.BarInterface com.company.FooInterface.getBar()
Java肯定不支持多个return类型,所以这个结果还是挺奇怪的。
下一个明显的想法是:"Okay, so maybe this is a special behavior that only applies to interfaces, because these methods have no implementation."
错了。
class Foo2 implements FooInterface2 {
public Bar getBar(){
throw new UnsupportedOperationException();
}
}
public class Main {
public static void main(String[] args) {
for(Method m : Foo2.class.getMethods()){
System.out.println(m);
}
}
}
产量
public com.company.Bar com.company.Foo2.getBar()
public com.company.BarInterface com.company.Foo2.getBar()
这是怎么回事?为什么 Java 将这些枚举为单独的方法,其中一种接口方法如何成为没有实现的默认方法?
这不是您提供的default
方法,而是一种桥接方法。在您定义的父接口中。
public BarInterface getBar();
并且你必须有一个可以调用的方法来实现它。
例如
FooInterface fi = new Foo();
BarInterface bi = fi.getBar(); // calls BarInterface getBar()
但是,您还需要能够调用它的协变 return 类型。
FooInterface2 fi = new Foo();
Bar bar = fi.getBar(); // calls Bar getBar()
这些是相同的方法,唯一的区别是一个调用另一个并转换 return 值。该方法似乎具有 default
实现,因为它在执行此操作的界面上。
注意:如果你有多个级别的interfaces/class并且每个级别都有不同的return类型,方法的数量会累积。
这样做的原因是 JVM 允许具有不同 return 类型的多个方法 因为 return 类型是签名的一部分。我是调用者必须说明它期望的 return 类型,而 JVM 实际上并不理解协变 return 类型。
在 Java 8 中,如果我有两个具有不同(但兼容)return 类型的接口,反射告诉我这两个方法之一是 default 方法,即使我实际上没有将该方法声明为默认方法或提供方法体。
例如,采用以下代码片段:
package com.company;
import java.lang.reflect.Method;
interface BarInterface {}
class Bar implements BarInterface {}
interface FooInterface {
public BarInterface getBar();
}
interface FooInterface2 extends FooInterface {
public Bar getBar();
}
class Foo implements FooInterface2 {
public Bar getBar(){
throw new UnsupportedOperationException();
}
}
public class Main {
public static void main(String[] args) {
for(Method m : FooInterface2.class.getMethods()){
System.out.println(m);
}
}
}
Java 1.8 产生以下输出:
public abstract com.company.Bar com.company.FooInterface2.getBar()
public default com.company.BarInterface com.company.FooInterface2.getBar()
这看起来很奇怪,不仅因为两种方法都存在,还因为其中一种方法突然莫名其妙地变成了默认方法。
运行 Java 7 中的相同代码会产生一些不太出乎意料的结果,尽管仍然令人困惑,因为这两种方法具有相同的签名:
public abstract com.company.Bar com.company.FooInterface2.getBar()
public abstract com.company.BarInterface com.company.FooInterface.getBar()
Java肯定不支持多个return类型,所以这个结果还是挺奇怪的。
下一个明显的想法是:"Okay, so maybe this is a special behavior that only applies to interfaces, because these methods have no implementation."
错了。
class Foo2 implements FooInterface2 {
public Bar getBar(){
throw new UnsupportedOperationException();
}
}
public class Main {
public static void main(String[] args) {
for(Method m : Foo2.class.getMethods()){
System.out.println(m);
}
}
}
产量
public com.company.Bar com.company.Foo2.getBar()
public com.company.BarInterface com.company.Foo2.getBar()
这是怎么回事?为什么 Java 将这些枚举为单独的方法,其中一种接口方法如何成为没有实现的默认方法?
这不是您提供的default
方法,而是一种桥接方法。在您定义的父接口中。
public BarInterface getBar();
并且你必须有一个可以调用的方法来实现它。
例如
FooInterface fi = new Foo();
BarInterface bi = fi.getBar(); // calls BarInterface getBar()
但是,您还需要能够调用它的协变 return 类型。
FooInterface2 fi = new Foo();
Bar bar = fi.getBar(); // calls Bar getBar()
这些是相同的方法,唯一的区别是一个调用另一个并转换 return 值。该方法似乎具有 default
实现,因为它在执行此操作的界面上。
注意:如果你有多个级别的interfaces/class并且每个级别都有不同的return类型,方法的数量会累积。
这样做的原因是 JVM 允许具有不同 return 类型的多个方法 因为 return 类型是签名的一部分。我是调用者必须说明它期望的 return 类型,而 JVM 实际上并不理解协变 return 类型。