У меня есть follwing Java 9 модуль:Почему компиляция открытых API-интерфейсов, протекающих во внутренних типах, не работает?
module com.example.a {
exports com.example.a;
}
с типом экспортируемого:
public class Api {
public static void foo(ImplDetail args) {}
}
И неэкспортированной типа:
package com.example.b.internal;
public class ImplDetail {}
Экспортируемый тип использует Непостоянство экспортированный тип как тип параметра метода в общедоступном методе. Я бы предположил, что компилятор откажется от такой несогласованной конфигурации классов, поскольку клиенты в других модулях не могут действительно ссылаться на метод foo()
, поскольку они не могут создать экземпляр типа параметра.
К моему удивлению, этот модуль успешно скомпилирован javac. Я вижу особый случай прохождения null
, но я считаю, что такое определение API искажено и полагает, что оно не должно поддерживаться, что идеально подходит компилятору.
В чем причина отказа в таком случае?
Спасибо за подробный ответ, Стюарт! Вывод экспортированного типа из неэкспортного типа кажется мне несовместимым, поэтому я бы сказал, что один должен гарантировать ошибку компиляции (для самого Sub). Но, вероятно, у вас будет такая же проблема, которую вы описываете несколькими этапами компиляции. – Gunnar
@ Gunnar. Подумав об этом некоторое время, я понял, что разумно (если не редкость) иметь открытый класс, который является подклассом частного класса.В JDK, например, в java.lang, 'StringBuffer' и' StringBuilder' являются публичными подклассами 'AbstractStringBuilder', частного класса. Немного странно иметь иерархию SB <: ASB <: Объект с внутренним частным классом, но это сделано для совместного использования. Однако обратите внимание, что ASB не отображается как тип API. –
Спасибо за последующее наблюдение. Лично я считаю такой дизайн неудобным. Пользователь типа должен иметь возможность видеть полную иерархию типа ИМО. Если речь идет о совместном использовании, это можно сделать путем делегирования в частный общий класс. – Gunnar