Основные препятствия для нестатического доступа от внутренних классов к внешним интерфейсам

Пример:

interface Outer {
    default String get() {
        return "hi";
    }
    class Inner {
        String got() {
            return get();
        }
    }
}

Это дает ошибку

java: нестатический метод get() не может ссылаться на статический контекст.

Внутренний интерфейс/класс всегда статичен; в отличие от внешнего класса, где он не статичен, если не объявлен статическим.

Вот как это происходит сегодня и в предстоящей java 8. Есть ли фундаментальная причина для этой разницы между внешними классами и внешними интерфейсами?

Обновление: После прочтения комментария @Radiodef я изменил внутренний интерфейс как внутренний класс. Внешний класс не может содержать нестатический внутренний интерфейс, поэтому пример сбивает с толку. Внутренний класс действительно то, что я хотел бы в любом случае.

Обновить. Для справки. Это совершенно законно:

class Outer {
    String get() {
        return "hei";
    }
    class Inner {
        String got() {
            return get();
        }
    }
}

Ответы

Ответ 1

Возможно, я неправильно понял ваш вопрос, но ваш фрагмент кода в точности эквивалентен

interface Outer {
    public default String get() {
        return "hi";
    }
    public static class Inner {
        String got() {
            return get();
        }
    }
}

Как главу 9.5 (Java 8) JLS утверждает

Объявление типа элемента в интерфейсе неявно public и static. Разрешено избыточно указывать один или оба из этих модификаторы.

Итак, если вы сделали

Inner innerInstance = new Outer.Inner();
innerInstance.got();

на что будет ссылаться get()? Здесь нет объекта типа Outer.

Существует ли фундаментальная причина этой разницы между внешними классы и внешние интерфейсы?

Это не проблема. Код вашего класса является примером внутренних классов, т.е. non static вложенный класс. Код интерфейса - это пример вложенного класса static. Вы сравниваете две разные вещи.

Эквивалентный пример с static вложенным классом внутри класса-оболочки будет

class Outer {
    String get() {
        return "hei";
    }

    public static class Inner {
        String got() {
            return get(); // won't compile
        }
    }
}

где снова не имеет смысла работать с get(), поскольку для его включения не существует соответствующего (охватывающего) экземпляра.


Если вопрос, как @Radiodef положил его,

почему класс должен быть неявно статическим, кроме того, что это существующая спецификация?

тогда мой ответ следующий:

Интерфейс, по определению,

Точка, в которой независимые системы или различные группы взаимодействуют

Интерфейс не имеет состояния и не имеет поведения. Он просто описывает поведение. Элементы интерфейса неявно static, потому что интерфейс не имеет состояния. С другой стороны, для типа интерфейса имеет смысл иметь состояние, т.е. static. Важно то, что это ссылочный тип, а не интерфейс.