本文介绍了Eclipse / javac在使用默认方法冲突编译签名时不同意;谁是对的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里有一个简单的类来演示这个问题:

  package com.mimvista.debug; 

public class DefaultCollisionTest {
public static interface Interface1 {
public String getName();
}

public static interface Interface2 {
public default String getName(){returnMr. 2; };
}

public static< X extends Interface1& Interface2> String extractName(X target){
return target.getName();






Eclipse(Neon 2)很高兴地编译这个类,而javac (JDK 1.8.0_121)吐出以下编译错误:

  $ javac src / com / mimvista / debug / DefaultCollisionTest.java 
src\com\mimvista\debug\DefaultCollisionTest.java:13:error:class INT#1从类型Interface2和Interface1继承了getName()的抽象和默认值
public static< X扩展Interface1& Interface2>字符串extractName(X目标){
^
其中INT#1是交叉类型:
INT#1扩展Object,Interface1,Interface2
1错误

我相信Eclipse在这种情况下是正确的,但我并不完全确定。根据我对继承抽象和默认错误的理解,我认为它应该只在编译实现这两个接口的实际声明类时生成。看起来像javac可能会生成一个中间类来处理这个通用签名,并将其错误地进行默认的方法碰撞测试?

解决方案
在中进行报告:



通过(见 I2> < T extends IDefault> ,但是失败并且< T extends I1& IDefault> javac

 接口I1 {
String get();
}

interface I2 {
String get();
}

interface IDefault {
default String get(){
returndefault;
};
}

public class Foo实现I1,I2,IDefault {

@Override
public String get(){
returnfoo ;


public static void main(String [] args){
System.out.print(getOf(new Foo()));
}

// static< T extends I1& IDefault> String getOf(T t){//失败,返回javac
static< T extends I1& I2> String getOf(T t){// OK
return t.get();
}

}


Here's a simple class that demonstrates the issue:

package com.mimvista.debug;

public class DefaultCollisionTest {
    public static interface Interface1 {
        public String getName();
    }

    public static interface Interface2 {
        public default String getName() { return "Mr. 2"; };
    }

    public static <X extends Interface1&Interface2> String extractName(X target) {
        return target.getName();
    }
}

Eclipse (Neon 2) happily compiles this class while javac (JDK 1.8.0_121) spits out the following compile error:

$ javac src/com/mimvista/debug/DefaultCollisionTest.java
src\com\mimvista\debug\DefaultCollisionTest.java:13: error: class INT#1 inherits abstract and default for getName() from types Interface2 and Interface1
        public static <X extends Interface1&Interface2> String extractName(X target) {
                       ^
  where INT#1 is an intersection type:
    INT#1 extends Object,Interface1,Interface2
1 error

I believe that Eclipse is correct in this case but I'm not totally sure. Based on my understanding of the "inherits abstract and default" error, I think it should only be generated when compiling an actual declared class that implements those two interfaces. It seems like javac may be generating an intermediate class under-the-hood to deal with that generic signature and erroneously subjecting it to the default method collision test?

解决方案

Eclipse is right.

I have not found this javac bug in the Java Bug Database and therefore reported it: JDK-8186643

Better explanation by Stephan Herrmann (see his comment below):

A class that implements multiple interfaces of the same method can be compiled with both compilers, even if the method of one interface has a default implementation. The class can be referenced as <T extends I1 & I2> as long as neither I1 nor I2 has a default implementation for a equally named method. Only if one of the two interfaces has a default implementation javac fails.

In case of ambiguity which implementation should apply, the error should already occur when defining a class, not when the class is referred as <T extends ...> (see JLS 4.9. Intersection Types).

See following example which works with <T extends I1 & I2> and <T extends IDefault>, but fails with <T extends I1 & IDefault> and javac:

interface I1 {
    String get();
}

interface I2 {
    String get();
}

interface IDefault {
    default String get() {
        return "default";
    };
}

public class Foo implements I1, I2, IDefault {

    @Override
    public String get() {
        return "foo";
    }

    public static void main(String[] args) {
        System.out.print(getOf(new Foo()));
    }

//  static <T extends I1 & IDefault> String getOf(T t) { // fails with javac
    static <T extends I1 & I2> String getOf(T t) { // OK
        return t.get();
    }

}

这篇关于Eclipse / javac在使用默认方法冲突编译签名时不同意;谁是对的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 23:43