Java调试器无法调用某些默认方法实现

gvl*_*sov 8 debugging interface intellij-idea java-8 default-method

我在IntelliJ IDEA中编码.在调试我的应用程序时,我无法在Watches中使用某些默认方法实现.

这是一个简洁的例子:

public class Friendship {
    interface Friend {
        default void sayHiTo(Friend friend) {
            System.out.println("Hi, " + friend.hashCode());
        }

        default int amountOfHands() {
            return 2;
        }
    }

    public static class BasicFriend implements Friend {

        int numberOfFaces() {
            return 1;
        }
    }

    public static void main(String[] args) {
        System.out.println("Put a breakpoint here");
    }
}
Run Code Online (Sandbox Code Playgroud)

main()方法中我放了一个断点并设置了三个手表:

// Default interface method with dependency
new BasicFriend().sayHiTo(new BasicFriend())

// Default interface method without dependency
new BasicFriend().amountOfHands()

// Class method
new BasicFriend().numberOfFaces()
Run Code Online (Sandbox Code Playgroud)

第一只手表投掷NoSuchMethodException抱怨该方法Friendship$BasicFriend.sayHiTo()不存在.

第二只手表成功运行,但奇怪的是它会报告一个盒装对象{java.lang.Integer@537} "2"而不仅仅是一个原始对象 2.

正如预期的那样,第三只手表报告原始1.

为什么第一只手表不工作?这是一个错误吗?这实际上与IDE有关吗?是因为默认方法的一些概念缺陷?它应该像我想要的那样起作用吗?第二只手表的奇怪结果是否与第一只手表中的问题有关?

Jef*_*oom 8

在JDK 8u40之前,JDI(Java调试器接口),JDWP(Java调试器线协议)和JDB(标准Java调试器)不支持缺省和静态接口方法.这是JDK-8042123的错误,它在8u40中被记录为固定,并且相应的blurb出现在8u40发行说明中.

更新到8u40或更高版本以解决此问题,至少在JDK方面.

从错误描述看,看起来还需要调试器端更改,以避免将com.sun.jdi.InterfaceType对象转换为com.sun.jdi.ClassType,而是直接调用InterfaceType.invokeMethod().

在IntelliJ的具体案例中,Suseika在评论证实 14.1.2主要解决了这个问题(除了意外的拳击),尽管Mike Kobit仍然在该版本上遇到这个问题,并且ClassCastException暗示了上面的错误演员.

  • @Suseika感谢您提供的信息(编辑到答案中).这似乎证实需要调试器端更改. (2认同)