Default and Static Interface Methods

Java 8 introduces default and static interface methods.

Here's an example Java 8 interface:

public interface Foo {

default void m1() {

System.out.println("Hello from default interface method");

}

static void m2() {

System.out.println("Hello from static interface method");

}

}

When this interface is compiled by ikvmc, it produces the approximate equivalent of the following pseudo C# code:

public interface Foo {

public static class __DefaultMethods {

public static void m1(Foo obj) {

if (obj == null) throw new NullReferenceException();

Foo.<default>m1(obj);

}

}

public static class __Methods {

public static void m2() {

Foo.m2();

}

}

public static void <default>m1(Foo obj) {

System.out.println("Hello from default interface method");

}

public abstract void m1();

public static void m2() {

System.out.println("Hello from static interface method");

}

}

There are a number of things going on here, so let's go over them one by one.

__DefaultMethods

This nested type exists to allow C# code to call the default method implemenation. So when your C# class implements the Foo interface, it may implement the m1 method by calling the default method. The reason it is a nested type is to avoid method name clashes and because the current C# compiler doesn't allow access to static interface members.

__Methods

This only exists because the current C# compiler doesn't allow access to static interface members (the new Roslyn C# compiler does). It is similar to the nested __Fields type that already exists to expose interface fields.

<default>m1

This is a static method that contains the body of the default interface method. Its name is mangled to avoid conflict with the "real" abstract method. Internally ikvmc calls this method when a class inherits the default method.

m1

Regular abstract interface method.

m2

Regular static method.

The result of this implementation choice is that it can be quite painful to implement a Java 8 interface in C#, because you manually have to forward each default method.

Given the large number of default methods introduced in Java 8 this is going to make interop quite a bit more inconvenient. A partial workaround for this is to write more interop code in Java or create a Java base class that implements the interface so that it can inherit the default methods and then write the implementation as a C# subclass.

I'm considering changing ikvmc to automatically generate a __BaseClass nested type inside all public interfaces to at least make it easy to write a class that implements a single Java interface.

JVM interfaces can also have private methods. The current C# compiler doesn't like interfaces with non-public members, so the private methods are put into another nested type by ikvmc (and instance methods are compiled as static methods).